Author SHA1 Message Date
ptitSeb d698861478 Bumped to v0.3.0 2023-03-10 17:09:12 +01:00
wannacu be02c88792 Fix some wrapping error (#777) 2023-03-09 08:52:18 +01:00
wannacu 99059ffb19 Fix some errors (#776)
* Fix some wrapping error

* Fix multithreading error
2023-03-08 12:17:54 +01:00
ptitSeb a4752afacf [DYNAREC] Added BOX86_DYNAREC_FORWARD parameter, with a default value to 128 (unfortunatly, it doesn't seems to help performances much on box86) 2023-03-07 22:02:59 +01:00
ptitSeb a320c37681 Removed ONCE optim in gtkclass (fixed regression on Kega-Fusion) 2023-03-07 13:15:30 +01:00
ptitSeb 42a9a40ac4 Added some special case to the CPU Name grabbing 2023-03-06 18:39:32 +01:00
ptitSeb 6320a07d17 Fixed cpu name extraction for big.LITTLE configurations 2023-03-06 14:33:20 +01:00
ptitSeb 5e251cf478 [CI] Ubuntu 18 is deprecated, moved to 20 2023-03-06 14:24:53 +01:00
ptitSeb 355a2fa8e5 [DYNAREC] Put box86 dynarec and cpu info on the same line 2023-03-06 14:19:06 +01:00
ptitSeb 78ed9d07f2 Change branding of Cpu to refect Box86 and the cpu it's running on 2023-03-06 14:10:10 +01:00
ptitSeb 8c38d5dd36 Forcing BAD_SIGNAL for RK3588 config 2023-03-06 10:40:58 +01:00
wannacu f682ca6bf0 Fix some wrapping error (#771) 2023-03-06 10:07:59 +01:00
ptitSeb 70a2a2dd1b Made the Signal workaround more generic, so it can be used by Termux user 2023-03-05 20:58:33 +01:00
ptitSeb 3678f44945 [README] Fixed the Steam section according the latest Valve changes 2023-03-05 20:48:33 +01:00
ptitSeb 5bb473158b Added wrapped libibus and a few other libgtk fixed 2023-03-04 13:09:38 +01:00
ptitSeb 3f549749c1 Improved install_steam script a bit 2023-03-04 13:08:18 +01:00
ptitSeb 11535dabe0 [RK3588] fixed build 2023-02-26 09:51:00 +01:00
ptitSeb 1c2d36f98a [RK3588] Added a Signal workaround specific to RK3588 (because of old/hacked Kernel) 2023-02-26 09:49:36 +01:00
ptitSeb 8563ba8b70 Forgot an essencial part in RK3588 and generic ARM64 compile profile 2023-02-24 18:08:31 +01:00
ptitSeb 4b43da2081 Added RK3588 and generic ARM64 compile profile 2023-02-24 18:02:29 +01:00
ptitSeb 49c650781f [TRACE] Fixed a regression on BOX86_TRACE that was not working as intended 2023-02-22 20:36:27 +01:00
ptitSeb 36e5bf731c [D3DADAPTER9] Added support for CreateDeviceEx 2023-02-22 14:59:34 +01:00
ptitSeb f4d4116590 libssl depends on libcrypto 2023-02-22 14:37:37 +01:00
ptitSeb 11281589e0 Some fixes for program using __sprintf_chk and __vsnprintf_chk 2023-02-22 14:37:13 +01:00
ptitSeb 756811a901 [DYNAREC] Small optim on F3 0F 70 opcode 2023-02-22 14:36:18 +01:00
ptitSeb dd405c7c49 Added some more wrapped functions to gstreamer and gsttag 2023-02-19 15:13:15 +01:00
ptitSeb 20237019e4 Improved convertion to/from 80bits double, and added BOX86_X87_NO80BITS to not handle them 2023-02-19 14:51:54 +01:00
ptitSeb 7682cdce57 [DYNAREC] Small improvment in jmp/ret 2023-02-15 10:50:26 +01:00
ptitSeb 1dcac1b868 Added 64 87 opcode 2023-02-14 18:24:13 +01:00
ptitSeb 5f0add0e82 [DYNAREC] Don't forget to Cancel the block itself before bailling out of a failled FillBlock 2023-02-14 14:58:02 +01:00
ptitSeb 8f2ef48e25 Merge pull request #758 from rajdakin/master
Bug and warning fixes
2023-02-13 18:05:05 +01:00
rajdakin 4f98f568a7 Fixed the getline return type in libc 2023-02-13 17:52:17 +01:00
rajdakin 0e0e346e45 Fixed nearly all GCC warnings (-Wall -Wextra) 2023-02-13 14:56:28 +01:00
rajdakin 4388092f11 Fixed some copy-paste issues and save_fpreg/load_fpreg 2023-02-13 14:55:59 +01:00
ptitSeb b83c693192 Fixed a small issue on previous commit 2023-02-13 13:24:41 +01:00
ptitSeb 9de1bd884f Fixed another minor warnings 2023-02-13 10:20:36 +01:00
ptitSeb 1b462b8200 Fixed some minor warnings 2023-02-13 10:14:22 +01:00
ptitSeb d7c75be001 Various small (or less small) fixes 2023-02-12 19:16:54 +01:00
ptitSeb 957fcc2449 Fix non-dynarec builds 2023-02-12 17:52:05 +01:00
ptitSeb 328794e4d6 Fixed wrapped fcnt syscall 2023-02-12 17:15:03 +01:00
ptitSeb af519f6046 Small improvment for emu thread tracking (will help #728) 2023-02-12 17:05:27 +01:00
ptitSeb fa9a059921 [DYNAREC] Create empty block instead of NULL for blocks in forbidden zone (to not try to create a block again) 2023-02-12 16:46:05 +01:00
ptitSeb 771d65dc10 [DYNAREC] Better handling of Signal while Fillblock is running 2023-02-12 16:45:08 +01:00
ptitSeb 1dc92c216f [TRACE] Fixed printing of details of pthread_mutex_lock call in LOG=2 2023-02-12 16:41:27 +01:00
ptitSeb db4ff551cc [DYNAREC] Remove a debug leftover 2023-02-12 12:04:58 +01:00
ptitSeb 7abb9a1893 [DYNAREC] Better way to not UpdateFlags when only X_PEND is used 2023-02-12 11:52:06 +01:00
ptitSeb 60f987ff90 [DYNAREC] Use Dynarec in signal if it seems safe (no SIGSEGV and no dynarec mutex) 2023-02-11 21:53:39 +01:00
ptitSeb f38d122b67 [DYNARCE] Free dynablocklists when possible 2023-02-11 21:52:33 +01:00
ptitSeb a654193f1d Added some more function to wrapped libgcrypt.so 2023-02-11 20:06:47 +01:00
ptitSeb 632a01dbe6 [DYNAREC] Use custom mutex, and improved atomic handling 2023-02-11 17:19:05 +01:00
ptitSeb ae2e3aed0f [DYNAREC] Don't UpdateFlags if only X_PEND is used 2023-02-11 17:04:20 +01:00
ptitSeb 244b273250 Added RPI3ARM64 config in CMakeFile project (and fixed COMPILE.md about it) 2023-02-10 15:11:29 +01:00
ptitSeb 27756113ef Added ODROID N2/N2+ Compile instructions (for #755) 2023-02-03 16:27:35 +01:00
ptitSeb d550293ccc Added wrapped libXpresent.so.1 (backported from box64) 2023-01-29 22:27:42 +01:00
ptitSeb 74bb2e84f2 More work on vulkan wrapper 2023-01-29 22:27:42 +01:00
ptitSeb 09d2b067b5 Added some more vulkan structure alignment hint 2023-01-29 22:27:42 +01:00
ptitSeb 6d7f901167 Fixed test on i386 platforms 2023-01-29 19:12:10 +01:00
ptitSeb bdc839ef87 More work on sse opcode and testing ([DYNAREC] too) 2023-01-29 18:39:30 +01:00
ptitSeb 52f7e89fdb A few more improvment to SSE convert to int functions and tests 2023-01-29 17:12:08 +01:00
ptitSeb 6a2b45ec5c [DYNAREC] Small optim on x87 convert to int opcodes 2023-01-29 17:11:44 +01:00
ptitSeb ac0fd0278b More precise flost/double -> int SSE conversion 2023-01-29 16:42:23 +01:00
ptitSeb db06cec325 Improved precision for SSE rounding ([DYNAREC] too, with BOX86_DYNAREC_FASTROUND to control it) 2023-01-29 15:40:48 +01:00
ptitSeb d93e7f92f2 [DYNAREC] Improved Strong Memory Model emulation 2023-01-29 10:59:52 +01:00
ptitSeb d8e94908ff Added a couple of extension to libGL wrapper 2023-01-29 10:50:49 +01:00
ptitSeb 8e9d31e670 Improved wrapping of VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO structure for wrapped Vulkan 2023-01-29 10:47:24 +01:00
ptitSeb 6ed7bbdb21 Fix regression on readdir wrapped function (fixes unreal / ut99 not loading) 2023-01-29 10:46:39 +01:00
ptitSeb 8338ebaa46 [RCFILE] Disable the BOX86_PREFER_EMULATED for hl2_linux, the emulated sdl2 seems to have mouse issue with current box86 2023-01-28 11:35:03 +01:00
ptitSeb d4c08eb083 [DYNAREC] Fixed 65 D1 /2 and /3 opcodes (might help #425) 2023-01-28 11:30:40 +01:00
ptitSeb c62dc24155 Merge pull request #756 from q4a/dont-starve
[BOX86RC] add EMULATED_LIBS for dontstarve_steam
2023-01-28 10:18:48 +01:00
Aleksey Komarov f8e2b81160 [BOX86RC] add EMULATED_LIBS for dontstarve_steam
Works with steam versions of Don't Starve and Don't Starve Together
2023-01-28 12:06:44 +03:00
ptitSeb 06b38df650 [RCFILE] Added BOX86_LD_PRELOAD handling 2023-01-28 09:38:18 +01:00
ptitSeb 00e6ed3feb Added commented code, it works better wihtout it but keeping it for reference (linked to #753) 2023-01-23 13:50:23 +01:00
ptitSeb 6ffbacd808 Try to improve tls hadnling(for some old java distrib for #753) 2023-01-23 13:49:34 +01:00
ptitSeb 8e88ca6985 Added some more wrapped function to libfontconfig and libxcb (for #755) 2023-01-23 10:57:32 +01:00
ptitSeb ada65fc0da Added 1 more libx11 wrapped function (for #751) 2023-01-22 15:47:44 +01:00
ptitSeb 52002ebc64 Added some workaround for spr_readdir.so lib so it can redirect readdir and friends (for #751) 2023-01-21 13:30:07 +01:00
ptitSeb a3e25e32a4 More deitalled trace for LOG=2 for XDrawImageString function 2023-01-21 13:29:18 +01:00
ptitSeb 8aedf8957e Fixed some issue with readdir and some wrapped libc function (help #751) 2023-01-19 14:37:21 +01:00
ptitSeb db7924e26a Added a few more wrapped libX11 functions (for #751) 2023-01-19 13:55:16 +01:00
ptitSeb 2b2478381a [DYNAREC] Another attempt to force defered flags on FF/4 JMP (for #742) 2023-01-03 13:49:34 +01:00
ptitSeb 59b1e323f7 Fixed some more warning on wrapped libnm, libmimalloc and libtbbmalloc 2023-01-03 12:12:19 +01:00
ptitSeb 31e7957362 Fixed some wrapped libsdl1 warning 2023-01-03 12:08:16 +01:00
ptitSeb 917a9ba11f Fixed some wrapped libx11 warning 2023-01-03 12:07:55 +01:00
ptitSeb 71f6654062 [DYNAREC] Fixed a warning with custommem handling 2023-01-03 12:07:30 +01:00
ptitSeb 5b1670390a Added F2 0F 7D opcode (for #744) 2023-01-03 12:07:03 +01:00
ptitSeb f4999d71f3 [DYNAREC] Try to fix some FF/4 JMP opcode are not propagating proper defered flags need (for #742) 2023-01-03 12:06:14 +01:00
ptitSeb 64f52cb1b9 Added a wrapped function libxi (fixed a crash at steam big picture exit) 2022-12-28 10:50:20 +01:00
ptitSeb 905780e47d Added experimental BOX86_SSE_FLUSHTO0 env. var. 2022-12-28 09:53:50 +01:00
ptitSeb 6f176bceae [DYNAREC] Fixed call_rd helper function, and some optimization to x87/mmx flag handling (helps #740) 2022-12-28 09:49:51 +01:00
ptitSeb 21a8e20b94 Improved BOX86_NODYNAREC handling 2022-12-26 17:22:08 +01:00
ptitSeb 20b2b083f5 Added a few more wrapped function to libm and libgnutls 2022-12-26 10:14:22 +01:00
ptitSeb bfeedef03b [PYRA] Added mojo install hack to PYRA profile too 2022-12-25 16:05:06 +01:00
ptitSeb d42767414d Removed some trace to get bash working fine again 2022-12-25 15:50:31 +01:00
ptitSeb c83f21cc38 Merge pull request #738 from ye-yeshun/master
Add some instructions.
2022-12-22 08:38:09 +01:00
YeshunYe f1ce0668f8 Remove redundant code.
Signed-off-by: YeshunYe <[email protected]>
2022-12-22 14:48:06 +08:00
YeshunYe 20e6869e53 add: 0f1c as NOP instruction.
Signed-off-by: YeshunYe <[email protected]>
2022-12-22 14:48:06 +08:00
YeshunYe 75a3fb0d89 add: 0f1d as NOP instruction.
Signed-off-by: YeshunYe <[email protected]>
2022-12-22 14:48:06 +08:00
YeshunYe 0145c5bb34 add: 0f1e as NOP instruction.
Signed-off-by: YeshunYe <[email protected]>
2022-12-22 14:48:05 +08:00
YeshunYe 8e3d0835a2 add: 0f19 as NOP instruction.
Signed-off-by: YeshunYe <[email protected]>
2022-12-22 14:48:05 +08:00
YeshunYe 9fe432ac60 add: 'into' instruction.
Signed-off-by: YeshunYe <[email protected]>
2022-12-22 14:48:05 +08:00
ptitSeb 5e46f8825b Merge pull request #737 from ChisBread/master
Ignore steam dbus warning
2022-12-20 10:14:42 +01:00
ChisBread 359ba4836d Ignore steam dbus warning 2022-12-20 08:44:57 +00:00
ptitSeb fe57003477 Added strange F3 64 F1 opcode (fixed Login screen for DONTFORGET) 2022-12-19 11:40:27 +01:00
ptitSeb 067eb6d7da Fixed a warning 2022-12-18 15:54:49 +01:00
ptitSeb 69ec807d56 Of course Android doesn't have dladdr1 2022-12-18 11:20:25 +01:00
ptitSeb 8462b62c0b Improved handling of dladdr/dladdr1 with wrapped symbol (help NWN movie conversion tool) 2022-12-18 11:06:10 +01:00
ptitSeb 3313d7a158 Added init of lib n PltResolver 2022-12-17 15:54:45 +01:00
ptitSeb 47581ddb50 Added more wrapped function to libgnutls (should helps #732) 2022-12-14 11:43:46 +01:00
ptitSeb ccf1249b24 Added 1 wrapped function to libgnutls (should helps #732) 2022-12-13 23:05:21 +01:00
ptitSeb ebab21f211 Merge pull request #733 from ryanfortner/master
update debian pkg changelog for 0.2.8 release
2022-12-12 18:49:56 +01:00
Ryan Fortner 0de956191b update debian pkg changelog for 0.2.8 release 2022-12-12 12:42:22 -05:00
ptitSeb 1e648aa3d6 Reworked Local/TLS Relocation (helps #641) 2022-12-11 16:46:01 +01:00
ptitSeb 89e5517961 Added hndling of # and z modifier for printf fmt alignment (fixes graphical issues of Borderland 2 / Borderland PreSequel, probably other stuff too) 2022-12-11 12:52:33 +01:00
ptitSeb a4cfa477d6 [RCFILE] Small improvement to BOX86_ROLLING_LOG handling 2022-12-11 12:41:29 +01:00
ptitSeb 66d5fa5ef8 [TRACE] Various small improvment to LOG=2/ROLLING_LOG 2022-12-11 12:40:50 +01:00
ptitSeb cb09b0978a [DYNAREC] Added some precise rounding to 2 SSE opcodes 2022-12-03 16:32:04 +01:00
ptitSeb dbd5e1b565 [RCFILE] Fixed String reading 2022-12-03 14:28:26 +01:00
ptitSeb 66ef165184 Use DynaCall instead of EmuCall for pthread_once callback (speedup some init code= 2022-12-03 13:21:41 +01:00
ptitSeb f92b5851d0 [DYNAREC] Fixed updateProtection 2022-12-03 13:21:09 +01:00
ptitSeb 36b62b9464 [DYNAREC] This was UB on armv7 doc (store re to same reg address with pre-index), so use alternate code for everyone 2022-12-03 10:04:04 +01:00
ptitSeb d867acd295 [BOX86RC] Added some more optimized profiles 2022-12-02 23:56:57 +01:00
ptitSeb f0d525ddcc Fixed a vulkan wrapped function that was not returning it's result 2022-12-02 22:42:22 +01:00
ptitSeb f82ea51a2b [PANDORA] Fix build on CI for Pandora 2022-12-02 22:42:01 +01:00
ptitSeb 1be3d617c7 [DYNAREC] Reworked memory protection tracking, improving stability of JIT+multi-threading programs 2022-12-02 20:06:32 +01:00
ptitSeb 8bc26298a0 [DYNAREC] Protect memory even if MAP_FIXED_NOREPLACE flags was not repected 2022-12-02 18:55:58 +01:00
ptitSeb e6cf41c381 Ignore error relocating data_start, __data_start or __gmon_start__ symbols with R_386_32 type 2022-12-02 18:45:26 +01:00
ptitSeb 657f19d357 Fixed handing of special case BOX86_ROLLING_LOG=1 in rcfile 2022-12-02 14:22:32 +01:00
ptitSeb e681acaf36 Fixed handing of BOX86_ROLLING_LOG in rcfile 2022-12-02 14:18:44 +01:00
ptitSeb 5142245b1f [DYNAREC] Added BOX64_DYNAREC_BLEEDING_EDGE to control detection of MonoBleedingEdge 2022-12-02 11:41:45 +01:00
ptitSeb 6a49000bc5 [DYNAREC] More control over HotPage handling with BOX86_DYNARC_HOTPAGE 2022-12-02 11:19:00 +01:00
ptitSeb 8d06a36508 Added 3 function to wrapped libpng16 2022-12-02 10:46:42 +01:00
ptitSeb f120154675 Merge pull request #729 from Jai-JAP/patch-1
Fix typos in README.md
2022-12-01 14:45:18 +01:00
Jai A P ef84c8a635 Update README.md 2022-12-01 19:05:17 +05:30
ptitSeb 33a2716c43 [DYNAREC] Added HotPage handling (help C# and other JIT/Dynarec program) 2022-12-01 11:56:53 +01:00
ptitSeb 3fcdee46b9 Added hl_linux to box86.box86rc 2022-11-29 18:49:40 +01:00
ptitSeb 8b28872b0e Fixed wrapping of mallinfo (this fixes Garry's Mod missing UI) 2022-11-28 21:32:07 +01:00
ptitSeb 29158238bc Fixed 2 logs when applay trace setting from RCFiles 2022-11-28 19:04:41 +01:00
ptitSeb a0191247b9 Fixed an issue when an entry is found 2 times in RCFiles 2022-11-28 18:36:55 +01:00
ptitSeb f07af5825c Fixed Dynarec non-trace build 2022-11-27 19:06:07 +01:00
ptitSeb fcc5528d77 Added 1 more structure aligment info on vulkan 2022-11-27 18:53:08 +01:00
ptitSeb ab13305bc0 Added box86rc configuration file handling 2022-11-27 18:50:58 +01:00
ptitSeb 61075afbb9 Update release.yml 2022-11-27 10:18:48 +01:00
ptitSeb b4ee108c9c Fixed an issue with grabNCpu function, as getline might use realloc, don't use alloca to allocate initial line (for #728) 2022-11-27 09:42:45 +01:00
ptitSeb e31348b6d5 [DYNAREC] Refactored Strong Memory Model emulation 2022-11-26 20:04:43 +01:00
ptitSeb d76efc849f Merge pull request #727 from Itai-Nelken/patch-1
Docs: Add note about installing the correct package from my apt repo on arm64.
2022-11-24 17:13:35 +01:00
ptitSeb 76700c1dab Fixed alignment issue for pa_sink_info (fixes Steam) (for #726) 2022-11-24 17:11:05 +01:00
ptitSeb 3f58046288 Small trace improvment for new x86emu_t structure 2022-11-24 17:09:36 +01:00
ptitSeb 069f488f7b Small optim on bridge brick creation (no need to get an x86emu_t structure) 2022-11-24 17:09:03 +01:00
Itai Nelken 320977d84a Update COMPILE.md 2022-11-24 17:09:24 +02:00
ptitSeb 2e7af32cd9 Improve (non-libc) syscall 2022-11-24 13:56:52 +01:00
ptitSeb c10c86e1d4 Simplified alignment of epoll_event structure 2022-11-23 18:29:39 +01:00
ptitSeb a4bf1d2c72 Improve stack management on signal handler 2022-11-23 18:26:44 +01:00
ptitSeb b3d45c348d Added wrapped libcairoobject-2 and a bunch of other gtk related wrapped functions 2022-11-23 18:24:14 +01:00
ptitSeb a4ce2bd549 Start of a new Dev. cycle 2022-11-22 14:00:32 +01:00
ptitSeb 891593c1c9 Bumped to version v0.2.8 2022-11-17 14:19:34 +01:00
ptitSeb b43e4acc3e Merge pull request #722 from liuli0217/master
Add MOV GS:od, AL
2022-11-16 08:10:14 +01:00
刘莉 9cbc531502 Add MOV GS:od, AL
test11 contains the instruction.
2022-11-16 08:51:12 +08:00
ptitSeb 41c9d92593 Improved BOX86_ROLLING_LOG (backported from box64) 2022-11-15 18:12:11 +01:00
ptitSeb c2a782839d Added one more GLES extension to wrapped libGL 2022-11-15 16:48:23 +01:00
ptitSeb e7653bdda8 Added 1 wrapped function to libcrypto 2022-11-15 16:45:14 +01:00
ptitSeb 00a2b44be3 [DYNAREC] Force BOX86_DYNAREC_STRONGMEM=2 when detecting steam 2022-11-15 12:56:34 +01:00
ptitSeb bb2d5d43cd Added 1 wrapped function to libX11 2022-11-15 12:54:24 +01:00
ptitSeb 97aae9521b Added 1 extension to wrapped libGL 2022-11-15 12:54:07 +01:00
ptitSeb 9f2745ad53 Set TLS size to be a 64K page on all cases 2022-11-15 10:29:03 +01:00
ptitSeb ec4783bb6f Added some synonym for libpango-1 and libcairo 2022-11-15 10:28:43 +01:00
ptitSeb 5760c04de4 [DYNAREC] Fixed alternate address not always taken into account by Dynarec 2022-11-15 10:27:59 +01:00
ptitSeb 4250c61e0f Added a bunch of libGL and libGLES2 extensions 2022-11-15 00:27:15 +01:00
ptitSeb c16317850a Small fix in internal findBlockHinted function 2022-11-14 13:11:59 +01:00
ptitSeb 3d325747a5 Added one more Vulkan extension 2022-11-14 09:40:05 +01:00
ptitSeb 21abac8b06 Added 1 function to wrapped libsdl2 2022-11-14 09:39:52 +01:00
ptitSeb 89f05a35e3 [DYNAREC] Fixed some internal structure size 2022-11-14 09:39:31 +01:00
ptitSeb 116e700248 Merge pull request #721 from liuli0217/master
Modify sizeof(instsize_t) to 1 byte
2022-11-14 08:13:24 +01:00
liuli db3a80b089 Modify sizeof(instsize_t) to 1 byte
instsize_t uses 1 byte acturlly, while alloced 4 bytes before.
2022-11-14 11:05:07 +08:00
ptitSeb 09b234e719 More work on vulkan wrapping, with vulkan 1.3 support (now dxvk 2.0 works) 2022-11-12 22:31:01 +01:00
ptitSeb 5f0ca6f03e Also use size when selecting symbol for R_386_COPY and R_386_GLOB_DAT relocations 2022-11-12 17:29:48 +01:00
ptitSeb bf3da2d1b5 Removed debug left-over on a vulkan wrapped function 2022-11-12 11:36:39 +01:00
235 changed files with 8830 additions and 2172 deletions

No files matched your search

+6 -6
View File
@@ -34,21 +34,21 @@ jobs:
include:
- platform: TEGRAX1
type: Release
os: ubuntu-18.04
os: ubuntu-20.04
- platform: TEGRAX1
type: Trace
os: ubuntu-18.04
os: ubuntu-20.04
- platform: TEGRAX1ARM32
type: Release
os: ubuntu-18.04
os: ubuntu-20.04
- platform: TEGRAX1ARM32
type: Trace
os: ubuntu-18.04
os: ubuntu-20.04
runs-on: ${{ matrix.os }}
steps:
- name: "Checkout Box86 Repository"
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: "Environment preparation"
run: |
@@ -111,7 +111,7 @@ jobs:
ctest -j$(nproc)
- name: "Upload Artifact"
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: box86-${{ matrix.platform }}-${{ matrix.type }}
path: build/box86
+2 -1
View File
@@ -5,4 +5,5 @@ build*/
src/git_head.h
backup/
box86_update.sh
restore_backup.sh
restore_backup.sh
.cache
+41 -3
View File
@@ -5,10 +5,12 @@ option(PYRA "Set to ON if targeting an OpenPandora device" ${PYRA})
option(RPI2 "Set to ON if targeting an RaspberryPI2 device" ${RPI2})
option(RPI3 "Set to ON if targeting an RaspberryPI3 device" ${RPI3})
option(RPI4 "Set to ON if targeting an RaspberryPI4 device" ${RPI4})
option(RPI3ARM64 "Set to ON if targeting an RaspberryPI3 device with multiarch arm64 and armhf" ${RPI3ARM64})
option(RPI4ARM64 "Set to ON if targeting an RaspberryPI4 device with multiarch arm64 and armhf" ${RPI4ARM64})
option(GOA_CLONE "Set to ON if targeting GO Advance clones, like RG351p/v, Gameforce Chi, RGB10..." ${GOA_CLONE})
option(RK3288 "Set to ON if targeting an Rockchip RK3288 based device" ${RK3288})
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
option(RK3588 "Set to ON if targeting an Rockchip RK3588 / RK3588S based device" ${RK3588})
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})
@@ -18,6 +20,8 @@ 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(ARM64 "Set to ON if targeting a generic ARM64 based device" ${ARM64})
option(BAD_SIGNAL "Set to ON to activate the workaround for incoherent si_info on SIGSEGV" ${BAD_SIGNAL})
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})
@@ -25,10 +29,13 @@ option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${
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 TEGRAX1 OR TEGRAX1ARM32 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64 OR LX2160A)
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 RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64 OR LX2160A OR ARM64 OR RK3588)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
if(RK3588)
set(BAD_SIGNAL ON CACHE BOOL "")
endif()
endif()
if(ANDROID)
set(NOLOADADDR ON CACHE BOOL "")
@@ -61,7 +68,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 TEGRAX1 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64 OR LX2160A))
if(_aarch64 AND (RK3399 OR ODROIDN2 OR TEGRAX1 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64 OR LX2160A OR RK3588 OR ARM64))
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)
@@ -81,6 +88,7 @@ endif()
if(PANDORA)
add_definitions(-DPANDORA)
#add_definitions(-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize -fsingle-precision-constant -ffast-math)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp")
elseif(GAMESHELL)
add_definitions(-DGAMESHELL)
add_definitions(-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
@@ -104,6 +112,11 @@ elseif(RPI4)
add_definitions(-DRPI4)
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(RPI3ARM64)
add_definitions(-DRPI)
add_definitions(-DRPI3ARM64)
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(RPI4ARM64)
add_definitions(-DRPI)
add_definitions(-DRPI4ARM64)
@@ -133,6 +146,15 @@ elseif(RK3399)
add_definitions(-DRK3399)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(RK3588)
add_definitions(-DRK3588)
add_definitions(-pipe -mcpu=cortex-a76.cortex-a55+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
add_definitions(-DBAD_SIGNAL)
set(CMAKE_ASM_FLAGS "-pipe -mcpu=cortex-a76.cortex-a55+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(ARM64)
add_definitions(-DARM64)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(ODROIDN2)
add_definitions(-DODROIDN2)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a73.cortex-a53+crypto -mfpu=crypto-neon-fp-armv8 -mfloat-abi=hard)
@@ -160,6 +182,10 @@ elseif(ARM_DYNAREC)
set(CMAKE_ASM_FLAGS "-pipe -march=armv7-a+simd -mfpu=neon")
endif()
if(BAD_SIGNAL)
add_definitions(-DBAD_SIGNAL)
endif()
if(POWER9)
add_definitions(-mcpu=power9 -mtune=power9)
endif()
@@ -260,6 +286,7 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/tools/box86stack.c"
"${BOX86_ROOT}/src/tools/my_cpuid.c"
"${BOX86_ROOT}/src/tools/gtkclass.c"
"${BOX86_ROOT}/src/tools/rcfile.c"
"${BOX86_ROOT}/src/tools/wine_tools.c"
"${BOX86_ROOT}/src/elfs/elfloader.c"
"${BOX86_ROOT}/src/elfs/elfparser.c"
@@ -327,6 +354,7 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedpng16.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxxf86vm.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxrandr.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxpresent.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxext.c"
"${BOX86_ROOT}/src/wrapped/wrappedxinerama.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxfixes.c"
@@ -408,6 +436,7 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedgsttag.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstbase.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstapp.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibibus.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenugtk.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenuglib.c"
"${BOX86_ROOT}/src/wrapped/wrappedappindicator.c"
@@ -418,6 +447,7 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedpangocairo.c"
"${BOX86_ROOT}/src/wrapped/wrappedgthread2.c"
"${BOX86_ROOT}/src/wrapped/wrappedcairo.c"
"${BOX86_ROOT}/src/wrapped/wrappedcairogobject.c"
"${BOX86_ROOT}/src/wrapped/wrappedpango.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusglib1.c"
"${BOX86_ROOT}/src/wrapped/wrappedgudev1.c"
@@ -655,6 +685,7 @@ if(NOT _x86 AND NOT _x86_64)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.box86rc DESTINATION /etc/)
endif()
if(NOT TARGET uninstall)
@@ -784,7 +815,7 @@ add_test(NAME sse COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/$
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(sse PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0")
set_tests_properties(sse PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0;BOX86_DYNAREC_FASTROUND=0")
add_test(NAME longjumpInSignals COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test18 -D TEST_OUTPUT=tmpfile18.txt
@@ -810,4 +841,11 @@ foreach(file ${extension_tests})
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
endforeach()
add_test(NAME sse_optimized COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17_o2 -D TEST_OUTPUT=tmpfile17_o2.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17_o2.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(sse_optimized PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0;BOX86_DYNAREC_FASTROUND=0")
endif(BOX86LIB)
+61
View File
@@ -1,3 +1,64 @@
box86 (0.3.0) unstable; urgency=low
* Added rcfile handling: box86 now read "/etc/box86.box86rc" and "~/.box86rc" and apply per process parameters
* Added BOX86_DYNAREC_FORWARD to allow bigger Dynarec block to be build
* Refactored Strong Memory Model emulation (faster and more accurate)
* Box86 now return a custom name for the CPU instal of P4, build with Box86 and the cpu name it's running on
* Improved memory protection tracking and signal handling, again
* More wrapped libs (especially on the gtk familly)
* More wrapped functions
* Added support for CreateDeviceEx in d3dadapter9, for better gallium nine support
* Improved dladdr/dladdr1 wrapped function
* Some fixes to flags handling in the Dynarec on some special cases
* Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel)
* Lots of improvment in the Rounding of float & double (Dynarec and Interpretor), and proper handling of denormals when converting to/from 80 bits long double
* Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel)
-- Sebastien Chevalier <[email protected]> Thu, 10 Mar 2023 10:20:33 -0500
box86 (0.2.8) unstable; urgency=low
* Wrapped more Vulkan functions, dxvk2.0 now works
* Added support for overridden malloc/free functions
* Improved elf loader
* Improved dlsym handling with RTLD_NEXT
* Added BOX86_DYNAREC_SAFEFLAGS to allow finetuning Dynarec generated code handling of flags accross function calls and returns.
* Added BOX86_BASH to setup x86 bash binary, so shell script can be run in x86 world
* Added BOX86_ROLLING_LOG to have details log only on crash
* Improved TLS Size handling (Unity3D games now works)
* Improved execv family of function to have better box86 integration
* Added a few more wrapped libs, like FAudio
* Improved gtk, SDL2, GL, vulkan (and more) wrapping
* Improved Signal Handling and memory protection traking
* Added some basic support for statically linked program. Thread are not working yet, but memory allocation and file access does.
* add LX2160A config by @lizthegrey in #612
* Grammar and formatting COMPILE.md by @Radiicall in #615
* Update README.md by @everypizza1 in #617
* docs: add instructions for Debian-based Linux by @ryanfortner in #622
* Fix typoes in readme by @ryanfortner in #621
* Various improvements to install_steam.sh by @ryanfortner in #620
* docs: remove unnecessary newline by @ryanfortner in #624
* fix: the first parameter of realpath may be null by @ye-yeshun in #630
* Add 6 wrapped function to libdrm, and 2 to libexpat. by @cjy880927 in #632
* Fix #610 by @rajdakin in #634
* some floating point instructions by @ye-yeshun in #637
* Fix Typo in readme x86_64 -> x86 by @Jai-JAP in #642
* Fix grammar by @Jai-JAP in #645
* Test wine preload by @ptitSeb in #649
* Align address when call mprotect by @wannacu in #651
* Added 66 0F 7D HSUBPD opcode by @wannacu in #652
* add TEGRAX1 and TEGRAX1ARM32 targets on ubuntu-18.04 by @theofficialgman in #654
* automatically install 32 bit libraries if 64 bit OS is detected in install_steam.sh by @Moldytzu in #659
* mention gcc-arm-linux-gnueabihf in compile.md by @Moldytzu in #660
* Add libc6:armhf install to RPi4 aarch64 build info by @WheezyE in #685
* Updated wine install for RPiOS bullseye 32/64bit by @WheezyE in #689
* Add atomic add opcodes by @Trass3r in #695
* steam: disable modern login and pass arguments to client by @Moldytzu in #700
* Modify sizeof(instsize_t) to 1 byte by @liuli0217 in #721
* Add MOV GS:od, AL by @liuli0217 in #722
-- Sebastien Chevalier <[email protected]> Thu, 17 Nov 2022 11:20:33 -0500
box86 (0.2.6) unstable; urgency=low
* Added an option to get generated -NAN on SSE2 operation
+37
View File
@@ -1,3 +1,40 @@
v0.3.0
======
* Added rcfile handling: box86 now read `/etc/box86.box86rc` and `~/.box86rc` and apply per process parameters
=> Every program can be finetuned, for speed or just to make them work
* Added BOX86_DYNAREC_FORWARD to allow bigger Dynarec block to be build
* Refactored Strong Memory Model emulation (faster and more accurate)
* Box86 now return a custom name for the CPU instal of P4, build with Box86 and the cpu name it's running on
* Improved memory protection tracking and signal handling, again
* More wrapped libs (especially on the gtk familly)
* More wrapped functions
* Added support for CreateDeviceEx in d3dadapter9, for better gallium nine support
* Improved dladdr/dladdr1 wrapped function
* Some fixes to flags handling in the Dynarec on some special cases
* Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel)
* Lots of improvment in the Rounding of float & double (Dynarec and Interpretor), and proper handling of denormals when converting to/from 80 bits long double
* Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel)
v0.2.8
======
* Wrapped more vulkan function, dxvk 2.0 now works
* Added support for overriden malloc/free functions
* Improved elf loader
* Improved dlsym handling with RTLD_NEXT
* Added BOX86_DYNAREC_SAFEFLAGS to allow finetuning Dynarec generated code handling of flags accross function calls and returns.
* Added BOX86_BASH to setup x86 bash binary, so shell script can be run in x86 world
* Added BOX86_ROLLING_LOG to have details log only on crash
* Improved TLS Size handling (Unity3D games now works)
* Improved `execv` family of function to have better box86 integration
* Added a few more wrapped libs, like FAudio
* Improved gtk, SDL2, GL, vulkan (and more) wrapping
* Improved Signal Handling and memory protection traking
* Added some basic support for statically linked program. Thread are not working yet, but memory allocation and file access does.
=> with the use of the new SafeFlags, some C# Windows program now runs fine (it's forced when the Vara family of software is detected)
=> With the basic support of statcaly linked program, old emulator like modeler for linux works. Program with threads like mugen for linux still doesn't
=> The bash integration is usefull for device with no binfmt integration or for script that check the machine it's running on
v0.2.6
======
* Added an option to get generated -NAN on SSE2 operation
+32 -1
View File
@@ -10,6 +10,8 @@ wget -qO- https://itai-nelken.github.io/weekly-box86-debs/debian/KEY.gpg | sudo
sudo apt update && sudo apt install box86 -y
```
**Note:** On a 64bit OS, install the `box86:armhf` package.
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
@@ -52,7 +54,7 @@ _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 # -DRPI4ARM64=1 for Pi4 aarch64 (use `-DRPI2ARM64=1` etc for other models)
mkdir build; cd build; cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # -DRPI4ARM64=1 for Pi4 aarch64 (use `-DRPI3ARM64=1` for a PI3 model)
make -j2
sudo make install
sudo systemctl restart systemd-binfmt
@@ -70,6 +72,22 @@ As most RK3399 devices run an AARCH64 OS, you'll need an `armhf` multiarch envir
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 RK3588 / RK3588S
`mkdir build; cd build; cmake .. -DRK3588=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
As most RK3588 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 ODROID N2/N2+
`mkdir build; cd build; cmake .. -DODROIDN2=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
As most ODROID N2/N2+ 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
`mkdir build; cd build; cmake .. -DRK3288=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
@@ -94,12 +112,25 @@ As most Snapdragon 845 devices run an AARCH64 OS, you'll need an `armhf` multiar
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 ARM64 64bits Linux platform
`mkdir build; cd build; cmake .. -DARM64 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
You can also add `-DBAD_SIGNAL=ON` to the cmake command if you are on Linux Kernel mixed with Android, like on RK3588 or maybe Termux
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
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
You can also add `-DBAD_SIGNAL=ON` to the cmake command if you are on Linux Kernel mixed with Android, like on RK3588 or maybe Termux
#### for x86 Linux
`mkdir build; cd build; cmake .. -DCMAKE_C_FLAGS="-m32" -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
+27 -15
View File
@@ -12,13 +12,13 @@ Box86 lets you run x86 Linux programs (such as games) on non-x86 Linux systems,
You *NEED* a 32-bit subsystem to run and build Box86. Box86 is useless on 64-bit only systems. Also, you *NEED* a 32-bit toolchain to build Box86. A toolchain that only supports 64-bit will not compile Box86, and you'll get errors (typically on aarch64, you get "-marm" not recognized, and you'll need a multiarch or chroot environment).
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at those bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at those bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/). That also means that you will need a 32bits userspace on 64bits OS, like `armhf` on top an `aarch64` 64bits OS.
Most x86 Games need OpenGL, so on ARM platforms a solution like [gl4es](https://github.com/ptitSeb/gl4es) is usually necessary. (Most ARM platforms only support OpenGL ES and/or their OpenGL implementation is dodgy (see OpenGL on Android).)
Most x86 Games need OpenGL, so on ARM platforms a solution like [gl4es](https://github.com/ptitSeb/gl4es) might be necessary. (Some ARM platforms only support OpenGL ES and/or their OpenGL implementation is dodgy. (see OpenGL on Android))
Box86 now integrates a DynaRec (dynamic recompiler) for the ARM platform, providing a speed boost between 5 to 10 times faster than only using the interpreter. Some high level information on how the Dynarec work can be found [here](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
Many games already work without much tweaking, for example: WorldOfGoo, Airline Tycoon Deluxe, and FTL. Many of the GameMaker Linux games also run fine. (there's a long list, among them are UNDERTALE, A Risk of Rain, and Cook Serve Delicious)
Many games just work without much tweaking, for example: WorldOfGoo, Airline Tycoon Deluxe, and FTL. Many of the GameMaker Linux games also run fine. (there's a long list, among them are UNDERTALE, A Risk of Rain, and Cook Serve Delicious). Unity3D games also works fine, but the OpenGL requirement might be an issue on some ARM platforms.
If you are serious about developing Box86, you should install ccache and build Box86 with it. (Use ccmake for example.)
To enable TRACE (i.e. dumping to stdout all individual x86 instructions executed, with dump of registers), you'll also need [Zydis library](https://github.com/zyantific/zydis) available on your system.
@@ -56,7 +56,7 @@ There are a few environment variables to control the behaviour of Box86.
See [here](USAGE.md) for all environment variables and what they do.
Note: Box86's Dynarec uses a mechanism with Memory Protection and a SegFault signal handler to handle JIT code. In simpler terms, if you want to use GDB to debug a running program that use JIT'd code (like mono/Unity3D), you will still have many "normal" segfaults triggering. It is suggested to use something like `handle SIGSEGV nostop` in GDB to not stop at each segfault, and maybe put a breakpoint inside `my_memprotectionhandler` in `signals.c` if you want to trap SegFaults.
Note: Box86's Dynarec uses a mechanism with Memory Protection and a SegFault signal handler to handle JIT code. In simpler terms, if you want to use GDB to debug a running program that use JIT'd code (like mono/Unity3D), you will still have many "normal" segfaults triggering. It is suggested to use something like `handle SIGSEGV nostop` in GDB to not stop at each segfault, and maybe put a breakpoint inside `my_box86signalhandler` in `signals.c` if you want to trap SegFaults.
----
@@ -76,28 +76,40 @@ If you look at a 64bits version of box86, look at [Box64](https://github.com/pti
----
Notes about Box86 configuration
----
Box86 now have configurations files. There are 2 files loaded. `/etc/box4.box86rc` and `~/.box86rc`. Both files have the same syntax, and is basicaly an ini files. Section in square brakets define the process name, and the rest is the env. var. to set. Looke at [Usage](USAGE.md) for detail on what parameters can be put. Box86 comes with a default file that should be installed for better stability. The file in in `system/box86.box86rc` and should be installed to `/etc/box86.box86rc` If, for some reasons, you don't want to install that file here, at least copy it to `~/.box86rc` or some game may not function correctly.
Note that the priority is: `~/.bashrc` > `/etc/box86.box86rc` > command line
So, your settings in `~/.bashrc` may override the setting from your command line...
----
Notes about Unity game emulation
----
Running Unity games is a hit or miss for now. Unity uses Mono (which uses signals that are not well emulated enough), and a runtime embedded in the main binary. A solution would be to use a native version of the libmono library used by Unity (it can be found here: https://github.com/Unity-Technologies/mono and needs to be built from source). But the wrapping of this lib is tricky, and not done for now, so the only solution is to emulate everything. The tricky part is to emulate the "JIT" code emitted by Mono, however with the new "protected memory" mechanism implemented it should be running with correct performance now.
You should also note that some Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
TL;DR: Not all Unity games work and can require a high OpenGL profile, but the speed, for the ones running, should be correct now.
Running Unity games shoudl generaly work now, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
Hint: on Pi4, use `MESA_GL_VERSION_OVERRIDE=3.2` and with Panfrost use `PAN_MESA_DEBUG=gl3` to use higher profile if the game starts then quits before showing anything.
----
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`.
Linux Steam's can run now with box86. but you also need box64 for it to completly usable.
It is advised to run steam in the Small mode, as it use the less memory, but steamwebhelper (a 64bits process) will still be loaded even if not used.
The login screen cannot run without steamwebhelper, and will just show a blank windows without box64 properly setup in the system.
File note, Steam will use a lot of memory, and barely fit on system with 4GB of RAM. It will not work anymore on system with less memory (as a workaround, create a swap file, login and check "remember me", the use box64rc to disable steamwebhelper and run only in small mode without swap after the 1st login)
Final note: the Steam BigPicture will work, but also need steamwebhelper (and so box64), and lots of memory. It will not start on system with only 4GB of RAM without swap.
- 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 (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.
to disable `steamwebhelper` when box64 installed and running, create (or edit) `~/.box64rc` and add:
```
[steamwebhelper]
BOX64_EXIT=1
```
in it and it will be disable. Comment with a `#` those 2 lines to enable it again
----
@@ -112,7 +124,7 @@ Note: if you plan to use box86 with Wine on Raspberry Pi 3 or earlier, those mod
Notes about Vulkan
----
Box86 already wrap Vulkan. If your system has a 32bits Vulkan driver, box86 will use it when needed. Note that Vulkan wrapping has not been tested much, due to the limited Vulkan support on the hardware I currently own. Profile 1.0 and 1.1, with some extension, should be OK. 1.2 is not really wrapped. I know some demos work on Pi4 (Sascha Willems demos build for x86 work the same as if build on armhf directly). Note that the Vulkan driver of the Pi4 DOES NOT support dxvk for now (wine DirectX->Vulkan wrapper). It's not a box86 issue, it's missing extensions (hardware support) and a few other things that make dxvk not working on pi4. On Panfrost side, PanVK is a bit young and I haven't tested dxvk with it yet.
Box86 already wrap Vulkan. If your system has a 32bits Vulkan driver, box86 will use it when needed. Profile 1.0, 1.1, 1.2 and 1.3, with some extensions, should be OK. DXVK, including the 2.0, works. I know some demos work on Pi4 (Sascha Willems demos build for x86 work the same as if build on armhf directly). Note that the Vulkan driver of the Pi4 DOES NOT support dxvk for now (wine DirectX->Vulkan wrapper). It's not a box86 issue, it's missing extensions (hardware support) and a few other things that make dxvk not working on pi4. On Panfrost side, PanVK is a bit young and I haven't tested dxvk with it yet.
----
Final word
+85 -44
View File
@@ -3,196 +3,233 @@ Usage
----
There are many environment variables to control Box86 behaviour.
Env. var with * can also be put inside box64rc files
#### BOX86_LOG
#### BOX86_LOG *
Controls the Verbosity level of the logs
* 0: NONE : No message (except some fatal error). (Default.)
* 1: INFO : Show some minimum log (Example: librairies not found)
* 2: DEBUG : Details a lot of stuff (Example: relocations or functions called).
* 3: DUMP : All DEBUG plus DUMP of all ELF Info (so same as `BOX86_LOG=2 BOX86_DUMP=1`)
#### BOX86_DUMP
#### BOX86_DUMP *
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
#### 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)
* 1: Last 16 wrapped functions calls printed when a signal is printed. Incompatible with BOX86_LOG>1 (may need BOX86_SHOWSEGV=1 also)
* N: Last N wrapped functions calls 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.)
* 1 : Disable printing its banner.
#### BOX86_LD_LIBRARY_PATH
#### BOX86_LD_LIBRARY_PATH *
Path to look for x86 libraries. Default is current folder and `lib` in current folder.
Also, `/usr/lib/i386-linux-gnu` and `/lib/i386-linux-gnu` are added if they exist.
#### BOX86_PATH
#### BOX86_PATH *
Path to look for x86 executable. Default is current folder and `bin` in current folder.
#### BOX86_DLSYM_ERROR
#### BOX86_DLSYM_ERROR *
Enables/Disables the logging of `dlsym` errors.
* 0 : Don't log `dlsym` errors. (Default.)
* 1 : Log dlsym errors.
#### BOX86_TRACE_FILE
#### BOX86_TRACE_FILE *
Send all log and trace to a file instead of `stdout`
Also, if name contains `%pid` then this is replaced by the actual PID of box86 instance
Use `stderr` to use this instead of default `stdout`
#### BOX86_TRACE
#### BOX86_TRACE *
Only on build with trace enabled. Trace allow the logging of all instruction executed, along with register dump
* 0 : No trace. (Default.)
* 1 : Trace enabled. Trace start after the initialisation of all depending libraries is done.
* symbolname : Trace only `symbolname` (trace is disable if the symbol is not found).
* 0xXXXXXXX-0xYYYYYYY : Trace only between the 2 addresses.
#### BOX86_TRACE_INIT
#### BOX86_TRACE_INIT *
Use BOX86_TRACE_INIT instead of BOX_TRACE to start trace before the initialisation of libraries and the running program
* 0 : No trace. (Default.)
* 1 : Trace enabled. The trace start with the initialisation of all depending libraries is done.
#### BOX86_TRACE_START
#### BOX86_TRACE_START *
Only on builds with trace enabled.
* NNNNNNN : Start trace only after NNNNNNNN opcode execute (number is an `uint64_t`).
#### BOX86_TRACE_XMM
#### BOX86_TRACE_XMM *
Only on builds with trace enabled.
* 0 : The XMM (i.e. SSE/SSE2) register will not be logged with the general and x86 registers. (Default.)
* 1 : Dump the XMM registers.
#### BOX86_LOAD_ADDR
#### BOX86_TRACE_EMM *
Only on builds with trace enabled.
* 0 : The EMM (i.e. MMX) register will not be logged with the general and x86 registers. (Default.)
* 1 : Dump the EMM registers.
#### BOX86_LOAD_ADDR *
Try to load at 0xXXXXXX main binary (if binary is a PIE)
* 0xXXXXXXXX : The load address . (Only active on PIE programs.)
#### BOX86_NOSIGSEGV
#### BOX86_NOSIGSEGV *
Disable handling of SigSEGV. (Very useful for debugging.)
* 0 : Let the x86 program set sighandler for SEGV (Default.)
* 1 : Disable the handling of SigSEGV.
#### BOX86_NOSIGILL
#### BOX86_NOSIGILL *
Disable handling of SigILL (to ease debugging mainly).
* 0 : Let x86 program set sighandler for Illegal Instruction
* 1 : Disables the handling of SigILL
#### BOX86_X11COLOR16
#### BOX86_X11COLOR16 *
PANDORA only: Try converting X11 color from 32 bits to 16 bits (to avoid light green on light cyan windows).
* 0 : Don't touch X11 colors. (Default.)
* 1 : Change colors arguments in XSetForeground, XSetBackground and XCreateGC.
#### BOX86_X11THREADS
#### BOX86_X11THREADS *
Call XInitThreads when loading X11. (This is mostly for old Loki games with the Loki_Compat library.)
* 0 : Don't force call XInitThreads. (Default.)
* 1 : Call XInitThreads as soon as libX11 is loaded.
#### BOX86_X11GLX
#### BOX86_X11GLX *
Force libX11's GLX extension to be present.
* 0 : Do not force libX11's GLX extension to be present.
* 1 : GLX will always be present when using XQueryExtension. (Default.)
#### BOX86_DYNAREC_DUMP
#### BOX86_DYNAREC_DUMP *
Enables/disables Box86's Dynarec's dump.
* 0 : Disable Dynarec's blocks dump. (Default.)
* 1 : Enable Dynarec's blocks dump.
* 2 : Enable Dynarec's blocks dump with some colors.
#### BOX86_DYNAREC_LOG
#### BOX86_DYNAREC_LOG *
Set the level of DynaRec's logs.
* 0 : NONE : No Logs for DynaRec. (Default.)
* 1 :INFO : Minimum Dynarec Logs (only unimplemented OpCode).
* 2 : DEBUG : Debug Logs for Dynarec (with details on block created / executed).
* 3 : VERBOSE : All of the above plus more.
#### BOX86_DYNAREC
#### BOX86_DYNAREC *
Enables/Disables Box86's Dynarec.
* 0 : Disables Dynarec.
* 1 : Enable Dynarec. (Default.)
#### BOX86_DYNAREC_TRACE
#### BOX86_DYNAREC_TRACE *
Enables/Disables trace for generated code.
* 0 : Disable trace for generated code. (Default.)
* 1 : Enable trace for generated code (like regular Trace, this will slow down the program a lot and generate huge logs).
#### BOX86_NODYNAREC
#### BOX86_NODYNAREC *
Forbid dynablock creation in the interval specified (helpfull for debugging behaviour difference between Dynarec and Interpretor)
* 0xXXXXXXXX-0xYYYYYYYY : define the interval where dynablock cannot start (inclusive-exclusive)
#### BOX86_DYNAREC_BIGBLOCK
#### BOX86_DYNAREC_BIGBLOCK *
Enables/Disables Box86's Dynarec building BigBlock.
* 0 : Don't try to build block as big as possible (can help program using lots of thread and a JIT, like C#/Unity) (Default when libmonobdwgc-2.0.so is loaded)
* 1 : Build Dynarec block as big as possible (Default.)
* 2 : Build Dynarec block bigger (don't stop when block overlaps)
#### BOX86_DYNAREC_STRONGMEM
#### BOX86_DYNAREC_FORWARD *
Define Box86's Dynarec max allowed forward value when building Block.
* 0 : No forward value. When current block end, don't try to go further even if there are previous forward jumps
* XXX : Allow up to XXXX bytes of gap when building a Block after the block end to next forward jump (Default: 128)
#### BOX86_DYNAREC_STRONGMEM *
Enable/Disable simulation of Strong Memory model
* 0 : Don't try anything special (Default.)
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
#### BOX86_DYNAREC_X87DOUBLE
#### BOX86_DYNAREC_X87DOUBLE *
Force the use of Double for x87 emulation
* 0 : Try to use float when possible for x87 emulation (faster, Default)
* 1 : Only use Double for x87 emulation (slower, may be needed for some specific games, like Crysis were it's enable automatically)
#### BOX86_DYNAREC_FASTNAN
#### 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
#### BOX86_DYNAREC_FASTROUND *
Enable/Disable generation of precise x86 rounding
* 0 : Generate float/double -> int rounding like on x86
* 1 : Don't do anything special with edge case Rounding, to go as fast as possible (no INF/NAN/Overflow -> MIN_INT conversion) (faster, 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
#### BOX86_DYNAREC_HOTPAGE *
Handling of HotPage (Page beeing both executed and writen)
* 0 : Don't track hotpage
* 1-255 : Trak HotPage, and disable execution of a page beeing writen for N attempts (default is 16)
#### BOX86_DYNAREC_BLEEDING_EDGE *
Detect MonoBleedingEdge and apply conservative settings
* 0 : Don't detect MonoBleedingEdge
* 1 : Detect MonoBleedingEdge, and apply BIGBLOCK=0 STRONGMEM=1 if detected (Default)
#### BOX86_SSE_FLUSHTO0 *
Handling of SSE Flush to 0 flags
* 0 : Just track the flag (Default)
* 1 : Direct apply of SSE Flush to 0 flag
#### BOX86_X87_NO80BITS *
Handling of x87 80bits long double
* 0 : Try to handle 80bits long double as precise as possible (Default)
* 1 : Handle them as double
#### BOX86_LIBGL *
* libXXXX set the name for libGL (defaults to libGL.so.1).
* /PATH/TO/libGLXXX : Sets the name and path for libGL
You can also use SDL_VIDEO_GL_DRIVER
#### BOX86_LD_PRELOAD
#### BOX86_LD_PRELOAD *
* XXXX[:YYYYY] force loading XXXX (and YYYY...) libraries with the binary
PreLoaded libs can be emulated or native, and are treated the same way as if they were comming from the binary
PreLoaded libs can be emulated or native, and are treated the same way as if they were comming from the binary (not that using this inside a rcfile might not work if the process needs to be renamed, for example for Wine process)
#### BOX86_EMULATED_LIBS
#### BOX86_EMULATED_LIBS *
* XXXX[:YYYYY] force lib XXXX (and YYYY...) to be emulated (and not wrapped)
Some games uses an old version of some libraries, with an ABI incompatible with native version.
Note that LittleInferno for example is auto detected, and libvorbis.so.0 is automatical added to emulated libs, and same for Don't Starve (and Together / Server variant) that use an old SDL2 too
#### BOX86_ALLOWMISSING_LIBS
#### BOX86_ALLOWMISSING_LIBS *
Allow Box86 to continue even if a library is missing (renamed from BOX86_ALLOWMISSINGLIBS).
* 0 : Box86 will stop if a library cannot be loaded. (Default.)
* 1 : Continue even if a needed library cannot be loaded. Unadvised, this will, in most cases, crash later on.
#### BOX86_ALLOWMISSING_SYMBOLS
#### BOX86_ALLOWMISSING_SYMBOLS *
Allow dlopen with RTLD_NOW flag to not resolve all symbols.
* 0 : Box86 will stop if a library have unresolved symbols. (Default.)
* 1 : Continue even if a needed library have unresolved symbols (like symbols not yet wrapped).
#### BOX86_PREFER_WRAPPED
#### BOX86_PREFER_WRAPPED *
Box86 will use wrapped libs even if the lib is specified with absolute path
* 0 : Try to use emulated libs when they are defined with absolute path (Default.)
* 1 : Use Wrapped native libs even if path is absolute
#### BOX86_PREFER_EMULATED
#### BOX86_PREFER_EMULATED *
Box86 will prefer emulated libs first (execpt for glibc, alsa, pulse, GL, vulkan and X11
* 0 : Native libs are prefered (Default.)
* 1 : Emulated libs are prefered (Default for program running inside pressure-vessel)
#### BOX86_NOPULSE
#### BOX86_NOPULSE *
Disables the load of pulseaudio libraries.
* 0 : Load pulseaudio libraries if found. (Default.)
* 1 : Disables the load of pulse audio libraries (libpulse and libpulse-simple), both the native library and the x86 library
#### BOX86_NOGTK
#### BOX86_NOGTK *
Disables the loading of wrapped GTK libraries.
* 0 : Load wrapped GTK libraries if found. (Default.)
* 1 : Disables loading wrapped GTK libraries.
#### BOX86_NOVULKAN
#### BOX86_NOVULKAN *
Disables the load of vulkan libraries.
* 0 : Load vulkan libraries if found.
* 1 : Disables the load of vulkan libraries, both the native and the i386 version (can be useful on Pi4, where the vulkan driver is not quite there yet.)
@@ -205,22 +242,22 @@ Disables the load of vulkan libraries.
* XXX=yyyy
will add XXX=yyyy env. var. and continue with BOX86_ENV2 ... until var doesn't exist
#### BOX86_FIX_64BIT_INODES
#### 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
#### 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
#### BOX86_SHOWBT *
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
#### 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.
@@ -229,7 +266,8 @@ Will use yyyy as x86 bash to launch script. yyyy needs to be a full path to a va
Define where to find box64 binary
* yyyy
Will use yyyy as x86_64 interpretor, to launch x64_64 binaries
#### BOX86_JITGDB
#### BOX86_JITGDB *
* 0 : Just print the Segfault message on segfault (default)
* 1 : Launch `gdb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process and go in an endless loop, waiting.
@@ -240,3 +278,6 @@ Will use yyyy as x86_64 interpretor, to launch x64_64 binaries
* 2 : Launch `gdbserver` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process, and go in an endless loop, waiting.
Use `gdb /PATH/TO/box86` and then `target remote 127.0.0.1:1234` to connect to the gdbserver (or use actual IP if not on the machine). After that, the procedure is the same as with ` BOX86_JITGDB=1`.
This mode can be usefullwhen programs redirect all console output to a file (like Unity3D Games)
#### BOX86_NORCFILES
If the env var exist, no rc files (like /etc/box86.box86rc and ~/.box86rc) will be loaded
+3 -1
View File
@@ -21,6 +21,7 @@ cd ../ && rm -rf ./tmp/
echo "#!/bin/bash
export STEAMOS=1
export STEAM_RUNTIME=1
export DBUS_FATAL_WARNINGS=0
~/steam/bin/steam -noreactlogin steam://open/minigameslist $@" > steam
# make script executable and move
@@ -33,7 +34,8 @@ 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
# install the libraries that Steam requires
sudo apt install libc6:armhf libncurses5:armhf libsdl2-2.0-0:armhf libsdl2-image-2.0-0:armhf libsdl2-mixer-2.0-0:armhf libsdl2-ttf-2.0-0:armhf libopenal1:armhf libpng16-16:armhf libfontconfig1:armhf libxcomposite1:armhf libbz2-1.0:armhf libxtst6:armhf
echo "Don't forget to compile/install Box64!"
fi
+1 -1
View File
@@ -1249,7 +1249,7 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
f.write("void {0}(x86emu_t *emu, uintptr_t fcn) {2} {1} fn = ({1})fcn; ".format(N.orig, W, "{"))
if N.orig == 'vFv':
f.write("(void)fcn; ")
f.write("(void)emu; ")
args = N.orig[2:]
if args == 'Ev': args = 'E'
+55 -22
View File
@@ -22,6 +22,7 @@
#include <sys/mman.h>
#include "custommem.h"
#include "dictionnary.h"
#include "rcfile.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "dynarec/arm_lock_helper.h"
@@ -48,6 +49,7 @@ void finiAllHelpers(box86context_t* context)
static int finied = 0;
if(finied)
return;
DeleteParams();
fini_pthread_helper(context);
fini_signal_helper();
fini_bridge_helper();
@@ -82,11 +84,20 @@ int unlockMutex()
{
int ret = unlockCustommemMutex();
int i;
#ifdef DYNAREC
void* tid = (void*)GetTID();
#define GO(A, B) \
i = (arm_lock_storeifref2(&A, NULL, tid)==tid); \
if(i) { \
ret|=(1<<B); \
}
#else
#define GO(A, B) \
i = checkUnlockMutex(&A); \
if(i) { \
ret|=(1<<B); \
}
#endif
GO(my_context->mutex_once, 5)
GO(my_context->mutex_once2, 6)
@@ -100,7 +111,6 @@ int unlockMutex()
GO(my_context->mutex_thread, 10)
GO(my_context->mutex_bridge, 11)
#undef GO
return ret;
}
@@ -108,7 +118,7 @@ void relockMutex(int locks)
{
#define GO(A, B) \
if(locks&(1<<B)) \
pthread_mutex_lock(&A); \
mutex_lock(&A); \
GO(my_context->mutex_once, 5)
GO(my_context->mutex_once2, 6)
@@ -127,22 +137,29 @@ void relockMutex(int locks)
static void init_mutexes(box86context_t* context)
{
#ifdef DYNAREC
arm_lock_stored(&context->mutex_dyndump, 0);
arm_lock_stored(&context->mutex_once, 0);
arm_lock_stored(&context->mutex_once2, 0);
arm_lock_stored(&context->mutex_trace, 0);
arm_lock_stored(&context->mutex_tls, 0);
arm_lock_stored(&context->mutex_thread, 0);
arm_lock_stored(&context->mutex_bridge, 0);
#else
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&context->mutex_once, &attr);
pthread_mutex_init(&context->mutex_once2, &attr);
pthread_mutex_init(&context->mutex_trace, &attr);
#ifdef DYNAREC
pthread_mutex_init(&context->mutex_dyndump, &attr);
#else
pthread_mutex_init(&context->mutex_lock, &attr);
#endif
pthread_mutex_init(&context->mutex_tls, &attr);
pthread_mutex_init(&context->mutex_thread, &attr);
pthread_mutex_init(&context->mutex_bridge, &attr);
pthread_mutex_init(&context->mutex_lock, &attr);
pthread_mutexattr_destroy(&attr);
#endif
}
static void atfork_child_box64context(void)
@@ -151,6 +168,31 @@ static void atfork_child_box64context(void)
init_mutexes(my_context);
}
void freeCycleLog(box86context_t* 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->log_call);
box_free(ctx->log_ret);
ctx->log_call = NULL;
ctx->log_ret = NULL;
}
}
void initCycleLog(box86context_t* context)
{
if(cycle_log) {
context->log_call = (char**)box_calloc(cycle_log, sizeof(char*));
context->log_ret = (char**)box_calloc(cycle_log, sizeof(char*));
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);
}
}
}
EXPORTDYN
box86context_t *NewBox86Context(int argc)
{
@@ -163,11 +205,8 @@ box86context_t *NewBox86Context(int argc)
// init and put default values
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);
}
initCycleLog(context);
#ifdef BUILD_LIB
context->deferedInit = 0;
#else
@@ -320,23 +359,17 @@ void FreeBox86Context(box86context_t** context)
finiAllHelpers(ctx);
#ifndef DYNAREC
pthread_mutex_destroy(&ctx->mutex_once);
pthread_mutex_destroy(&ctx->mutex_once2);
pthread_mutex_destroy(&ctx->mutex_trace);
#ifdef DYNAREC
pthread_mutex_destroy(&ctx->mutex_dyndump);
#else
pthread_mutex_destroy(&ctx->mutex_lock);
#endif
pthread_mutex_destroy(&ctx->mutex_tls);
pthread_mutex_destroy(&ctx->mutex_thread);
pthread_mutex_destroy(&ctx->mutex_bridge);
pthread_mutex_destroy(&ctx->mutex_lock);
#endif
if(cycle_log)
for(int i=0; i<CYCLE_LOG; ++i) {
box_free(ctx->log_call[i]);
box_free(ctx->log_ret[i]);
}
freeCycleLog(ctx);
box_free(ctx);
}
+2 -2
View File
@@ -2,7 +2,7 @@
#define __BOX86_VERSION_H_
#define BOX86_MAJOR 0
#define BOX86_MINOR 2
#define BOX86_REVISION 7
#define BOX86_MINOR 3
#define BOX86_REVISION 0
#endif //__BOX86_VERSION_H_
+297 -131
View File
@@ -35,7 +35,6 @@ KHASH_MAP_INIT_INT(dynablocks, dynablock_t*)
static dynablocklist_t* dynmap[DYNAMAP_SIZE] = {0}; // 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];
@@ -46,8 +45,17 @@ static kh_lockaddress_t *lockaddress = NULL;
#define MEMPROT_SHIFT 12
#define MEMPROT_SIZE (1<<(32-MEMPROT_SHIFT))
static uint8_t memprot[MEMPROT_SIZE] = {0}; // protection flags by 4K block
#ifdef DYNAREC
static uint8_t hotpages[MEMPROT_SIZE] = {0};
#endif
static int inited = 0;
#define PROT_LOCK() mutex_lock(&mutex_blocks)
#define PROT_UNLOCK() mutex_unlock(&mutex_blocks)
#define PROT_GET(A) memprot[A]
#define PROT_SET(A, B) memprot[A] = B
#define PROT_SET_IF_0(A, B) if(!memprot[A]) memprot[A] = B
typedef struct mapmem_s {
uintptr_t begin, end;
struct mapmem_s *next;
@@ -57,13 +65,17 @@ static mapmem_t *mapmem = NULL;
typedef struct blocklist_s {
void* block;
int maxfree;
size_t maxfree;
size_t size;
} blocklist_t;
#define MMAPSIZE (256*1024) // allocate 256kb sized blocks
#ifndef DYNAREC
static pthread_mutex_t mutex_blocks;
#else
static uint32_t mutex_blocks;
#endif
static int n_blocks = 0; // number of blocks for custom malloc
static blocklist_t* p_blocks = NULL; // actual blocks for custom malloc
@@ -83,6 +95,7 @@ typedef struct blockmark_s {
#define PREV_BLOCK(b) (blockmark_t*)(((uintptr_t)(b) - (b)->prev.size) - sizeof(blockmark_t))
#define LAST_BLOCK(b, s) (blockmark_t*)(((uintptr_t)(b)+(s))-sizeof(blockmark_t))
#ifdef DYNAREC
static void printBlock(blockmark_t* b, void* start)
{
printf_log(LOG_INFO, "========== Block is:\n");
@@ -92,6 +105,7 @@ static void printBlock(blockmark_t* b, void* start)
} while(b->next.x32);
printf_log(LOG_INFO, "===================\n");
}
#endif
// get first subblock free in block. Return NULL if no block, else first subblock free (mark included), filling size
static void* getFirstBlock(void* block, size_t maxsize, size_t* size, void* start)
@@ -114,7 +128,7 @@ static size_t getMaxFreeBlock(void* block, size_t block_size, void* start)
// get start of block
if(start) {
blockmark_t *m = (blockmark_t*)start;
int maxsize = 0;
size_t maxsize = 0;
while(m->next.x32) { // while there is a subblock
if(!m->next.fill && m->next.size>maxsize) {
maxsize = m->next.size;
@@ -124,7 +138,7 @@ static size_t getMaxFreeBlock(void* block, size_t block_size, void* start)
return (maxsize>=sizeof(blockmark_t))?maxsize:0;
} else {
blockmark_t *m = LAST_BLOCK(block, block_size); // start with the end
int maxsize = 0;
size_t maxsize = 0;
while(m->prev.x32) { // while there is a subblock
if(!m->prev.fill && m->prev.size>maxsize) {
maxsize = m->prev.size;
@@ -243,7 +257,7 @@ void* customMalloc(size_t size)
{
// look for free space
void* sub = NULL;
pthread_mutex_lock(&mutex_blocks);
mutex_lock(&mutex_blocks);
for(int i=0; i<n_blocks; ++i) {
if(p_blocks[i].maxfree>=size) {
size_t rsize = 0;
@@ -252,7 +266,7 @@ void* customMalloc(size_t size)
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);
pthread_mutex_unlock(&mutex_blocks);
mutex_unlock(&mutex_blocks);
return ret;
}
}
@@ -284,7 +298,7 @@ void* customMalloc(size_t size)
// alloc 1st block
void* ret = allocBlock(p_blocks[i].block, p, size, NULL);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
pthread_mutex_unlock(&mutex_blocks);
mutex_unlock(&mutex_blocks);
return ret;
}
void* customCalloc(size_t n, size_t size)
@@ -299,24 +313,24 @@ void* customRealloc(void* p, size_t size)
if(!p)
return customMalloc(size);
uintptr_t addr = (uintptr_t)p;
pthread_mutex_lock(&mutex_blocks);
mutex_lock(&mutex_blocks);
for(int i=0; i<n_blocks; ++i) {
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));
if(expandBlock(p_blocks[i].block, sub, size)) {
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
pthread_mutex_unlock(&mutex_blocks);
mutex_unlock(&mutex_blocks);
return p;
}
pthread_mutex_unlock(&mutex_blocks);
mutex_unlock(&mutex_blocks);
void* newp = customMalloc(size);
memcpy(newp, p, sizeBlock(sub));
customFree(p);
return newp;
}
}
pthread_mutex_unlock(&mutex_blocks);
mutex_unlock(&mutex_blocks);
if(n_blocks)
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for realloc, malloc'ing again without free\n", (void*)addr);
return customMalloc(size);
@@ -326,85 +340,113 @@ void customFree(void* p)
if(!p)
return;
uintptr_t addr = (uintptr_t)p;
pthread_mutex_lock(&mutex_blocks);
mutex_lock(&mutex_blocks);
for(int i=0; i<n_blocks; ++i) {
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));
size_t newfree = freeBlock(p_blocks[i].block, sub, NULL);
if(p_blocks[i].maxfree < newfree) p_blocks[i].maxfree = newfree;
pthread_mutex_unlock(&mutex_blocks);
mutex_unlock(&mutex_blocks);
return;
}
}
pthread_mutex_unlock(&mutex_blocks);
mutex_unlock(&mutex_blocks);
if(n_blocks)
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for Free\n", (void*)addr);
}
#ifdef DYNAREC
typedef struct mmaplist_s {
typedef struct mmapchunk_s {
void* block;
int maxfree;
size_t size;
kh_dynablocks_t* dblist;
uint8_t* helper;
void* first; // first free block, to speed up things
int locked; // don't try to add stuff on locked block
uint8_t lock; // don't try to add stuff on locked block
} mmapchunk_t;
#define NCHUNK 64
typedef struct mmaplist_s {
mmapchunk_t chunks[NCHUNK];
mmaplist_t* next;
} mmaplist_t;
mmapchunk_t* addChunk(int mmapsize) {
if(!mmaplist)
mmaplist = (mmaplist_t*)box_calloc(1, sizeof(mmaplist_t));
mmaplist_t* head = mmaplist;
int i = mmapsize;
while(1) {
if(i>=NCHUNK) {
i-=NCHUNK;
if(!head->next) {
head->next = (mmaplist_t*)box_calloc(1, sizeof(mmaplist_t));
}
head=head->next;
} else
return &head->chunks[i];
}
}
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);
mmaplist_t* head = mmaplist;
int i = mmapsize;
while(head) {
const int n = (i>NCHUNK)?NCHUNK:i;
i-=n;
for(int i=0; i<n; ++i) {
mmapchunk_t* chunk = &head->chunks[i];
if(chunk->maxfree>=size+sizeof(blockmark_t) && !arm_lock_incif0b(&chunk->lock)) {
size_t rsize = 0;
sub = getFirstBlock(chunk->block, size, &rsize, chunk->first);
if(sub) {
uintptr_t ret = (uintptr_t)allocBlock(chunk->block, sub, size, &chunk->first);
if(rsize==chunk->maxfree) {
chunk->maxfree = getMaxFreeBlock(chunk->block, chunk->size, chunk->first);
}
kh_dynablocks_t *blocks = chunk->dblist;
if(!blocks) {
blocks = chunk->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)
chunk->helper[(uintptr_t)ret-(uintptr_t)(chunk->block)+j] = j;
if(size!=size255)
memset(&chunk->helper[(uintptr_t)ret-(uintptr_t)(chunk->block)+256], -1, size-255);
arm_lock_decifnot0b(&chunk->lock);
return ret;
} else {
printf_log(LOG_INFO, "BOX86: Warning, sub not found, corrupted %p->chunk[%d] info?\n", head, i);
arm_lock_decifnot0b(&chunk->lock);
if(box86_log >= LOG_DEBUG)
printBlock(chunk->block, chunk->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);
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);
}
}
head = head->next;
}
return 0;
}
uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
{
int i = mmapsize++; // yeah, useful post incrementation
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%zu/%zu\n", mmapsize, mmapcap);
if(mmapsize>mmapcap) {
mmapcap += 32;
mmaplist = (mmaplist_t*)box_realloc(mmaplist, mmapcap*sizeof(mmaplist_t));
}
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%zu\n", mmapsize);
mmapchunk_t* chunk = addChunk(mmapsize++);
arm_lock_incb(&chunk->lock);
#ifndef USE_MMAP
void *p = NULL;
if(posix_memalign(&p, box86_pagesize, MMAPSIZE)) {
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, i);
arm_lock_storeb(&chunk->lock, 0);
--mmapsize;
return 0;
}
@@ -412,18 +454,18 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
#else
void* p = mmap(NULL, MMAPSIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if(p==(void*)-1) {
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, i);
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, mmapsize-1);
arm_lock_storeb(&chunk->lock, 0);
--mmapsize;
return 0;
}
#endif
setProtection((uintptr_t)p, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
mmaplist[i].locked = 1;
mmaplist[i].block = p;
mmaplist[i].size = MMAPSIZE;
mmaplist[i].helper = (uint8_t*)box_calloc(1, MMAPSIZE);
mmaplist[i].first = p;
chunk->block = p;
chunk->size = MMAPSIZE;
chunk->helper = (uint8_t*)box_calloc(1, MMAPSIZE);
chunk->first = p;
// setup marks
blockmark_t* m = (blockmark_t*)p;
m->prev.x32 = 0;
@@ -434,17 +476,17 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
n->prev.fill = 0;
n->prev.size = m->next.size;
// alloc 1st block
uintptr_t sub = (uintptr_t)allocBlock(mmaplist[i].block, p, size, &mmaplist[i].first);
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size, mmaplist[i].first);
kh_dynablocks_t *blocks = mmaplist[i].dblist = kh_init(dynablocks);
uintptr_t sub = (uintptr_t)allocBlock(chunk->block, p, size, &chunk->first);
chunk->maxfree = getMaxFreeBlock(chunk->block, chunk->size, chunk->first);
kh_dynablocks_t *blocks = chunk->dblist = kh_init(dynablocks);
kh_resize(dynablocks, blocks, 64);
khint_t k;
int ret;
k = kh_put(dynablocks, blocks, (uintptr_t)sub, &ret);
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;
chunk->helper[(uintptr_t)sub-(uintptr_t)chunk->block + j] = (j<256)?j:255;
arm_lock_decifnot0b(&chunk->lock);
return sub;
}
@@ -452,25 +494,41 @@ void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
{
if(!addr || !size)
return;
for(int i=0; i<mmapsize; ++i) {
if ((addr>(uintptr_t)mmaplist[i].block)
&& (addr<((uintptr_t)mmaplist[i].block+mmaplist[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
size_t newfree = freeBlock(mmaplist[i].block, sub, &mmaplist[i].first);
if(mmaplist[i].maxfree < newfree) mmaplist[i].maxfree = newfree;
kh_dynablocks_t *blocks = mmaplist[i].dblist;
if(blocks) {
khint_t k = kh_get(dynablocks, blocks, (uintptr_t)sub);
if(k!=kh_end(blocks))
kh_del(dynablocks, blocks, k);
memset(&mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block], 0, size);
mmaplist_t* head = mmaplist;
int i = mmapsize;
while(head) {
const int n = (i>NCHUNK)?NCHUNK:i;
i-=n;
for(int i=0; i<n; ++i) {
mmapchunk_t* chunk = &head->chunks[i];
if ((addr>(uintptr_t)(chunk->block))
&& (addr<((uintptr_t)(chunk->block)+chunk->size))) {
int loopedwait = 256;
while (arm_lock_incif0b(&chunk->lock) && loopedwait) {
sched_yield();
--loopedwait;
}
if(!loopedwait) {
printf_log(LOG_INFO, "BOX86: Warning, Free a chunk in a locked mmaplist[%d]\n", i);
//arm_lock_incb(&chunk->lock);
if(cycle_log)
print_cycle_log(LOG_INFO);
}
void* sub = (void*)(addr-sizeof(blockmark_t));
size_t newfree = freeBlock(chunk->block, sub, &chunk->first);
if(chunk->maxfree < newfree) chunk->maxfree = newfree;
kh_dynablocks_t *blocks = chunk->dblist;
if(blocks) {
khint_t k = kh_get(dynablocks, blocks, (uintptr_t)sub);
if(k!=kh_end(blocks))
kh_del(dynablocks, blocks, k);
memset(&chunk->helper[(uintptr_t)sub-(uintptr_t)chunk->block], 0, size);
}
arm_lock_decifnot0b(&chunk->lock);
return;
}
if(mmaplist[i].locked) {
printf_log(LOG_INFO, "BOX86: Warning, Free a chunk in a locked mmaplist[%d]\n", i);
++mmaplist[i].locked;
}
return;
}
head = head->next;
}
if(mmapsize)
dynarec_log(LOG_NONE, "Warning, block %p (size %d) not found in mmaplist for Free\n", (void*)addr, size);
@@ -479,20 +537,28 @@ void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
dynablock_t* FindDynablockFromNativeAddress(void* addr)
{
// look in actual list
for(int i=0; i<mmapsize; ++i) {
if ((uintptr_t)addr>=(uintptr_t)mmaplist[i].block
&& ((uintptr_t)addr<(uintptr_t)mmaplist[i].block+mmaplist[i].size)) {
if(!mmaplist[i].helper)
return FindDynablockDynablocklist(addr, mmaplist[i].dblist);
else {
uintptr_t p = (uintptr_t)addr - (uintptr_t)mmaplist[i].block;
while(mmaplist[i].helper[p]) p -= mmaplist[i].helper[p];
khint_t k = kh_get(dynablocks, mmaplist[i].dblist, (uintptr_t)mmaplist[i].block + p);
if(k!=kh_end(mmaplist[i].dblist))
return kh_value(mmaplist[i].dblist, k);
return NULL;
mmaplist_t* head = mmaplist;
int i = mmapsize;
while(head) {
const int n = (i>NCHUNK)?NCHUNK:i;
i-=n;
for(int i=0; i<n; ++i) {
mmapchunk_t* chunk = &head->chunks[i];
if ((uintptr_t)addr>=(uintptr_t)chunk->block
&& ((uintptr_t)addr<(uintptr_t)chunk->block+chunk->size)) {
if(!chunk->helper)
return FindDynablockDynablocklist(addr, chunk->dblist);
else {
uintptr_t p = (uintptr_t)addr - (uintptr_t)chunk->block;
while(chunk->helper[p]) p -= chunk->helper[p];
khint_t k = kh_get(dynablocks, chunk->dblist, (uintptr_t)chunk->block + p);
if(k!=kh_end(chunk->dblist))
return kh_value(chunk->dblist, k);
return NULL;
}
}
}
head = head->next;
}
// look in oversized
return FindDynablockDynablocklist(addr, dblist_oversized);
@@ -573,7 +639,7 @@ void addDBFromAddressRange(uintptr_t addr, uintptr_t size)
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)
if(arm_lock_storeifnull(&dynmap[i], p)!=NULL)
FreeDynablockList(&p);
}
}
@@ -585,11 +651,14 @@ void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy)
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];
int need_free = (destroy && addr<=(i<<DYNAMAP_SHIFT) && end>=((i+1)>>DYNAMAP_SHIFT)-1)?1:0;
dynablocklist_t* dblist = (need_free)?((dynablocklist_t*)arm_lock_xchg(&dynmap[i], 0)):dynmap[i];
if(dblist) {
if(destroy)
if(destroy) {
FreeRangeDynablock(dblist, addr, size);
else
if(need_free)
FreeDynablockList(&dblist);
} else
MarkRangeDynablock(dblist, addr, size);
}
}
@@ -656,18 +725,20 @@ void protectDB(uintptr_t addr, uintptr_t size)
dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
PROT_LOCK();
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i];
uint32_t prot = PROT_GET(i);
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_DYNAREC;
PROT_SET(i, prot|PROT_DYNAREC);
if(!dyn) mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
} else
memprot[i] = prot|PROT_DYNAREC_R;
PROT_SET(i, prot|PROT_DYNAREC_R);
}
PROT_UNLOCK();
}
// Add the Write flag from an adress range, and mark all block as dirty
@@ -677,16 +748,37 @@ void unprotectDB(uintptr_t addr, uintptr_t size, int mark)
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);
PROT_LOCK();
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i];
uint32_t prot = PROT_GET(i);
if(prot&PROT_DYNAREC) {
memprot[i] = prot&~PROT_DYNAREC;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_DYNAREC);
PROT_SET(i, prot&~PROT_CUSTOM);
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_CUSTOM);
if(mark)
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
} else if(prot&PROT_DYNAREC_R)
memprot[i] = prot&~(PROT_CUSTOM);
PROT_SET(i, prot&~PROT_CUSTOM);
}
PROT_UNLOCK();
}
int isprotectedDB(uintptr_t addr, size_t size)
{
dynarec_log(LOG_DEBUG, "isprotectedDB %p -> %p => ", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
PROT_LOCK();
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = PROT_GET(i);
if(!(prot&(PROT_DYNAREC|PROT_DYNAREC_R))) {
dynarec_log(LOG_DEBUG, "0\n");
PROT_UNLOCK();
return 0;
}
}
dynarec_log(LOG_DEBUG, "1\n");
PROT_UNLOCK();
return 1;
}
#endif
@@ -702,6 +794,8 @@ void printMapMem()
void addMapMem(uintptr_t begin, uintptr_t end)
{
if(!mapmem)
return;
begin &=~0xfff;
end = (end&~0xfff)+0xfff; // full page
// sanitize values
@@ -739,6 +833,8 @@ void addMapMem(uintptr_t begin, uintptr_t end)
}
void removeMapMem(uintptr_t begin, uintptr_t end)
{
if(!mapmem)
return;
begin &=~0xfff;
end = (end&~0xfff)+0xfff; // full page
// sanitize values
@@ -784,73 +880,81 @@ 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);
PROT_LOCK();
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|PROT_DYNAREC_R));
uint32_t dyn=(PROT_GET(i)&(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);
} else if(dyn && !(prot&PROT_WRITE)) {
dyn = PROT_DYNAREC_R;
}
memprot[i] = prot|dyn;
PROT_SET(i, prot|dyn);
}
PROT_UNLOCK();
}
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);
PROT_LOCK();
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_CUSTOM);
memprot[i] = prot;
PROT_SET(i, prot);
}
PROT_UNLOCK();
}
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;
PROT_LOCK();
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;
PROT_SET(i, prot);
}
PROT_UNLOCK();
}
void freeProtection(uintptr_t addr, uintptr_t size)
{
PROT_LOCK();
removeMapMem(addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
memprot[i] = 0;
PROT_SET(i, 0);
}
PROT_UNLOCK();
}
uint32_t getProtection(uintptr_t addr)
{
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
uint32_t ret = memprot[idx];
PROT_LOCK();
uint32_t ret = PROT_GET(idx);
PROT_UNLOCK();
return ret;
}
void allocProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
{
PROT_LOCK();
addMapMem(addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
if(!memprot[i])
memprot[i] = prot;
PROT_SET_IF_0(i, prot);
}
PROT_UNLOCK();
}
void loadProtectionFromMap()
@@ -869,7 +973,7 @@ void loadProtectionFromMap()
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(sscanf(buf, "%x-%x %c%c%c", &s, &e, &r, &w, &x)==5) {
if(current<s) {
removeMapMem(current, s-1);
current = e;
@@ -901,7 +1005,7 @@ static void* findBlockHinted(void* hint, size_t size)
return hint;
if(addr>=h && end-addr+1>=size)
return (void*)addr;
if(end>=0xc0000000 & h<0xc0000000)
if(end>=0xc0000000 && h<0xc0000000)
return NULL;
m = m->next;
}
@@ -918,15 +1022,63 @@ void* find32bitBlock(size_t size)
return ret;
}
#ifdef DYNAREC
int IsInHotPage(uintptr_t addr) {
if(addr<=(1LL<<48))
return 0;
int idx = (addr>>MEMPROT_SHIFT);
if(!hotpages[idx])
return 0;
// decrement hot
arm_lock_decifnot0b(&hotpages[idx]);
return 1;
}
int AreaInHotPage(uintptr_t start, uintptr_t end_) {
uintptr_t idx = (start>>MEMPROT_SHIFT);
uintptr_t end = (end_>>MEMPROT_SHIFT);
if(end<idx) { // memory addresses higher than 48bits are not tracked
return 0;
}
int ret = 0;
for (uintptr_t i=idx; i<=end; ++i) {
if(hotpages[idx]) {
// decrement hot
arm_lock_decifnot0b(&hotpages[idx]);
ret = 1;
}
}
if(ret && box86_dynarec_log>LOG_INFO)
dynarec_log(LOG_DEBUG, "BOX86: AreaInHotPage %p-%p\n", (void*)start, (void*)end_);
return ret;
}
void AddHotPage(uintptr_t addr) {
int idx = (addr>>MEMPROT_SHIFT);
arm_lock_storeb(&hotpages[idx], box86_dynarec_hotpage);
}
#endif
int unlockCustommemMutex()
{
int ret = 0;
int i = 0;
#ifdef DYNAREC
void* tid = (void*)GetTID();
#define GO(A, B) \
i = (arm_lock_storeifref2(&A, NULL, (void*)tid)==tid); \
if(i) { \
ret|=(1<<B); \
}
#else
#define GO(A, B) \
i = checkUnlockMutex(&A); \
if(i) { \
ret|=(1<<B); \
}
#endif
GO(mutex_blocks, 0)
#undef GO
return ret;
@@ -936,7 +1088,7 @@ void relockCustommemMutex(int locks)
{
#define GO(A, B) \
if(locks&(1<<B)) \
pthread_mutex_lock(&A); \
mutex_lock(&A); \
GO(mutex_blocks, 0)
#undef GO
@@ -944,12 +1096,16 @@ void relockCustommemMutex(int locks)
static void init_mutexes(void)
{
#ifdef DYNAREC
arm_lock_stored(&mutex_blocks, 0);
#else
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mutex_blocks, &attr);
pthread_mutexattr_destroy(&attr);
#endif
}
static void atfork_child_custommem(void)
@@ -960,6 +1116,7 @@ static void atfork_child_custommem(void)
void init_custommem_helper(box86context_t* ctx)
{
(void)ctx;
if(inited) // already initialized
return;
inited = 1;
@@ -985,34 +1142,41 @@ void init_custommem_helper(box86context_t* ctx)
void fini_custommem_helper(box86context_t *ctx)
{
(void)ctx;
if(!inited)
return;
inited = 0;
#ifdef DYNAREC
if(box86_dynarec) {
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
for (int i=0; i<mmapsize; ++i) {
if(mmaplist[i].block)
#ifdef USE_MMAP
munmap(mmaplist[i].block, mmaplist[i].size);
#else
box_free(mmaplist[i].block);
#endif
if(mmaplist[i].dblist) {
kh_destroy(dynablocks, mmaplist[i].dblist);
mmaplist[i].dblist = NULL;
}
if(mmaplist[i].helper) {
box_free(mmaplist[i].helper);
mmaplist[i].helper = NULL;
mmaplist_t* head = mmaplist;
mmaplist = NULL;
while(head) {
for (int i=0; i<NCHUNK; ++i) {
if(head->chunks[i].block)
#ifdef USE_MMAP
munmap(head->chunks[i].block, head->chunks[i].size);
#else
box_free(head->chunks[i].block);
#endif
if(head->chunks[i].dblist) {
kh_destroy(dynablocks, head->chunks[i].dblist);
head->chunks[i].dblist = NULL;
}
if(head->chunks[i].helper) {
box_free(head->chunks[i].helper);
head->chunks[i].helper = NULL;
}
}
mmaplist_t *old = head;
head = head->next;
free(old);
}
if(dblist_oversized) {
kh_destroy(dynablocks, dblist_oversized);
dblist_oversized = NULL;
}
mmapsize = 0;
mmapcap = 0;
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
uintptr_t idx = 0;
uintptr_t end = ((0xFFFFFFFF)>>DYNAMAP_SHIFT);
@@ -1034,7 +1198,9 @@ void fini_custommem_helper(box86context_t *ctx)
box_free(p_blocks[i].block);
#endif
box_free(p_blocks);
#ifndef DYNAREC
pthread_mutex_destroy(&mutex_blocks);
#endif
while(mapmem) {
mapmem_t *tmp = mapmem;
mapmem = mapmem->next;
+4
View File
@@ -820,6 +820,8 @@ Op is 20-27
#define VLD1_32(Dd, Rn) EMIT(Vxx1gen(1, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b0111, 2, 0, 15))
// Load [Rn]! => Dd. Align is 4
#define VLD1_32_W(Dd, Rn) EMIT(Vxx1gen(1, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b0111, 2, 0, 13))
// Load [Rn]! => Dd. Align is 8
#define VLD1_64_W(Dd, Rn) EMIT(Vxx1gen(1, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b0111, 3, 0, 13))
// Load [Rn]! => Dd/Dd+1. Align is 4
#define VLD1Q_32_W(Dd, Rn) EMIT(Vxx1gen(1, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b1010, 2, 0, 13))
// Load [Rn, Rm]! => Dd/Dd+1. If Rm==15, no writeback, Rm ignored, else writeback Rn <- Rn+Rm. Align is 4
@@ -841,6 +843,8 @@ Op is 20-27
// Store [Rn]! => Dd. Align is 4
#define VST1_32_W(Dd, Rn) EMIT(Vxx1gen(0, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b0111, 2, 0, 13))
// Store [Rn]! => Dd. Align is 8
#define VST1_64_W(Dd, Rn) EMIT(Vxx1gen(0, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b0111, 3, 0, 13))
// Store [Rn] => Dd/Dd+1. Align is 4
#define VST1Q_32(Dd, Rn) EMIT(Vxx1gen(0, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b1010, 2, 0, 15))
// Store [Rn]! => Dd/Dd+1. Align is 4
+101 -10
View File
@@ -16,7 +16,14 @@
.global arm_lock_xchg
.global arm_lock_storeifnull
.global arm_lock_storeifref
.global arm_lock_storeifref2
.global arm_lock_decifnot0b
.global arm_lock_incb
.global arm_lock_incif0b
.global arm_lock_stored
.global arm_lock_storeb
.global arm_lock_storeif0b
.global arm_lock_readb
arm_lock_read_b:
// address is r0, return is r0
@@ -83,33 +90,117 @@ arm_lock_xchg:
bx lr
arm_lock_storeifnull:
// address is r0, value is r1, r1 store to r0 only if [r0] is 0. return new [r0] value (so r1 or old value)
// address is r0, value is r1, r1 store to r0 only if [r0] is 0. return old [r0] value
// r0 needs to be aligned
dmb ish
ldrex r2, [r0]
cmp r2, #0
bne arm_lock_storeifnull_exit
mov r2, r1
strex r3, r2, [r0]
strex r3, r1, [r0]
cmp r3, #1
beq arm_lock_storeifnull
arm_lock_storeifnull_exit:
mov r0, r2
bx lr
arm_lock_storeifref2:
dmb ish
arm_lock_storeifref2_loop:
// address is r0, value is r1, r1 store to r0 only if [r0] is r2. return old [r0] value (so r2 or old value)
ldrex r3, [r0]
cmp r3, r2
movne r0, r3
bne arm_lock_storeifref2_exit
strex r3, r1, [r0]
cmp r3, #1
beq arm_lock_storeifref_loop
mov r0, r2
arm_lock_storeifref2_exit:
bx lr
arm_lock_storeifref:
push {r4}
dmb ish
arm_lock_storeifref_loop:
// address is r0, value is r1, r1 store to r0 only if [r0] is r2. return new [r0] value (so r1 or old value)
ldrex r3, [r0]
cmp r3, r2
movne r0, r3
bne arm_lock_storeifref_exit
mov r3, r1
strex r4, r3, [r0]
cmp r4, #1
strex r3, r1, [r0]
cmp r3, #1
beq arm_lock_storeifref_loop
mov r0, r1
arm_lock_storeifref_exit:
mov r0, r3
pop {r4}
bx lr
arm_lock_decifnot0b:
dmb ish
arm_lock_decifnot0b_0:
ldrexb r1, [r0]
cmp r1, #0
subne r3, r1, #1
moveq r3, r1
strexb r2, r3, [r0]
cmp r2, #1
beq arm_lock_decifnot0b_0
dmb ish
mov r0, r1
bx lr
arm_lock_incb:
dmb ish
arm_lock_incb_0:
ldrexb r1, [r0]
add r1, r1, #1
strexb r2, r1, [r0]
cmp r2, #1
beq arm_lock_incb_0
arm_lock_incb_exit:
dmb ish
bx lr
arm_lock_incif0b:
dmb ish
arm_lock_incif0b_0:
ldrexb r1, [r0]
cmp r1, #0
addeq r3, r1, #1
movne r3, r1
strexb r2, r3, [r0]
cmp r2, #1
beq arm_lock_incif0b_0
dmb ish
mov r0, r1
bx lr
arm_lock_stored:
dmb ish
str r1, [r0]
dmb ish
bx lr
arm_lock_storeb:
dmb ish
strb r1, [r0]
dmb ish
bx lr
arm_lock_storeif0b:
dmb ish
arm_lock_storeif0b_0:
ldrexb r2, [r0]
cmp r2, #0
bne arm_lock_storeif0b_exit
strexb r3, r1, [r0]
cmp r3, #1
beq arm_lock_storeif0b_0
mov r2, #0
dmb ish
arm_lock_storeif0b_exit:
mov r0, r2
bx lr
arm_lock_readb:
dmb ish
ldrb r0, [r0]
bx lr
+25 -1
View File
@@ -25,10 +25,34 @@ extern int arm_lock_write_dd(uint32_t a, uint32_t b, void* addr);
// Atomically exchange value at [p] with val, return old p
extern uintptr_t arm_lock_xchg(void* p, uintptr_t val);
// Atomically store value to [p] only if [p] is NULL. Return new [p] value (so val or old)
// Atomically store value to [p] only if [p] is NULL. Return old [p] value
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 ref. Return old [p] value
extern void* arm_lock_storeifref2(void* p, void* val, void* ref);
// decrement atomicaly the byte at [p] (but only if p not 0). Return old [p] value
extern int arm_lock_decifnot0b(void*p);
// increment atomicaly the byte at [p]
extern void arm_lock_incb(void*p);
// increment atomicaly the byte at [p] only if it was 0. Return the old value of [p]
extern int arm_lock_incif0b(void*p);
// atomic store (with memory barrier)
extern void arm_lock_stored(void*p, uint32_t d);
// atomic store (with memory barrier)
extern void arm_lock_storeb(void*p, uint8_t b);
// atomic store (with memory barrier) only if it was 0. Return the old value of [p]
extern int arm_lock_storeif0b(void*p, uint8_t b);
// atomic load (with memory barrier)
extern int arm_lock_readb(void*p);
#endif //__ARM_LOCK_HELPER__H__
+23 -15
View File
@@ -20,6 +20,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"
@@ -64,7 +65,7 @@ void FreeDynablock(dynablock_t* db, int need_lock)
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);
if(need_lock)
pthread_mutex_lock(&my_context->mutex_dyndump);
mutex_lock(&my_context->mutex_dyndump);
db->done = 0;
db->gone = 1;
// remove from direct if there
@@ -91,7 +92,7 @@ void FreeDynablock(dynablock_t* db, int need_lock)
}
box_free(db);
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
mutex_unlock(&my_context->mutex_dyndump);
}
}
@@ -274,10 +275,9 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
if (!*created)
return block;
pthread_mutex_lock(&my_context->mutex_dyndump);
if(!dynablocks->direct) {
dynablock_t** p = (dynablock_t**)box_calloc(dynablocks->textsz, sizeof(dynablock_t*));
if(arm_lock_storeifnull(&dynablocks->direct, p)!=p)
if(arm_lock_storeifnull(&dynablocks->direct, p)!=NULL)
box_free(p); // someone already create the direct array, too late...
}
@@ -286,8 +286,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
block = (dynablock_t*)box_calloc(1, sizeof(dynablock_t));
block->parent = dynablocks;
dynablock_t* tmp = (dynablock_t*)arm_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
pthread_mutex_unlock(&my_context->mutex_dyndump);
dynablock_t* tmp = (dynablock_t*)arm_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], block, NULL);
if(tmp != block) {
// a block appeard!
box_free(block);
@@ -312,6 +311,8 @@ void cancelFillBlock()
*/
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current, int need_lock)
{
if(hasAlternate((void*)addr))
return NULL;
// try the quickest way first: get parent of current and check if ok!
dynablocklist_t *dynablocks = NULL;
dynablock_t* block = NULL;
@@ -335,23 +336,26 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
return block;
int created = create;
if(need_lock)
mutex_lock(&my_context->mutex_dyndump);
block = AddNewDynablock(dynablocks, addr, &created);
if(!created)
if(!created) {
if(need_lock)
mutex_unlock(&my_context->mutex_dyndump);
return block; // existing block...
}
// 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)
pthread_mutex_unlock(&my_context->mutex_dyndump);
mutex_unlock(&my_context->mutex_dyndump);
return NULL;
}
void* ret = FillBlock(block, filladdr);
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
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);
@@ -393,7 +397,11 @@ dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t**
{
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))
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;
}
if(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;
@@ -414,7 +422,7 @@ dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t**
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault(father->sons[i]->x86_addr, father->sons[i]->block);
}
pthread_mutex_unlock(&my_context->mutex_dyndump);
mutex_unlock(&my_context->mutex_dyndump);
}
return db;
}
@@ -425,7 +433,7 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t 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))) {
if(pthread_mutex_trylock(&my_context->mutex_dyndump))
if(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;
@@ -443,7 +451,7 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault(father->sons[i]->x86_addr, father->sons[i]->block);
}
pthread_mutex_unlock(&my_context->mutex_dyndump);
mutex_unlock(&my_context->mutex_dyndump);
}
return db;
}
+2 -2
View File
@@ -4,8 +4,8 @@
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 {
+45 -45
View File
@@ -298,12 +298,15 @@ static void fillPredecessors(dynarec_arm_t* dyn)
}
// 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))
if((i!=dyn->size-1) && dyn->insts[i].x86.has_next)
dyn->insts[i+1].pred[dyn->insts[i+1].pred_sz++] = i;
if(dyn->insts[i].x86.jmp && dyn->insts[i].x86.jmp_insts!=-1)
dyn->insts[dyn->insts[i].x86.jmp_insts].pred[dyn->insts[dyn->insts[i].x86.jmp_insts].pred_sz++] = i;
if(dyn->insts[i].x86.jmp && (dyn->insts[i].x86.jmp_insts!=-1)) {
int j = dyn->insts[i].x86.jmp_insts;
dyn->insts[j].pred[dyn->insts[j].pred_sz++] = i;
}
}
}
// updateNeed goes backward, from last intruction to top
@@ -358,7 +361,7 @@ uintptr_t arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
uintptr_t arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
uintptr_t arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
__thread void* current_helper = NULL;
void* current_helper = NULL;
void CancelBlock()
{
@@ -373,16 +376,35 @@ void CancelBlock()
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->block, helper->dynablock->size);
}
void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
block->isize = 0;
block->done = 0;
block->size = 0;
block->block = NULL;
block->need_test = 0;
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(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_DEBUG, "Asked to fill a block in fobidden zone\n");
return NULL;
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;
}
if(current_helper) {
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock at %p as anothor one is going on\n", (void*)addr);
return NULL;
}
// protect the 1st page
protectDB(addr, 1);
// init the helper
dynarec_arm_t helper = {0};
current_helper = &helper;
@@ -403,14 +425,22 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
CancelBlock();
return (void*)block;
}
if(!isprotectedDB(addr, 1)) {
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
AddHotPage(addr);
CancelBlock();
return NULL;
}
// already protect the block and compute hash signature
protectDB(addr, end-addr); //end is 1byte after actual end
// protect the block of it goes over the 1st page
if((addr&~box86_pagesize)!=(end&~box86_pagesize)) // need to protect some other pages too
protectDB(addr, end-addr); //end is 1byte after actual end
uint32_t hash = X31_hash_code((void*)addr, end-addr);
// 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) {
if(j<start || j>=end || j==helper.insts[i].x86.addr) {
helper.insts[i].x86.jmp_insts = -1;
helper.insts[i].x86.need_after |= X_PEND;
} else {
@@ -427,44 +457,7 @@ 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
}
}
}*/
int pos = helper.size;
while (pos>=0)
pos = updateNeed(&helper, pos, 0);
@@ -539,8 +532,15 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
if(block->hash != hash) {
dynarec_log(LOG_INFO, "Warning, a block changed while beeing processed hash(%p:%d)=%x/%x\n", block->x86_addr, block->x86_size, block->hash, hash);
CancelBlock();
AddHotPage(addr);
return NULL;
}
if(!isprotectedDB(addr, end-addr)) {
dynarec_log(LOG_DEBUG, "Warning, block unprotected while beeing processed %p:%zd, cancelling\n", block->x86_addr, block->x86_size);
AddHotPage(addr);
block->need_test = 1;
//protectDB(addr, end-addr);
}
// fill sons if any
dynablock_t** sons = NULL;
int sons_size = 0;
+25 -26
View File
@@ -581,16 +581,12 @@ 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:
@@ -665,7 +661,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
i32 = F32S;
if(PK(0)==0xC3) {
MESSAGE(LOG_DUMP, "PUSH then RET, using indirect\n");
MOV32(x3, ip+1);
MOV32(x3, addr-4);
LDR_IMM9(x1, x3, 0);
PUSH1(x1);
} else {
@@ -1015,7 +1011,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFI(eb1, x14, eb2*8, 8);
} else {
GETGB(x14);
DMB_ISH();
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
// do the swap with exclusive locking
@@ -1025,7 +1021,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
BFI(gb1, x1, gb2*8, 8);
DMB_ISH();
SMDMB();
}
break;
case 0x87:
@@ -1041,7 +1037,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
} else {
GETGD;
DMB_ISH();
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
if(!fixedaddress) {
TSTS_IMM8(ed, 3);
@@ -1065,7 +1061,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(!fixedaddress) {
MARK2;
}
DMB_ISH();
SMDMB();
MOV_REG(gd, x1);
}
break;
@@ -1089,7 +1085,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
STRB_IMM9(gd, ed, fixedaddress);
if(lock) {DMB_ISH();}
SMWRITELOCK(lock);
}
break;
case 0x89:
@@ -1101,7 +1097,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
STR_IMM9(gd, ed, fixedaddress);
if(lock) {DMB_ISH();}
SMWRITELOCK(lock);
}
break;
case 0x8A:
@@ -1123,10 +1119,10 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
if(box86_dynarec_strongmem &&
(dyn->insts[ninst].x86.barrier || !ninst || (box86_dynarec_strongmem>1) || (ninst && dyn->insts[ninst-1].x86.barrier))) {
DMB_ISH();
SMDMB();
}
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, &lock);
if(lock) {DMB_ISH();}
SMREADLOCK(lock);
LDRB_IMM9(x14, wback, fixedaddress);
ed = x14;
}
@@ -1140,10 +1136,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
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();
}
SMREADLOCK(lock);
LDR_IMM9(gd, ed, fixedaddress);
}
break;
@@ -1157,6 +1150,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDRH_REG(x3, xEmu, x3);
STRH_IMM8(x3, ed, fixedaddress);
SMWRITE2();
}
break;
case 0x8D:
@@ -1284,12 +1278,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
u32 = F32;
MOV32(x2, u32);
STRB_IMM9(xEAX, x2, 0);
SMWRITE();
break;
case 0xA3:
INST_NAME("MOV Od, EAX");
u32 = F32;
MOV32(x2, u32);
STR_IMM9(xEAX, x2, 0);
SMWRITE();
break;
case 0xA4:
INST_NAME("MOVSB");
@@ -1522,7 +1518,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; // no SBACK here because ret value is ed directly
WBACK;
break;
case 3:
INST_NAME("RCR Ed, Ib");
@@ -1553,13 +1549,13 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFC_COND(cCC, xFlags, F_CF, 1);
}
WBACK; // no SBACK here because ed has been used all along and not x1
WBACK;
} 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; // no SBACK here because ret value is ed directly
WBACK;
}
break;
case 4:
@@ -1633,7 +1629,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
u8 = F8;
MOVW(x3, u8);
STRB_IMM9(x3, ed, fixedaddress);
if(lock) {DMB_ISH();}
SMWRITELOCK(lock);
}
break;
case 0xC7:
@@ -1648,7 +1644,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
i32 = F32S;
MOV32(x3, i32);
STR_IMM9(x3, ed, fixedaddress);
if(lock) {DMB_ISH();}
SMWRITELOCK(lock);
}
break;
@@ -1719,6 +1715,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xCD:
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
SMEND();
if(PK(0)==0x80) {
INST_NAME("Syscall");
u8 = F8;
@@ -1884,7 +1881,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; // no SBACK here because ret value is ed directly
WBACK;
break;
case 3:
INST_NAME("RCR Ed, 1");
@@ -1994,7 +1991,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; // no SBACK here because ret value is ed directly
WBACK;
break;
case 3:
INST_NAME("RCR Ed, CL");
@@ -2004,7 +2001,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; // no SBACK here because ret value is ed directly
WBACK;
break;
case 4:
case 6:
@@ -2065,6 +2062,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xD7:
INST_NAME("XLAT");
UBFX(x1, xEAX, 0, 8); // x1 = AL
SMREAD();
LDRB_REG_LSL_IMM5(x1, xEBX, x1, 0); //x1 = byte ptr[EBX+AL]
BFI(xEAX, x1, 0, 8);
break;
@@ -2841,7 +2839,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 4: // JMP Ed
INST_NAME("JMP Ed");
BARRIER(BARRIER_FULL);
READFLAGS(X_PEND);
BARRIER(BARRIER_FLOAT);
GETEDH(xEIP);
jump_to_next(dyn, 0, ed, ninst);
*need_epilog = 0;
+69 -10
View File
@@ -31,6 +31,7 @@
if((nextop&0xC0)==0xC0) { \
a = sse_get_reg(dyn, ninst, x1, nextop&7, w); \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL); \
a = fpu_get_scratch_quad(dyn); \
VLD1Q_64(a, ed); \
@@ -42,6 +43,7 @@
if((nextop&0xC0)==0xC0) { \
a = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7); \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL); \
a = fpu_get_scratch_double(dyn); \
VLD1_64(a, ed); \
@@ -49,6 +51,7 @@
#define PUTEM(a) \
if((nextop&0xC0)!=0xC0) { \
VST1_64(a, ed); \
SMWRITE2(); \
}
uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
@@ -112,6 +115,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
//LDRD also have alignment requirements
@@ -140,6 +144,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOVfrV_D(x2, x3, v0+1);
STR_IMM9(x2, ed, fixedaddress+8);
STR_IMM9(x3, ed, fixedaddress+12);
SMWRITE2();
}
break;
case 0x12:
@@ -152,6 +157,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);
SMREAD();
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);
@@ -170,12 +176,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(parity) {
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
SMWRITE2();
} else {
VMOVfrV_D(x2, x3, v0);
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);
SMWRITE2();
}
}
break;
@@ -212,6 +219,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);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1_64(v0+1, ed);
}
@@ -228,12 +236,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(parity) {
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
SMWRITE2();
} else {
VMOVfrV_D(x2, x3, v0+1);
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);
SMWRITE2();
}
}
break;
@@ -278,6 +287,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);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1Q_32(v0, ed);
}
@@ -293,6 +303,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1Q_32(v0, ed);
SMWRITE2();
}
break;
case 0x2A:
@@ -303,6 +314,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_double(dyn);
VLD1_32(v1, ed);
@@ -330,6 +342,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_double(dyn);
VLD1_32(v1, ed);
@@ -344,6 +357,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_double(dyn);
VLD1_32(v1, ed);
@@ -383,6 +397,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
s0 = d0*2;
} else {
SMREAD();
parity = getedparity(dyn, ninst, addr, nextop, 2);
s0 = fpu_get_scratch_single(dyn);
if(parity) {
@@ -452,6 +467,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= reg
REV(gd, xEAX+(nextop&7));
} else { // mem <= reg
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(gd, ed, fixedaddress);
REV(gd, gd);
@@ -467,6 +483,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
REV(x1, gd);
STR_IMM9(gd, ed, fixedaddress);
SMWRITE();
}
break;
@@ -508,6 +525,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 { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL); \
LDR_IMM9_COND(YES, gd, ed, fixedaddress); \
}
@@ -620,6 +638,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
SMREAD();
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);
@@ -1005,6 +1024,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
d0 = fpu_get_scratch_quad(dyn);
VLD1_16(d0, ed);
@@ -1018,6 +1038,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
if((nextop&0xC0)!=0xC0) {
VST1_16(d0, ed);
SMWRITE2();
}
}
break;
@@ -1026,6 +1047,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
d0 = fpu_get_scratch_quad(dyn);
VLD1_16(d0, ed);
@@ -1036,6 +1058,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
if((nextop&0xC0)!=0xC0) {
VST1_16(d0, ed);
SMWRITE2();
}
break;
case 6:
@@ -1043,6 +1066,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
d0 = fpu_get_scratch_quad(dyn);
VLD1_16(d0, ed);
@@ -1056,6 +1080,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
if((nextop&0xC0)!=0xC0) {
VST1_16(d0, ed);
SMWRITE2();
}
}
break;
@@ -1065,6 +1090,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x72:
nextop = F8;
SMREAD();
GETEM(v0);
switch((nextop>>3)&7) {
case 2:
@@ -1106,6 +1132,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x73:
nextop = F8;
GETEM(v0);
SMREAD();
switch((nextop>>3)&7) {
case 2:
INST_NAME("PSRLQ Em, Ib");
@@ -1171,6 +1198,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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, NULL);
STR_IMM9(x2, ed, fixedaddress);
SMWRITE2();
}
break;
case 0x7F:
@@ -1185,11 +1213,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VSTR_64(v0, ed, fixedaddress);
SMWRITE2();
} else {
VMOVfrV_D(x2, x3, v0);
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);
SMWRITE2();
}
}
break;
@@ -1307,6 +1337,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
, cNE, cEQ, X_SF|X_OF|X_ZF)
break;
#undef GO
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
GETFLAGS; \
@@ -1321,8 +1352,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);\
STRB_IMM9(x3, ed, fixedaddress); \
SMWRITE(); \
}
case 0x90:
INST_NAME("SETO Eb");
GO( TSTS_IMM8_ROR(xFlags, 0b10, 0x0b)
@@ -1443,6 +1474,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 {
SMREAD();
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;
@@ -1499,6 +1531,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
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;
@@ -1517,6 +1550,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ORR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 0xAC:
@@ -1544,15 +1578,15 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// xFENCE -> DMB is approximative, but should be good enough
if((nextop&0xF8)==0xE8) {
INST_NAME("LFENCE");
DMB_ISH();
SMDMB();
} else
if((nextop&0xF8)==0xF0) {
INST_NAME("MFENCE");
DMB_ISH();
SMDMB();
} else
if((nextop&0xF8)==0xF8) {
INST_NAME("SFENCE");
DMB_ISH();
SMDMB();
} else {
switch((nextop>>3)&7) {
case 0:
@@ -1584,6 +1618,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("LDMXCSR Md");
GETED;
STR_IMM9(ed, xEmu, offsetof(x86emu_t, mxcsr));
if(box86_sse_flushto0) {
VMRS(x14); // get fpscr
MOV_REG_LSR_IMM5(x3, ed, 15); // get FZ bit
BFI(x14, x3, 24, 1); // inject FZ bit
VMSR(x14); // put new fpscr
}
break;
case 3:
INST_NAME("STMXCSR Md");
@@ -1674,6 +1714,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
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;
@@ -1692,6 +1733,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
XOR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
break;
@@ -1706,6 +1748,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
LDRB_IMM9(gd, ed, fixedaddress);
}
@@ -1718,6 +1761,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(gd, ed, fixedaddress);
}
@@ -1734,6 +1778,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x1, wback, fixedaddress);
ed = x1;
@@ -1754,6 +1799,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x1, wback, fixedaddress);
ed = x1;
@@ -1774,6 +1820,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 6:
@@ -1784,6 +1831,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x1, wback, fixedaddress);
ed = x1;
@@ -1804,6 +1852,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 7:
@@ -1814,6 +1863,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x1, wback, fixedaddress);
ed = x1;
@@ -1835,6 +1885,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
break;
@@ -1852,6 +1903,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
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;
@@ -1868,6 +1920,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
XOR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 0xBC:
@@ -1924,6 +1977,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRSB_IMM8(gd, ed, fixedaddress);
}
@@ -1936,6 +1990,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRSH_IMM8(gd, ed, fixedaddress);
}
@@ -1956,12 +2011,11 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGD;
GETED;
MOV_REG(x1, gd);
if(gd!=ed) {
XOR_REG_LSL_IMM5(gd, gd, ed, 0); // swap gd, ed
XOR_REG_LSL_IMM5(ed, gd, ed, 0);
XOR_REG_LSL_IMM5(gd, gd, ed, 0);
MOV_REG(gd, ed);
}
emit_add32(dyn, ninst, ed, gd, x3, x14);
emit_add32(dyn, ninst, ed, x1, x3, x14);
WBACK;
break;
case 0xC2:
@@ -2016,6 +2070,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, NULL);
u8 = (F8)&3;
VLD1LANE_16(d0, wback, u8);
@@ -2030,6 +2085,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255-8, 0, 0, NULL);
u8 = (F8)&3;
LDRH_IMM8(gd, wback, fixedaddress+u8*2);
@@ -2043,6 +2099,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGX(v0, 1);
v2 = fpu_get_scratch_double(dyn);
if((nextop&0xC0)!=0xC0) {
SMREAD();
// from memory
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 0, NULL);
u8 = F8;
@@ -2194,6 +2251,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);
SMREAD();
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);
@@ -2211,6 +2269,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOVW(x1, 0);
MARK3;
BFI(xFlags, x1, F_ZF, 1);
SMWRITE();
break;
default:
DEFAULT;
+16
View File
@@ -103,6 +103,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
STRH_REG(gd, x14, ed);
SMWRITE2();
}
break;
@@ -114,6 +115,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
SMREAD();
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
}
@@ -129,6 +131,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
POP1(x2);
STR_REG_LSL_IMM5(x2, x1, x14, 0);
SMWRITE2();
}
break;
@@ -140,6 +143,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
SMREAD();
LDR_IMM9(xEAX, x1, 0);
break;
@@ -152,6 +156,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
STR_IMM9(xEAX, x1, 0);
SMWRITE2();
break;
case 0xFF:
@@ -163,6 +168,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
SMREAD();
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
@@ -187,6 +193,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
STR_REG_LSL_IMM5(gd, ed, x14, 0);
SMWRITE2();
}
break;
@@ -198,6 +205,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
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
}
@@ -213,6 +221,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
POP1(x2);
STR_REG_LSL_IMM5(x2, ed, x14, 0);
SMWRITE2();
}
break;
@@ -224,6 +233,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDRB_IMM9(xEAX, x1, i32);
} else {
MOV32(x2, i32);
SMREAD();
LDRB_REG_LSL_IMM5(xEAX, x1, x2, 0);
}
break;
@@ -235,6 +245,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDR_IMM9(xEAX, x1, i32);
} else {
MOV32(x2, i32);
SMREAD();
LDR_REG_LSL_IMM5(xEAX, x1, x2, 0);
}
break;
@@ -247,6 +258,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
MOV32(x2, i32);
STRB_REG_LSL_IMM5(xEAX, x1, x2, 0);
SMWRITE2();
}
break;
case 0xA3:
@@ -255,9 +267,11 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
i32 = F32S;
if(i32>-4096 && i32<4096) {
STR_IMM9(xEAX, x1, i32);
SMWRITE2();
} else {
MOV32(x2, i32);
STR_REG_LSL_IMM5(xEAX, x2, x1, 0);
SMWRITE2();
}
break;
@@ -283,6 +297,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
i32 = F32S;
MOV32(x3, i32);
STR_REG_LSL_IMM5(x3, ed, x14, 0);
SMWRITE2();
}
break;
@@ -321,6 +336,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
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
+53 -39
View File
@@ -50,7 +50,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGD;
GETEDO2(x14);
emit_add32(dyn, ninst, ed, gd, x3, x14);
WBACK;
WBACK2;
break;
case 0x03:
@@ -97,7 +97,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGD;
GETEDO2(x14);
emit_and32(dyn, ninst, ed, gd, x3, x14);
WBACK;
WBACK2;
break;
case 0x23:
@@ -118,7 +118,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGD;
GETEDO2(x14);
emit_sub32(dyn, ninst, ed, gd, x3, x14);
WBACK;
WBACK2;
break;
case 0x2B:
@@ -139,7 +139,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGD;
GETEDO2(x14);
emit_xor32(dyn, ninst, gd, ed, x3, x14);
WBACK;
WBACK2;
break;
case 0x33:
@@ -202,7 +202,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEBO(x1);
u8 = F8;
emit_add8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
EBBACK2;
break;
case 1: //OR
INST_NAME("OR GS:Eb, Ib");
@@ -211,7 +211,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEBO(x1);
u8 = F8;
emit_or8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
EBBACK2;
break;
case 2: //ADC
INST_NAME("ADC GS:Eb, Ib");
@@ -221,7 +221,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEBO(x1);
u8 = F8;
emit_adc8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
EBBACK2;
break;
case 3: //SBB
INST_NAME("SBB GS:Eb, Ib");
@@ -231,7 +231,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEBO(x1);
u8 = F8;
emit_sbb8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
EBBACK2;
break;
case 4: //AND
INST_NAME("AND GS:Eb, Ib");
@@ -240,7 +240,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEBO(x1);
u8 = F8;
emit_and8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
EBBACK2;
break;
case 5: //SUB
INST_NAME("SUB GS:Eb, Ib");
@@ -249,7 +249,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEBO(x1);
u8 = F8;
emit_sub8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
EBBACK2;
break;
case 6: //XOR
INST_NAME("XOR GS:Eb, Ib");
@@ -258,7 +258,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEBO(x1);
u8 = F8;
emit_xor8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
EBBACK2;
break;
case 7: //CMP
INST_NAME("CMP GS:Eb, Ib");
@@ -290,7 +290,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
emit_add32c(dyn, ninst, ed, i32, x3, x14);
WBACK;
WBACK2;
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("OR Ed, Id");} else {INST_NAME("OR Ed, Ib");}
@@ -299,7 +299,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
emit_or32c(dyn, ninst, ed, i32, x3, x14);
WBACK;
WBACK2;
break;
case 2: //ADC
if(opcode==0x81) {INST_NAME("ADC Ed, Id");} else {INST_NAME("ADC Ed, Ib");}
@@ -309,7 +309,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
emit_adc32c(dyn, ninst, ed, i32, x3, x14);
WBACK;
WBACK2;
break;
case 3: //SBB
if(opcode==0x81) {INST_NAME("SBB Ed, Id");} else {INST_NAME("SBB Ed, Ib");}
@@ -319,7 +319,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
emit_sbb32c(dyn, ninst, ed, i32, x3, x14);
WBACK;
WBACK2;
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("AND Ed, Id");} else {INST_NAME("AND Ed, Ib");}
@@ -328,7 +328,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
emit_and32c(dyn, ninst, ed, i32, x3, x14);
WBACK;
WBACK2;
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("SUB Ed, Id");} else {INST_NAME("SUB Ed, Ib");}
@@ -337,7 +337,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
emit_sub32c(dyn, ninst, ed, i32, x3, x14);
WBACK;
WBACK2;
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("XOR Ed, Id");} else {INST_NAME("XOR Ed, Ib");}
@@ -346,7 +346,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
emit_xor32c(dyn, ninst, ed, i32, x3, x14);
WBACK;
WBACK2;
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("CMP Ed, Id");} else {INST_NAME("CMP Ed, Ib");}
@@ -374,6 +374,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
STR_REG_LSL_IMM5(gd, ed, x14, 0);
SMWRITE2();
}
break;
@@ -385,6 +386,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
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
}
@@ -400,6 +402,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
POP1(x2);
STR_REG_LSL_IMM5(x2, ed, x14, 0);
SMWRITE2();
}
break;
@@ -407,6 +410,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV EAX, GS:Id");
grab_tlsdata(dyn, addr, ninst, x1);
i32 = F32S;
SMREAD();
if(i32>-4096 && i32<4096) {
LDR_IMM9(xEAX, x1, i32);
} else {
@@ -416,6 +420,16 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
case 0xA2:
INST_NAME("MOV GS:Od, AL");
grab_tlsdata(dyn, addr, ninst, x1);
u32 = F32;
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x2, x1, x2, 0);
STRB_IMM9(xEAX, x2, 0);
SMWRITE2();
break;
case 0xA3:
INST_NAME("MOV GS:Od, EAX");
grab_tlsdata(dyn, addr, ninst, x1);
@@ -423,6 +437,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x2, x1, x2, 0);
STR_IMM9(xEAX, x2, 0);
SMWRITE2();
break;
case 0xC6:
@@ -441,6 +456,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
u8 = F8;
MOVW(x3, u8);
STRB_REG_LSL_IMM5(x3, ed, x14, 0);
SMWRITE2();
}
break;
case 0xC7:
@@ -456,6 +472,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
i32 = F32S;
MOV32(x3, i32);
STR_REG_LSL_IMM5(x3, ed, x14, 0);
SMWRITE2();
}
break;
@@ -468,14 +485,14 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEDO2(x14);
emit_rol32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
WBACK2;
break;
case 1:
INST_NAME("ROR Ed, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEDO2(x14);
emit_ror32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
WBACK2;
break;
case 2:
INST_NAME("RCL Ed, 1");
@@ -484,10 +501,9 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_OF|X_CF, SF_SET);
MOVW(x2, 1);
GETEDO2(x14);
wb = ed;
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
CALL_(rcl32, ed, (1<<x14));
SBACK(wb);
CALL_(rcl32, ed, (1<<x2));
WBACK2;
break;
case 3:
INST_NAME("RCR Ed, 1");
@@ -495,10 +511,9 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
MOVW(x2, 1);
wb = ed;
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
CALL_(rcr32, ed, (1<<x14));
SBACK(wb);
CALL_(rcr32, ed, (1<<x2));
WBACK2;
break;
case 4:
case 6:
@@ -506,21 +521,21 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEDO2(x14);
emit_shl32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
WBACK2;
break;
case 5:
INST_NAME("SHR Ed, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEDO2(x14);
emit_shr32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
WBACK2;
break;
case 7:
INST_NAME("SAR Ed, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEDO2(x14);
emit_sar32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
WBACK2;
break;
}
break;
@@ -537,7 +552,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
RSB_IMM8(x3, x3, 0x20);
GETEDO2(x14);
MOV_REG_ROR_REG(ed, ed, x3);
WBACK;
WBACK2;
UFLAG_IF { // calculate flags directly
CMPS_IMM8(x3, 31);
B_MARK(cNE);
@@ -558,7 +573,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARK2(cEQ);
GETEDO2(x14);
MOV_REG_ROR_REG(ed, ed, x3);
WBACK;
WBACK2;
UFLAG_IF { // calculate flags directly
CMPS_IMM8(x3, 1);
B_MARK(cNE);
@@ -578,10 +593,9 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
AND_IMM8(x2, xECX, 0x1f);
wb = ed;
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
CALL_(rcl32, ed, (1<<x14));
SBACK(wb);
CALL_(rcl32, ed, (1<<x2));
WBACK2;
break;
case 3:
INST_NAME("RCR Ed, CL");
@@ -589,10 +603,9 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
AND_IMM8(x2, xECX, 0x1f);
wb = ed;
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
CALL_(rcr32, ed, (1<<x14));
SBACK(wb);
WBACK2;
break;
case 4:
case 6:
@@ -601,7 +614,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
AND_IMM8(x3, xECX, 0x1f);
GETEDO2(x14);
emit_shl32(dyn, ninst, ed, x3, x3, x14);
WBACK;
WBACK2;
break;
case 5:
INST_NAME("SHR Ed, CL");
@@ -609,7 +622,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
AND_IMM8(x3, xECX, 0x1f);
GETEDO2(x14);
emit_shr32(dyn, ninst, ed, x3, x3, x14);
WBACK;
WBACK2;
break;
case 7:
INST_NAME("SAR Ed, CL");
@@ -618,7 +631,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
UFLAG_OP12(ed, x3);
MOV_REG_ASR_REG(ed, ed, x3);
WBACK;
WBACK2;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar32);
break;
@@ -640,6 +653,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
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
+9 -3
View File
@@ -505,7 +505,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x87:
INST_NAME("XCHG Ew, Gw");
INST_NAME("(LOCK) XCHG Ew, Gw");
nextop = F8;
if((nextop&0xC0)==0xC0) {
GETGD;
@@ -518,6 +518,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
GETGD;
UXTH(x14, gd, 0);
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
#if 0
MARKLOCK;
@@ -531,6 +532,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDRH_IMM8(x1, ed, fixedaddress);
STRH_IMM8(x14, ed, fixedaddress);
#endif
SMDMB();
BFI(gd, x1, 0, 16);
}
break;
@@ -547,7 +549,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, &lock);
STRH_IMM8(gd, ed, fixedaddress);
if(lock) {DMB_ISH();}
SMWRITELOCK(lock);
}
break;
case 0x8B:
@@ -561,7 +563,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, &lock);
if(lock) {DMB_ISH();}
SMREADLOCK(lock);
LDRH_IMM8(x1, ed, fixedaddress);
BFI(gd, x1, 0, 16);
}
@@ -577,6 +579,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
STRH_IMM8(x1, ed, fixedaddress);
SMWRITE2();
}
break;
@@ -588,6 +591,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 {
SMREAD();
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]));
@@ -645,6 +649,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV, AX, Od");
u32 = F32;
MOV32(x2, u32);
SMREAD();
LDRH_IMM8(x2, x2, 0);
BFI(xEAX, x2, 0, 16);
break;
@@ -653,6 +658,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
u32 = F32;
MOV32(x2, u32);
STRH_IMM8(xEAX, x2, 0);
SMWRITE();
break;
case 0xA5:
INST_NAME("MOVSW");
+117 -39
View File
@@ -27,9 +27,10 @@
if((nextop&0xC0)==0xC0) { \
a = sse_get_reg(dyn, ninst, x1, nextop&7, w); \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL); \
a = fpu_get_scratch_quad(dyn); \
VLD1Q_8(a, ed); \
VLD1Q_8(a, ed); \
}
#define GETGX(a, w) \
gd = (nextop&0x38)>>3; \
@@ -70,6 +71,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
@@ -96,6 +98,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVfrV_D(x2, x3, v0+1);
STR_IMM9(x2, ed, fixedaddress+8);
STR_IMM9(x3, ed, fixedaddress+12);
SMWRITE2();
}
break;
case 0x12:
@@ -108,6 +111,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
return addr;
}
parity = getedparity(dyn, ninst, addr, nextop, 3);
SMREAD();
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0, ed, fixedaddress);
@@ -137,6 +141,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
SMWRITE2();
break;
case 0x14:
INST_NAME("UNPCKLPD Gx, Ex");
@@ -146,6 +151,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0+1, ed, fixedaddress);
}
@@ -159,6 +165,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023-4, 3, 0, NULL);
VLDR_64(v0+1, ed, fixedaddress+4);
}
@@ -173,6 +180,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
return addr;
}
parity = getedparity(dyn, ninst, addr, nextop, 3);
SMREAD();
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0+1, ed, fixedaddress); // vfpu opcode here
@@ -202,6 +210,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
SMWRITE2();
break;
case 0x1F:
@@ -222,6 +231,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1Q_32(v0, ed);
SMWRITE2();
}
break;
case 0x29:
@@ -235,6 +245,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1Q_32(v0, ed);
SMWRITE2();
}
break;
@@ -262,6 +273,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1Q_64(q1, ed);
v0 = q1;
@@ -469,6 +481,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 { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);\
LDRH_IMM8_COND(YES, x1, ed, fixedaddress); \
ed = x1; \
@@ -687,8 +700,26 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0);
// need rounding?
VCVTQ_S32_F32(v0, v1);
if(v0>15)
q0 = fpu_get_scratch_quad(dyn);
else
q0 = v0;
if(v1>15) {
q1 = fpu_get_scratch_quad(dyn);
VMOVQ(q1, v1);
} else
q1 = v1;
// need rounding!
//VCVTQ_S32_F32(v0, v1);
u8 = sse_setround(dyn, ninst, x1, x2, x14);
VCVTR_S32_F32(q0*2+0, q1*2+0);
VCVTR_S32_F32(q0*2+1, q1*2+1);
VCVTR_S32_F32(q0*2+2, q1*2+2);
VCVTR_S32_F32(q0*2+3, q1*2+3);
if(q0!=v0) {
VMOVQ(v0, q0);
}
x87_restoreround(dyn, ninst, u8);
break;
case 0x5C:
INST_NAME("SUBPD Gx, Ex");
@@ -893,6 +924,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0+1, ed, fixedaddress);
}
@@ -906,6 +938,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023-8, 3, 0, NULL);
VLDR_64(q0+1, ed, fixedaddress+8);
}
@@ -928,6 +961,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1Q_64(v0, ed);
@@ -1043,6 +1077,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVQ(v0, q0);
}
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
u8 = F8;
@@ -1071,6 +1106,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_16(q0, ed);
@@ -1084,6 +1120,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_16(q0, ed);
SMWRITE2();
}
}
break;
@@ -1092,6 +1129,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_16(q0, ed);
@@ -1102,6 +1140,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_16(q0, ed);
SMWRITE2();
}
break;
case 6:
@@ -1109,6 +1148,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_16(q0, ed);
@@ -1122,6 +1162,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_16(q0, ed);
SMWRITE2();
}
}
break;
@@ -1138,6 +1179,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_32(q0, ed);
@@ -1151,6 +1193,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_32(q0, ed);
SMWRITE2();
}
}
break;
@@ -1159,6 +1202,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_32(q0, ed);
@@ -1169,6 +1213,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_32(q0, ed);
SMWRITE2();
}
break;
case 6:
@@ -1176,6 +1221,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_32(q0, ed);
@@ -1189,6 +1235,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_32(q0, ed);
SMWRITE2();
}
}
break;
@@ -1204,6 +1251,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q0, ed);
@@ -1217,6 +1265,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_64(q0, ed);
SMWRITE2();
}
}
break;
@@ -1225,6 +1274,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q0, ed);
@@ -1240,6 +1290,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_64(q0, ed);
SMWRITE2();
}
}
break;
@@ -1248,6 +1299,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q0, ed);
@@ -1261,6 +1313,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_64(q0, ed);
SMWRITE2();
}
}
break;
@@ -1269,6 +1322,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q0, ed);
@@ -1284,6 +1338,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_64(q0, ed);
SMWRITE2();
}
}
break;
@@ -1325,6 +1380,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVfrDx_32(x2, v0, 0); // to avoid Bus Error, using regular store
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
SMWRITE2();
}
break;
case 0x7F:
@@ -1337,6 +1393,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1Q_32(v0, ed);
SMWRITE2();
}
break;
@@ -1349,6 +1406,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 {
SMREAD();
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;
@@ -1391,6 +1449,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 {
SMREAD();
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;
@@ -1407,6 +1466,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ORR_REG_LSL_REG(ed, ed, x1, x2);
if(wback) {
STRH_IMM8(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 0xAC:
@@ -1459,6 +1519,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 {
SMREAD();
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;
@@ -1475,6 +1536,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
XOR_REG_LSL_REG(ed, ed, x1, x2);
if(wback) {
STRH_IMM8(ed, wback, fixedaddress);
SMWRITE();
}
break;
@@ -1488,6 +1550,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
LDRB_IMM9(x1, ed, fixedaddress);
}
@@ -1501,6 +1564,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, ed, fixedaddress);
}
@@ -1517,6 +1581,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, wback, fixedaddress);
ed = x1;
@@ -1537,6 +1602,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, wback, fixedaddress);
ed = x1;
@@ -1555,6 +1621,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
if(wback) {
STRH_IMM8(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
break;
@@ -1566,6 +1633,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, wback, fixedaddress);
ed = x1;
@@ -1584,6 +1652,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
if(wback) {
STRH_IMM8(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
break;
@@ -1595,6 +1664,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, wback, fixedaddress);
ed = x1;
@@ -1612,6 +1682,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
if(wback) {
STRH_IMM8(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
break;
@@ -1629,6 +1700,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 {
SMREAD();
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;
@@ -1643,6 +1715,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
XOR_REG_LSL_REG(ed, ed, x1, x2);
if(wback) {
STRH_IMM8(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 0xBC:
@@ -1688,6 +1761,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRSB_IMM8(x1, ed, fixedaddress);
}
@@ -1759,6 +1833,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, NULL);
u8 = (F8)&7;
VLD1LANE_16(v0+(u8/4), wback, u8&3);
@@ -1773,6 +1848,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255-14, 0, 0, NULL);
u8 = (F8)&7;
LDRH_IMM8(gd, wback, fixedaddress+u8*2);
@@ -1830,8 +1906,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VDUPQ_16(v0, q1, 0);
VNEGNQ_16(v0, v0); // because we want SHR and not SHL
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VNEGNQ_8(v0, v0); // because we want SHR and not SHL
VSHLQ_U16(q0, q0, v0);
break;
case 0xD2:
@@ -1840,11 +1919,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
VNEGN_32(v0, v0); // because we want SHR and not SHL
VMOVD(v0+1, v0);
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VNEGNQ_8(v0, v0); // because we want SHR and not SHL
VSHLQ_U32(q0, q0, v0);
break;
case 0xD3:
@@ -1853,11 +1932,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
VNEGN_32(v0, v0); // because we want SHR and not SHL
VMOVL_S32(v0, v0); // 2*q1 in 64 bits now
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VNEGNQ_8(v0, v0); // because we want SHR and not SHL
VSHLQ_U64(q0, q0, v0);
break;
case 0xD4:
@@ -1894,6 +1973,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
STR_IMM9(x2, ed, fixedaddress+0);
STR_IMM9(x3, ed, fixedaddress+4);
}
SMWRITE2();
}
break;
case 0xD7:
@@ -1999,13 +2079,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
VMOVD(v0+1, v0);
VQMOVN_S32(v0, v0); // 4*q1 in 16bits now
VNEGN_16(v0, v0); // because we want SHR and not SHL
VMOVD(v0+1, v0);
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VNEGNQ_8(v0, v0); // because we want SHR and not SHL
VSHLQ_S16(q0, q0, v0);
break;
case 0xE2:
@@ -2014,11 +2092,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
VNEGN_32(v0, v0); // because we want SHR and not SHL
VMOVD(v0+1, v0);
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VNEGNQ_8(v0, v0); // because we want SHR and not SHL
VSHLQ_S32(q0, q0, v0);
break;
case 0xE3:
@@ -2148,12 +2226,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
VMOVD(v0+1, v0);
VQMOVN_S32(v0, v0); // 4*q1 in 16bits now
VMOVD(v0+1, v0);
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VSHLQ_U16(q0, q0, v0);
break;
case 0xF2:
@@ -2162,10 +2238,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
VMOVD(v0+1, v0);
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VSHLQ_U32(q0, q0, v0);
break;
case 0xF3:
@@ -2174,8 +2250,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VSHLQ_U64(q0, q0, v0);
break;
case 0xF4:
+9 -9
View File
@@ -41,7 +41,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x81:
case 0x83:
nextop = F8;
DMB_ISH();
SMDMB();
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
@@ -50,7 +50,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("LOCK ADD Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = xEAX+(nextop&7);
@@ -71,7 +71,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&1))) {
@@ -85,17 +85,17 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
B_MARK(cNE);
STRH_IMM8(x1, wback, 0); // put the whole value
}
DMB_ISH();
SMDMB();
}
break;
default:
DEFAULT;
}
DMB_ISH();
SMDMB();
break;
case 0xFF:
nextop = F8;
DMB_ISH();
SMDMB();
switch((nextop>>3)&7)
{
case 0: // INC Ew
@@ -120,7 +120,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&1))) {
@@ -158,7 +158,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
@@ -178,7 +178,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
// default to NO LOCK
addr-=2;
}
DMB_ISH();
SMDMB();
break;
default:
DEFAULT;
+6
View File
@@ -58,6 +58,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
STRH_REG(gd, x14, ed);
SMWRITE2();
}
break;
@@ -72,6 +73,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFI(gd, ed, 0, 16);
}
} else { // mem <= reg
SMREAD();
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(gd, x14, ed, 0);
}
@@ -87,6 +89,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
POP1(x2);
STR_REG_LSL_IMM5(x2, x14, ed, 0);
SMWRITE2();
}
break;
@@ -98,6 +101,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
SMREAD();
LDR_IMM9(xEAX, x1, 0);
break;
@@ -110,6 +114,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
STR_IMM9(xEAX, x1, 0);
SMWRITE2();
break;
case 0xFF:
@@ -121,6 +126,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg
DEFAULT;
} else { // mem <= i32
SMREAD();
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
+108 -88
View File
@@ -223,7 +223,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 2:
INST_NAME("FIST Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
u8 = x87_setround_reset(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
@@ -233,10 +233,6 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// x1 already have FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVTR_S32_F64(s0, v1);
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
VMOVfrV(ed, s0);
@@ -248,7 +244,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 3:
INST_NAME("FISTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
u8 = x87_setround_reset(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
@@ -258,10 +254,6 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// The FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVTR_S32_F64(s0, v1);
VMRS(x3); // get the FPCSR reg and test FPU execption (denormal and overflow only)
VMOVfrV(ed, s0);
@@ -287,17 +279,89 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STR_IMM9(x2, ed, 0);
STR_IMM9(x3, ed, 4);
STRH_IMM8(x14, ed, 8);
} else {
if(box86_x87_no80bits) {
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, NULL);
VLDR_64(v1, ed, fixedaddress);
} else {
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);
}
} else {
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
if(ed!=x1) {
MOV_REG(x1, ed);
}
x87_do_push_empty(dyn, ninst, x3);
CALL(arm_fld, -1, 0);
#else
v1 = x87_do_push(dyn, ninst, x2, NEON_CACHE_ST_D);
// copy 10bytes of *ED to STld(0)
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, top));
int a = -dyn->n.x87stack;
if(a) {
if(a<0) {
SUB_IMM8(x3, x3, -a);
} else {
ADD_IMM8(x3, x3, a);
}
AND_IMM8(x3, x3, 7);
}
ADD_IMM8(x2, xEmu, offsetof(x86emu_t, fpu_ld)+offsetof(fpu_ld_t, ld));
MOVW(x14, sizeof(fpu_ld_t));
MLA(x2, x3, x14, x2);
LDR_IMM9(x14, ed, 0);
STR_IMM9(x14, x2, 0);
LDR_IMM9(x14, ed, 4);
STR_IMM9(x14, x2, 4);
LDRH_IMM8(x14, ed, 8);
STRH_IMM8(x14, x2, 8);
// convert 10bytes -> double
CALL_1RD(FromLD, ed, x2, (1<<x3)|(1<<xFlags)|(1<<x2));
// store ref to STld(0).uref, but can be unaligned...
VMOVfrV_D(x3, x14, 0);
// also, store result to ST0
VMOVD(v1, 0);
STR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
STR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
#endif
}
}
break;
case 7:
INST_NAME("FSTP tbyte");
if(box86_x87_no80bits) {
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, NULL);
VSTR_64(v1, ed, fixedaddress);
} else {
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);
}
} else {
#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, NULL);
if(ed!=x1) {
MOV_REG(x1, ed);
}
x87_do_push_empty(dyn, ninst, x3);
CALL(arm_fld, -1, 0);
CALL(arm_fstp, -1, 0);
#else
v1 = x87_do_push(dyn, ninst, x2, NEON_CACHE_ST_D);
// copy 10bytes of *ED to STld(0)
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch_double(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
// get top in x3
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, top));
int a = -dyn->n.x87stack;
if(a) {
@@ -308,85 +372,41 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
AND_IMM8(x3, x3, 7);
}
// get STld(0)
ADD_IMM8(x2, xEmu, offsetof(x86emu_t, fpu_ld)+offsetof(fpu_ld_t, ld));
MOVW(x14, sizeof(fpu_ld_t));
MLA(x2, x3, x14, x2);
LDR_IMM9(x14, ed, 0);
STR_IMM9(x14, x2, 0);
LDR_IMM9(x14, ed, 4);
STR_IMM9(x14, x2, 4);
LDRH_IMM8(x14, ed, 8);
STRH_IMM8(x14, x2, 8);
// convert 10bytes -> double
CALL_1RD(FromLD, ed, x2, (1<<x3)|(1<<xFlags)|(1<<x2));
// store ref to STld(0).uref, but can be unaligned...
VMOVfrV_D(x3, x14, 0);
// also, store result to ST0
VMOVD(v1, 0);
STR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
STR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
// compare uref with actual value, top is not used anymore, so x3 is free
LDR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
LDR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
VMOVtoV_D(v2, x14, x3);
VCEQ_32(v2, v2, v1); // same?
VMOVfrV_D(x14, x3, v2);
TSTS_REG_LSL_IMM5(x14, x3, 0);
B_MARK(cEQ); // different, do the conversion
// same... copy STld(0).ld
LDR_IMM9(x14, x2, 0);
LDR_IMM9(x3, x2, 4);
STR_IMM9(x14, ed, 0);
STR_IMM9(x3, ed, 4);
LDRH_IMM8(x14, x2, 8);
STRH_IMM8(x14, ed, 8);
B_MARK2(c__);
MARK;
// different, call D2LD
SUB_IMM8(xSP, xSP, 8);
VSTR_64(v1, xSP, 0);
PUSH(xSP, (1<<xEmu)|(1<<xFlags));
ADD_IMM8(0, xSP, 8); //1st arg is &d
if(ed!=x1) {
MOV_REG_LSL_IMM5(x1, ed, 0); //2nd arg is ed
}
CALL_S(D2LD, -2, 0);
POP(xSP, (1<<xEmu)|(1<<xFlags));
ADD_IMM8(xSP, xSP, 8);
MARK2;
#endif
}
break;
case 7:
INST_NAME("FSTP tbyte");
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {
MOV_REG(x1, ed);
}
CALL(arm_fstp, -1, 0);
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch_double(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
// get top in x3
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, top));
int a = -dyn->n.x87stack;
if(a) {
if(a<0) {
SUB_IMM8(x3, x3, -a);
} else {
ADD_IMM8(x3, x3, a);
}
AND_IMM8(x3, x3, 7);
}
// get STld(0)
ADD_IMM8(x2, xEmu, offsetof(x86emu_t, fpu_ld)+offsetof(fpu_ld_t, ld));
MOVW(x14, sizeof(fpu_ld_t));
MLA(x2, x3, x14, x2);
// compare uref with actual value, top is not used anymore, so x3 is free
LDR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
LDR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
VMOVtoV_D(v2, x14, x3);
VCEQ_32(v2, v2, v1); // same?
VMOVfrV_D(x14, x3, v2);
TSTS_REG_LSL_IMM5(x14, x3, 0);
B_MARK(cEQ); // different, do the conversion
// same... copy STld(0).ld
LDR_IMM9(x14, x2, 0);
LDR_IMM9(x3, x2, 4);
STR_IMM9(x14, ed, 0);
STR_IMM9(x3, ed, 4);
LDRH_IMM8(x14, x2, 8);
STRH_IMM8(x14, ed, 8);
B_MARK2(c__);
MARK;
// different, call D2LD
SUB_IMM8(xSP, xSP, 8);
VSTR_64(v1, xSP, 0);
PUSH(xSP, (1<<xEmu)|(1<<xFlags));
ADD_IMM8(0, xSP, 8); //1st arg is &d
if(ed!=x1) {
MOV_REG_LSL_IMM5(x1, ed, 0); //2nd arg is ed
}
CALL_S(D2LD, -2, 0);
POP(xSP, (1<<xEmu)|(1<<xFlags));
ADD_IMM8(xSP, xSP, 8);
MARK2;
#endif
x87_do_pop(dyn, ninst, x3);
break;
default:
+2 -10
View File
@@ -203,15 +203,11 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 2:
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);
u8 = x87_setround_reset(dyn, ninst, x1, x2, x14);
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, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
if(ST_IS_F(0)) {
VCVTR_S32_F32(s0, v1);
} else {
@@ -229,15 +225,11 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 3:
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);
u8 = x87_setround_reset(dyn, ninst, x1, x2, x14);
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, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
if(ST_IS_F(0)) {
VCVTR_S32_F32(s0, v1);
} else {
+69 -69
View File
@@ -42,7 +42,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
@@ -59,14 +59,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
DMB_ISH();
SMDMB();
break;
case 0x01:
INST_NAME("LOCK ADD Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_add32(dyn, ninst, ed, gd, x3, x14);
@@ -79,13 +79,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0x08:
INST_NAME("LOCK OR Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
GETGB(x2);
wback = (nextop&7);
@@ -104,14 +104,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
DMB_ISH();
SMDMB();
break;
case 0x09:
INST_NAME("LOCK OR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_or32(dyn, ninst, ed, gd, x3, x14);
@@ -124,7 +124,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0x10:
INST_NAME("LOCK ADC Eb, Gb");
@@ -132,7 +132,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
@@ -149,7 +149,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
DMB_ISH();
SMDMB();
break;
case 0x11:
INST_NAME("LOCK ADC Ed, Gd");
@@ -157,7 +157,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_adc32(dyn, ninst, ed, gd, x3, x14);
@@ -170,7 +170,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0x18:
INST_NAME("LOCK SBB Eb, Gb");
@@ -178,7 +178,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
@@ -195,7 +195,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
DMB_ISH();
SMDMB();
break;
case 0x19:
INST_NAME("LOCK SBB Ed, Gd");
@@ -203,7 +203,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_sbb32(dyn, ninst, ed, gd, x3, x14);
@@ -216,13 +216,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0x20:
INST_NAME("LOCK AND Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
GETGB(x2);
wback = (nextop&7);
@@ -241,14 +241,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
DMB_ISH();
SMDMB();
break;
case 0x21:
INST_NAME("LOCK AND Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_and32(dyn, ninst, ed, gd, x3, x14);
@@ -261,14 +261,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0x28:
INST_NAME("LOCK SUB Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
@@ -285,14 +285,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
DMB_ISH();
SMDMB();
break;
case 0x29:
INST_NAME("LOCK SUB Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_sub32(dyn, ninst, ed, gd, x3, x14);
@@ -305,13 +305,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0x38:
INST_NAME("LOCK XOR Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
GETGB(x2);
wback = (nextop&7);
@@ -330,14 +330,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
DMB_ISH();
SMDMB();
break;
case 0x39:
INST_NAME("LOCK XOR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_xor32(dyn, ninst, ed, gd, x3, x14);
@@ -350,7 +350,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0x66:
@@ -368,7 +368,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("LOCK ADD Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
@@ -389,7 +389,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
@@ -403,13 +403,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARK(cNE);
STR_IMM9(x1, wback, 0); // put the whole value
}
DMB_ISH();
SMDMB();
}
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("LOCK OR Ed, Id");} else {INST_NAME("LOCK OR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
@@ -424,13 +424,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 2: //ADC
if(opcode==0x81) {INST_NAME("LOCK ADC Ed, Id");} else {INST_NAME("LOCK ADC Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
@@ -445,13 +445,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 3: //SBB
if(opcode==0x81) {INST_NAME("LOCK SBB Ed, Id");} else {INST_NAME("LOCK SBB Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
@@ -466,12 +466,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("LOCK AND Ed, Id");} else {INST_NAME("LOCK AND Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
@@ -486,7 +486,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("LOCK SUB Ed, Id");} else {INST_NAME("LOCK SUB Ed, Ib");}
@@ -496,7 +496,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_sub32c(dyn, ninst, ed, i32, x3, x14);
} else {
DMB_ISH();
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
if(!fixedaddress) {
@@ -512,7 +512,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
@@ -526,7 +526,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARK(cNE);
STR_IMM9(x1, wback, 0); // put the whole value
}
DMB_ISH();
SMDMB();
}
break;
case 6: //XOR
@@ -537,7 +537,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_xor32c(dyn, ninst, ed, i32, x3, x14);
} else {
DMB_ISH();
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
@@ -546,13 +546,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
DMB_ISH();
SMDMB();
}
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("(LOCK) CMP Ed, Id");} else {INST_NAME("(LOCK) CMP Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
SMDMB();
GETEDH(x1);
// No need to LOCK, this is readonly
if(opcode==0x81) i32 = F32S; else i32 = F8S;
@@ -582,7 +582,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
#undef GO
case 0x86: // for this two, the lock is already done by the opcode, so just ignoring it
case 0x87:
DMB_ISH();
SMDMB();
--addr;
break;
case 0x90: // This is xchg reg, reg, so let's ignore the LOCK prefix...
@@ -593,7 +593,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x95:
case 0x96:
case 0x97:
DMB_ISH();
SMDMB();
--addr;
break;
@@ -603,7 +603,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xB0:
INST_NAME("LOCK CMPXCHG Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
SMDMB();
nextop = F8;
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
@@ -640,7 +640,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// AL != Eb
BFI(xEAX, ed, 0, 8);
MARK3;
DMB_ISH();
SMDMB();
// done, do the cmp now
UFLAG_IF {emit_cmp8(dyn, ninst, x1, x2, x3, x14);}
break;
@@ -649,7 +649,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
// same as no lock, all in regs...
@@ -679,7 +679,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARK(cNE);
// EAX == Ed
STREX(x14, gd, wback);
DMB_ISH();
SMDMB();
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
B_MARK(c__);
@@ -695,7 +695,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARK2(cNE);
STR_IMM9(gd, wback, 0);
DMB_ISH();
SMDMB();
} else {
MARKLOCK;
// alignment is good
@@ -706,7 +706,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STREX(x14, gd, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
DMB_ISH();
SMDMB();
}
// end of EAX == Ed or EAX != Ed
MARK;
@@ -721,7 +721,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SET_DFNONE(x1);
nextop = F8;
GETGD;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
@@ -747,12 +747,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARKLOCK(cNE);
}
MARK3;
DMB_ISH();
SMDMB();
break;
case 0xBA:
nextop = F8;
DMB_ISH();
SMDMB();
switch((nextop>>3)&7) {
case 4:
INST_NAME("(LOCK) BT Ed, Ib");
@@ -839,7 +839,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
default:
DEFAULT;
}
DMB_ISH();
SMDMB();
break;
case 0xBB:
INST_NAME("LOCK BTC Ed, Gd");
@@ -847,7 +847,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SET_DFNONE(x1);
nextop = F8;
GETGD;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
@@ -870,14 +870,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0xC0:
INST_NAME("LOCK XADD Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
DMB_ISH();
SMDMB();
GETGB(x1);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
@@ -902,14 +902,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
BFI(wback, ed, wb2*8, 8);
}
DMB_ISH();
SMDMB();
break;
case 0xC1:
INST_NAME("LOCK XADD Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
if(gd!=ed) {
@@ -955,7 +955,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
MOV_REG(gd, x1);
}
DMB_ISH();
SMDMB();
break;
case 0xC7:
@@ -964,7 +964,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 1:
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
DMB_ISH();
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 1, LOCK_LOCK);
MARKLOCK;
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
@@ -1001,7 +1001,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV_REG(xEDX, x3);
MOVW(x1, 0);
MARK3;
DMB_ISH();
SMDMB();
BFI(xFlags, x1, F_ZF, 1);
break;
default:
@@ -1017,7 +1017,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xFF:
nextop = F8;
DMB_ISH();
SMDMB();
switch((nextop>>3)&7)
{
case 0: // INC Ed
@@ -1041,7 +1041,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
@@ -1078,7 +1078,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
@@ -1098,7 +1098,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// default to NO LOCK
addr-=2;
}
DMB_ISH();
SMDMB();
break;
default:
+57 -1
View File
@@ -29,6 +29,7 @@
} else { \
parity = getedparity(dyn, ninst, addr, nextop, 3); \
a = fpu_get_scratch_double(dyn); \
SMREAD(); \
if(parity) { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL); \
VLDR_64(a, ed, fixedaddress); \
@@ -72,6 +73,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(v0, d0);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
@@ -93,6 +95,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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);
SMWRITE2();
}
break;
case 0x12:
@@ -104,6 +107,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVD(v0, d0);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
@@ -132,28 +136,50 @@ 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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
d0 = fpu_get_scratch_double(dyn);
VLDR_64(d0, ed, fixedaddress);
}
if(!box86_dynarec_fastround) {
VMRS(x14); // Get FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VCVT_S32_F64(s0, d0);
VMOVfrV(gd, s0);
if(!box86_dynarec_fastround) {
VMRS(x3); // get the FPCSR reg and test FPU exception (IO only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
MOV_IMM_COND(cNE, gd, 0b10, 1); // 0x80000000
VMSR(x14); // put back values
}
break;
case 0x2D:
INST_NAME("CVTSD2SI Gd, Ex");
u8 = sse_setround(dyn, ninst, x1, x2, x14);
if(!box86_dynarec_fastround)
u8 = sse_setround_reset(dyn, ninst, x1, x2, x14);
else
u8 = sse_setround(dyn, ninst, x1, x2, x14);
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
d0 = fpu_get_scratch_double(dyn);
VLDR_64(d0, ed, fixedaddress);
}
VCVTR_S32_F64(s0, d0);
VMOVfrV(gd, s0);
if(!box86_dynarec_fastround) {
VMRS(x3); // get the FPCSR reg and test FPU exception (IO only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
MOV_IMM_COND(cNE, gd, 0b10, 1); // 0x80000000
}
x87_restoreround(dyn, ninst, u8);
break;
@@ -305,6 +331,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
@@ -340,6 +367,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
@@ -401,6 +429,33 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOV_64(v0, v1);
break;
case 0xE6:
INST_NAME("CVTPD2DQ Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_8(v1, ed);
}
u8 = sse_setround(dyn, ninst, x1, x2, x14);
if(v0<16) {
VCVTR_S32_F64(v0*2, v1);
VCVTR_S32_F64(v0*2+1, v1+1);
} else {
d0 = fpu_get_scratch_double(dyn);
VCVTR_S32_F64(d0*2, v1);
VCVTR_S32_F64(d0*2+1, v1+1);
VMOVD(v0, d0);
}
x87_restoreround(dyn, ninst, u8);
VEOR(v0+1, v0+1, v0+1);
break;
case 0xF0:
INST_NAME("LDDQ Gx,Ex");
nextop = F8;
@@ -410,6 +465,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
+36 -2
View File
@@ -37,6 +37,7 @@
b = fpu_get_scratch_double(dyn); \
a = b*2; \
parity = getedparity(dyn, ninst, addr, nextop, 2); \
SMREAD(); \
if(parity) { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0, NULL); \
VLDR_32(a, ed, fixedaddress); \
@@ -102,6 +103,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
parity = getedparity(dyn, ninst, addr, nextop, 2);
SMREAD();
if(parity && (v0<16)) {
VEORQ(v0, v0, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0, NULL);
@@ -147,6 +149,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
}
SMWRITE2();
}
break;
case 0x12:
@@ -156,6 +159,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q1, ed);
@@ -172,6 +176,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q1, ed);
@@ -229,6 +234,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOV_32(s0, d0*2);
} else {
parity = getedparity(dyn, ninst, addr, nextop, 3);
SMREAD();
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
@@ -238,12 +244,27 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVtoV(s0, x2);
}
}
if(!box86_dynarec_fastround) {
VMRS(x14); // Get FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VCVT_S32_F32(s0, s0);
VMOVfrV(gd, s0);
if(!box86_dynarec_fastround) {
VMRS(x3); // get the FPCSR reg and test FPU exception (IO only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
MOV_IMM_COND(cNE, gd, 0b10, 1); // 0x80000000
VMSR(x14); // put back values
}
break;
case 0x2D:
INST_NAME("CVTSS2SI Gd, Ex");
u8 = sse_setround(dyn, ninst, x1, x2, x14);
if(!box86_dynarec_fastround)
u8 = sse_setround_reset(dyn, ninst, x1, x2, x14);
else
u8 = sse_setround(dyn, ninst, x1, x2, x14);
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
@@ -258,6 +279,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOV_32(s0, d0*2);
} else {
parity = getedparity(dyn, ninst, addr, nextop, 3);
SMREAD();
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
@@ -269,6 +291,11 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
VCVTR_S32_F32(s0, s0);
VMOVfrV(gd, s0);
if(!box86_dynarec_fastround) {
VMRS(x3); // get the FPCSR reg and test FPU exception (IO only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
MOV_IMM_COND(cNE, gd, 0b10, 1); // 0x80000000
}
x87_restoreround(dyn, ninst, u8);
break;
@@ -396,6 +423,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 {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
@@ -500,6 +528,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
@@ -514,14 +543,15 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("PSHUFHW Gx, Ex, Ib");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
}
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
u8 = F8;
// only high part need to be shuffled. VTBL only handle 8bits value, so the 16bits shuffles need to be changed in 8bits
u32 = 0;
@@ -554,6 +584,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVD(v0, v1);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1_64(v0, ed);
@@ -576,6 +607,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVfrV_D(x2, x3, v0+1);
STR_IMM9(x2, ed, fixedaddress+8);
STR_IMM9(x3, ed, fixedaddress+12);
SMWRITE2();
}
break;
@@ -640,6 +672,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOV_64(v0, v1);
} else {
parity = getedparity(dyn, ninst, addr, nextop, 3);
SMREAD();
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0, ed, fixedaddress); // vfpu opcode here
@@ -666,6 +699,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
} else {
v0 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 3);
SMREAD();
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0, ed, fixedaddress); // vfpu opcode here
+45 -12
View File
@@ -251,6 +251,7 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
}
PASS3(void* epilog = arm_epilog);
MOV32_(2, (uintptr_t)epilog);
SMEND();
BX(2);
}
@@ -277,6 +278,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
#ifdef HAVE_TRACE
MOV_REG(x2, 15); // move current PC to x2, for tracing
#endif
SMEND();
BX(x3);
}
@@ -293,6 +295,7 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
#ifdef HAVE_TRACE
MOV_REG(x2, 15); // move current PC to x2, for tracing
#endif
SMEND();
BX(x3);
}
@@ -315,6 +318,7 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
#ifdef HAVE_TRACE
MOV_REG(x2, 15); // move current PC to x2, for tracing
#endif
SMEND();
BX(x3);
}
@@ -337,6 +341,7 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
SET_DFNONE(x1);
// Ret....
MOV32_(x2, (uintptr_t)arm_epilog); // epilog on purpose, CS might have changed!
SMEND();
BX(x2);
}
@@ -478,7 +483,7 @@ void call_rd(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int s1, uint32_t
if(s1!=xFlags) mask=1<<xFlags; else mask=1<<x3;
}
PUSH(xSP, (1<<xEmu) | mask);
fpu_pushcache(dyn, ninst, reg);
fpu_pushcache(dyn, ninst, s1);
if(saveflags) {
STR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
}
@@ -490,7 +495,7 @@ void call_rd(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int s1, uint32_t
#ifdef ARM_SOFTFP
VMOVtoV_64(0, 0, 1); // load r0:r1 to D0 to simulate hardfo
#endif
fpu_popcache(dyn, ninst, reg);
fpu_popcache(dyn, ninst, s1);
POP(xSP, (1<<xEmu) | mask);
if(saveflags) {
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
@@ -1066,15 +1071,13 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
}
static int round_map[] = {0, 2, 1, 3}; // map x86 -> arm round flag
// Set rounding according to cw flags, return reg to restore flags
int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, cw)); // hopefully cw is not too far for an imm8
UBFX(s2, s1, 10, 2); // extract round...
MOV32(s1, round_map);
LDR_REG_LSL_IMM5(s2, s1, s2, 2);
UBFX(s1, s1, 10, 2); // extract round...
UBFX(s2, s1, 1, 1); // swap bits 0 and 1
BFI(s2, s1, 1, 1);
VMRS(s1); // get fpscr
MOV_REG(s3, s1);
BFI(s1, s2, 22, 2); // inject new round
@@ -1082,6 +1085,21 @@ int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
return s3;
}
// Set rounding according to cw flags, also enable exception and reset counter, return reg to restore flags
int x87_setround_reset(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, cw)); // hopefully cw is not too far for an imm8
UBFX(s1, s1, 10, 2); // extract round...
UBFX(s2, s1, 1, 1); // swap bits 0 and 1
BFI(s2, s1, 1, 1);
VMRS(s3); // get fpscr
ORR_IMM8(s1, s3, 0b010, 9); // enable exceptions
BIC_IMM8(s1, s1, 0b10011111, 0); // reset counters
BFI(s1, s2, 22, 2); // inject new round
VMSR(s1); // put new fpscr
return s3;
}
void x87_swapreg(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int b)
{
int i1, i2, i3;
@@ -1106,9 +1124,9 @@ void x87_swapreg(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int b)
int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
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);
UBFX(s1, s1, 13, 2); // extract round...
UBFX(s2, s1, 1, 1); // swap bits 0 and 1
BFI(s2, s1, 1, 1);
VMRS(s1); // get fpscr
MOV_REG(s3, s1);
BFI(s1, s2, 22, 2); // inject new round
@@ -1116,6 +1134,21 @@ int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
return s3;
}
// Set rounding according to mxcsr flags, also enable exception and reset counter, return reg to restore flags
int sse_setround_reset(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, mxcsr));
UBFX(s1, s1, 13, 2); // extract round...
UBFX(s2, s1, 1, 1); // swap bits 0 and 1
BFI(s2, s1, 1, 1);
VMRS(s3); // get fpscr
ORR_IMM8(s1, s3, 0b010, 9); // enable exceptions
BIC_IMM8(s1, s1, 0b10011111, 0); // reset counters
BFI(s1, s2, 22, 2); // inject new round
VMSR(s1); // put new fpscr
return s3;
}
// Restore round flag
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1)
{
@@ -1333,7 +1366,7 @@ void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
MOV_REG(s1, xSP);
for (int i=16; i<32; ++i) { // should use VSTM?
if(dyn->n.fpuused[i-8]) {
VST1_32_W(i, s1);
VST1_64_W(i, s1);
}
}
MESSAGE(LOG_DUMP, "\t------- Push FPU Cache (%d)\n", n);
@@ -1352,7 +1385,7 @@ void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1)
MOV_REG(s1, xSP);
for (int i=16; i<32; ++i) {
if(dyn->n.fpuused[i-8]) {
VLD1_32_W(i, s1);
VLD1_64_W(i, s1);
}
}
if(n>=8) {
+51 -8
View File
@@ -27,6 +27,30 @@
#define PKip(a) *(uint8_t*)(ip+a)
#define PKa(a) *(uint8_t*)(a)
// Strong mem emulation helpers
// Sequence of Read will trigger a DMB on "first" read if strongmem is 2
// Squence of Write will trigger a DMB on "last" write if strongmem is 1
// Opcode will read
#define SMREAD() if(!dyn->smread && box86_dynarec_strongmem>1) {SMDMB();}
// Opcode will read with option forced lock
#define SMREADLOCK(lock) if(lock || (!dyn->smread && box86_dynarec_strongmem>1)) {SMDMB();}
// Opcode migh read (depend on nextop)
#define SMMIGHTREAD() if(!MODREG) {SMREAD();}
// Opcode has wrote
#define SMWRITE() dyn->smwrite=1
// Opcode has wrote (strongmem>1 only)
#define SMWRITE2() if(box86_dynarec_strongmem>1) dyn->smwrite=1
// Opcode has wrote with option forced lock
#define SMWRITELOCK(lock) if(lock) {SMDMB();} else dyn->smwrite=1
// Opcode migh have wrote (depend on nextop)
#define SMMIGHTWRITE() if(!MODREG) {SMWRITE();}
// Start of sequence
#define SMSTART() SMEND()
// End of sequence
#define SMEND() if(dyn->smwrite && box86_dynarec_strongmem) {DMB_ISH();} dyn->smwrite=0; dyn->smread=0;
// Force a Data memory barrier (for LOCK: prefix)
#define SMDMB() DMB_ISH(); dyn->smwrite=0; dyn->smread=1
//LOCK_* define
#define LOCK_LOCK (int*)1
@@ -37,6 +61,7 @@
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0, NULL); \
LDR_IMM9(x1, wback, fixedaddress); \
ed = x1; \
@@ -46,6 +71,7 @@
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 4095, 0, 0, NULL); \
LDR_IMM9(hint, wback, fixedaddress); \
ed = hint; \
@@ -56,19 +82,21 @@
MOV_REG(ret, ed); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 4095, 0, 0, NULL); \
ed = ret; \
LDR_IMM9(ed, wback, fixedaddress); \
}
// Write back ed in wback (if wback not 0)
#define WBACK if(wback) {STR_IMM9(ed, wback, fixedaddress);}
// Send back wb to either ed or wback
#define SBACK(wb) if(wback) {STR_IMM9(wb, wback, fixedaddress);} else {MOV_REG(ed, wb);}
#define WBACK if(wback) {STR_IMM9(ed, wback, fixedaddress); SMWRITE();}
// Write back ed in wback (if wback not 0) (SMWRITE2 version)
#define WBACK2 if(wback) {STR_IMM9(ed, wback, fixedaddress); SMWRITE2();}
//GETEDO can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
#define GETEDO(O) if((nextop&0xC0)==0xC0) { \
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL); \
LDR_REG_LSL_IMM5(x1, wback, O, 0); \
ed = x1; \
@@ -78,13 +106,14 @@
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL); \
ADD_REG_LSL_IMM5(x2, wback, O, 0); \
if(wback != x2) wback = x2; \
LDR_IMM9(x1, wback, 0); \
ed = x1; \
}
#define WBACKO(O) if(wback) {STR_REG_LSL_IMM5(ed, wback, O, 0);}
#define WBACKO(O) if(wback) {STR_REG_LSL_IMM5(ed, wback, O, 0); SMWRITE();}
//FAKEELike GETED, but doesn't get anything
#define FAKEED if((nextop&0xC0)!=0xC0) { \
addr = fakeed(dyn, addr, ninst, nextop); \
@@ -98,6 +127,7 @@
ed = i; \
wb1 = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 255, 0, 0, NULL); \
LDRH_IMM8(i, wback, fixedaddress); \
ed = i; \
@@ -110,6 +140,7 @@
ed = i; \
wb1 = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL); \
LDRH_IMM8(i, wback, fixedaddress); \
ed = i; \
@@ -122,15 +153,16 @@
ed = i; \
wb1 = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL); \
LDRSH_IMM8(i, wback, fixedaddress);\
ed = i; \
wb1 = 1; \
}
// Write ed back to original register / memory
#define EWBACK if(wb1) {STRH_IMM8(ed, wback, fixedaddress);} else {BFI(wback, ed, 0, 16);}
#define EWBACK if(wb1) {STRH_IMM8(ed, wback, fixedaddress); SMWRITE();} else {BFI(wback, ed, 0, 16);}
// Write w back to original register / memory
#define EWBACKW(w) if(wb1) {STRH_IMM8(w, wback, fixedaddress);} else {BFI(wback, w, 0, 16);}
#define EWBACKW(w) if(wb1) {STRH_IMM8(w, wback, fixedaddress); SMWRITE();} else {BFI(wback, w, 0, 16);}
// Write back gd in correct register
#define GWBACK BFI((xEAX+((nextop&0x38)>>3)), gd, 0, 16);
//GETEB will use i for ed, and can use r3 for wback.
@@ -142,6 +174,7 @@
wb1 = 0; \
ed = i; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL); \
LDRB_IMM9(i, wback, fixedaddress); \
wb1 = 1; \
@@ -156,6 +189,7 @@
wb1 = 0; \
ed = i; \
} else { \
SMREAD(); \
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; \
@@ -172,13 +206,16 @@
wb1 = 0; \
ed = i; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL); \
LDRSB_IMM8(i, wback, fixedaddress);\
wb1 = 1; \
ed = i; \
}
// Write eb (ed) back to original register / memory
#define EBBACK if(wb1) {STRB_IMM9(ed, wback, fixedaddress);} else {BFI(wback, ed, wb2*8, 8);}
#define EBBACK if(wb1) {STRB_IMM9(ed, wback, fixedaddress); SMWRITE();} else {BFI(wback, ed, wb2*8, 8);}
// Write eb (ed) back to original register / memory (SMWRITE2 version)
#define EBBACK2 if(wb1) {STRB_IMM9(ed, wback, fixedaddress); SMWRITE2();} else {BFI(wback, ed, wb2*8, 8);}
//GETGB will use i for gd
#define GETGB(i) gd = (nextop&0x38)>>3; \
gb2 = ((gd&4)>>2); \
@@ -306,7 +343,7 @@
#ifndef READFLAGS
#define READFLAGS(A) \
if((dyn->f.pending!=SF_SET) \
if(((A)!=X_PEND && dyn->f.pending!=SF_SET) \
&& (dyn->f.pending!=SF_SET_PENDING)) { \
if(dyn->f.pending!=SF_PENDING) { \
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, df)); \
@@ -497,9 +534,11 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define x87_reget_st STEPNAME(x87_reget_st)
#define x87_stackcount STEPNAME(x87_stackcount)
#define x87_setround STEPNAME(x87_setround)
#define x87_setround_reset STEPNAME(x87_setround_reset)
#define x87_restoreround STEPNAME(x87_restoreround)
#define x87_swapreg STEPNAME(x87_swapreg)
#define sse_setround STEPNAME(sse_setround)
#define sse_setround_reset STEPNAME(sse_setround_reset)
#define mmx_get_reg STEPNAME(mmx_get_reg)
#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty)
#define sse_get_reg STEPNAME(sse_get_reg)
@@ -644,12 +683,16 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
// Set rounding according to cw flags, return reg to restore flags
int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
// Set rounding according to cw flags, return reg to restore flags, also enable exceptions and reset counters
int x87_setround_reset(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
// Restore round flag
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1);
// swap 2 x87 regs
void x87_swapreg(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int b);
// Set rounding according to mxcsr flags, return reg to restore flags
int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
// Set rounding according to mxcsr flags, return reg to restore flags, also enable exceptions and reset counters
int sse_setround_reset(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);
+41 -8
View File
@@ -21,6 +21,7 @@
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
#include "custommem.h"
#include "elfloader.h"
#ifndef STEP
#error No STEP defined
@@ -39,9 +40,13 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
// Clean up (because there are multiple passes)
dyn->f.pending = 0;
dyn->f.dfnone = 0;
dyn->forward = 0;
dyn->forward_to = 0;
dyn->forward_size = 0;
dyn->forward_ninst = 0;
fpu_reset(dyn);
int reset_n = -1;
// ok, go now
int stopblock = 2+(FindElfAddress(my_context, addr)?0:1); // if block is in elf_memory, it can be extended with bligblocks==2, else it needs 3 // ok, go now
INIT;
while(ok) {
ip = addr;
@@ -119,6 +124,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
dyn->n.stack_push = 0;
dyn->n.swapped = 0;
NEW_INST;
if(dyn->insts[ninst].pred_sz>1) {SMSTART();}
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);
@@ -177,13 +183,33 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
#ifndef PROT_READ
#define PROT_READ 1
#endif
if(!ok && !need_epilog && box86_dynarec_bigblock && (getProtection(addr+3)&PROT_READ))
if(dyn->forward) {
if(dyn->forward_to == addr) {
// we made it!
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block %p -> %p\n", (void*)dyn->forward, (void*)dyn->forward_to);
dyn->forward = 0;
dyn->forward_to = 0;
dyn->forward_size = 0;
dyn->forward_ninst = 0;
} else if ((dyn->forward_to < addr) || !ok) {
// something when wrong! rollback
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Could not forward extend block %p -> %p\n", (void*)dyn->forward, (void*)dyn->forward_to);
ok = 0;
dyn->size = dyn->forward_size;
ninst = dyn->forward_ninst;
addr = dyn->forward;
dyn->forward = 0;
dyn->forward_to = 0;
dyn->forward_size = 0;
dyn->forward_ninst = 0;
}
// else just continue
} else 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))*/ ))
/*&& box86_dynarec_bigblock*/))
{
ok = 1;
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
@@ -194,16 +220,23 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
ii=ninst;
}
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %p -> %p (ninst=%d, jump from %d)\n", dyn, (void*)addr, (void*)next, ninst, reset_n);
} else if(next && (next-addr)<30) {
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7));
} else if(next && (next-addr<box86_dynarec_forward)
&& (getProtection(next)&PROT_READ)/*box86_dynarec_bigblock>=forwardblock*/) {
dyn->forward = addr;
dyn->forward_to = next;
dyn->forward_size = dyn->size;
dyn->forward_ninst = ninst;
reset_n = -2;
ok = 1;
}
}
#endif
if(ok<0) {ok = 0; need_epilog=1;}
++ninst;
#if STEP == 0
if((ok && !isJumpTableDefault((void*)addr) && (box86_dynarec_bigblock<2)) ||
(ok && dyn->size >= 2000))
if(ok && (((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)addr))
|| (addr>=box86_nodynarec_start && addr<box86_nodynarec_end)
/*|| (dyn->size >= 2000)*/)) // is this still needed? maybe it should be a parameter?
#else
if(ok && (ninst==dyn->size))
#endif
+1 -1
View File
@@ -34,7 +34,7 @@
#define INST_EPILOG \
dyn->insts[ninst].f_exit = dyn->f; \
dyn->insts[ninst].n = dyn->n; \
dyn->insts[ninst].x86.has_next = ok;
dyn->insts[ninst].x86.has_next = (ok>0)?1:0;
#define INST_NAME(name)
#define DEFAULT \
--dyn->size; \
+3 -2
View File
@@ -19,7 +19,7 @@
#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), %s=%X/%X, use=%X, need=%X/%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 sm=%d/%d", \
(box86_dynarec_dump>1)?"\e[32m":"", \
(void*)(dyn->arm_start+dyn->insts[ninst].address), \
dyn->insts[ninst].size/4, \
@@ -33,7 +33,8 @@
dyn->insts[ninst].x86.gen_flags, \
dyn->insts[ninst].x86.use_flags, \
dyn->insts[ninst].x86.need_before, \
dyn->insts[ninst].x86.need_after); \
dyn->insts[ninst].x86.need_after, \
dyn->smread, dyn->smwrite); \
if(dyn->insts[ninst].pred_sz) { \
dynarec_log(LOG_NONE, ", pred="); \
for(int ii=0; ii<dyn->insts[ninst].pred_sz; ++ii)\
+9 -3
View File
@@ -18,12 +18,12 @@ typedef struct dynablock_s dynablock_t;
typedef union neon_cache_s {
int8_t v;
struct {
unsigned int t:4; // reg type
unsigned int n:4; // reg number
uint8_t t:4; // reg type
uint8_t n:4; // reg number
};
} neon_cache_t;
typedef union sse_cache_s {
int v;
int8_t v;
struct {
uint8_t reg;
uint8_t write;
@@ -100,6 +100,12 @@ typedef struct dynarec_arm_s {
int sons_size; // number of potential dynablock sons
int* predecessor;// single array of all predecessor
dynablock_t* dynablock;
uint8_t smread; // for strongmem model emulation
uint8_t smwrite; // for strongmem model emulation
uintptr_t forward; // address of the last end of code while testing forward
uintptr_t forward_to; // address of the next jump to (to check if everything is ok)
int32_t forward_size; // size at the forward point
int forward_ninst; // ninst at the forward point
} dynarec_arm_t;
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
+7 -7
View File
@@ -235,12 +235,12 @@ void DumpMainHeader(Elf32_Ehdr *header, elfheader_t *h)
printf_dump(LOG_NEVER, "ELF Dump ==========\n");
printf_dump(LOG_NEVER, "ELF Dump PEntries (%d)\n", h->numSHEntries);
for (int i=0; i<h->numPHEntries; ++i)
for (uint16_t i=0; i<h->numPHEntries; ++i)
printf_dump(LOG_NEVER, " PHEntry %04d : %s\n", i, DumpPHEntry(h->PHEntries+i));
printf_dump(LOG_NEVER, "ELF Dump PEntries ====\n");
printf_dump(LOG_NEVER, "ELF Dump Sections (%d)\n", h->numSHEntries);
for (int i=0; i<h->numSHEntries; ++i)
for (uint16_t i=0; i<h->numSHEntries; ++i)
printf_dump(LOG_NEVER, " Section %04d : %s\n", i, DumpSection(h->SHEntries+i, h->SHStrTab));
printf_dump(LOG_NEVER, "ELF Dump Sections ====\n");
}
@@ -251,7 +251,7 @@ void DumpSymTab(elfheader_t *h)
if(box86_dump && h->SymTab) {
const char* name = ElfName(h);
printf_dump(LOG_NEVER, "ELF Dump SymTab(%d)=\n", h->numSymTab);
for (int i=0; i<h->numSymTab; ++i)
for (uint32_t i=0; i<h->numSymTab; ++i)
printf_dump(LOG_NEVER, " %s:SymTab[%d] = \"%s\", value=%p, size=%d, info/other=%d/%d index=%d\n", name,
i, h->StrTab+h->SymTab[i].st_name, (void*)h->SymTab[i].st_value, h->SymTab[i].st_size,
h->SymTab[i].st_info, h->SymTab[i].st_other, h->SymTab[i].st_shndx);
@@ -263,7 +263,7 @@ void DumpDynamicSections(elfheader_t *h)
{
if(box86_dump && h->Dynamic) {
printf_dump(LOG_NEVER, "ELF Dump Dynamic(%d)=\n", h->numDynamic);
for (int i=0; i<h->numDynamic; ++i)
for (uint32_t i=0; i<h->numDynamic; ++i)
printf_dump(LOG_NEVER, " Dynamic %04d : %s\n", i, DumpDynamic(h->Dynamic+i));
printf_dump(LOG_NEVER, "ELF Dump Dynamic=====\n");
}
@@ -274,7 +274,7 @@ void DumpDynSym(elfheader_t *h)
if(box86_dump && h->DynSym) {
const char* name = ElfName(h);
printf_dump(LOG_NEVER, "ELF Dump DynSym(%d)=\n", h->numDynSym);
for (int i=0; i<h->numDynSym; ++i) {
for (uint32_t i=0; i<h->numDynSym; ++i) {
int version = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
printf_dump(LOG_NEVER, " %s:DynSym[%d] = %s\n", name, i, DumpSym(h, h->DynSym+i, version));
}
@@ -286,7 +286,7 @@ void DumpDynamicNeeded(elfheader_t *h)
{
if(box86_dump && h->DynStrTab) {
printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n");
for (int i=0; i<h->numDynamic; ++i)
for (uint32_t i=0; i<h->numDynamic; ++i)
if(h->Dynamic[i].d_tag==DT_NEEDED) {
printf_dump(LOG_NEVER, " Needed : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
}
@@ -298,7 +298,7 @@ void DumpDynamicRPath(elfheader_t *h)
{
if(box86_dump && h->DynStrTab) {
printf_dump(LOG_NEVER, "ELF Dump DT_RPATH/DT_RUNPATH=====\n");
for (int i=0; i<h->numDynamic; ++i) {
for (uint32_t i=0; i<h->numDynamic; ++i) {
if(h->Dynamic[i].d_tag==DT_RPATH) {
printf_dump(LOG_NEVER, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
}
+97 -41
View File
@@ -1,4 +1,4 @@
#define _GNU_SOURCE
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -355,6 +355,7 @@ int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
{
(void)context;
for (int i=0; i<head->numPHEntries; ++i) {
if(head->PHEntries[i].p_type == PT_LOAD) {
Elf32_Phdr * e = &head->PHEntries[i];
@@ -383,7 +384,7 @@ int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
// TLS data are just a copy, no need to re-load it
return 0;
}
int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t** p, int version, const char* vername)
int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t** p, size_t size, int version, const char* vername)
{
if(!h)
return 0;
@@ -396,7 +397,7 @@ int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t*
int t = ELF32_R_TYPE(rel[i].r_info);
Elf32_Sym *sym = &h->DynSym[ELF32_R_SYM(rel[i].r_info)];
const char* symname = SymName(h, sym);
if(t==R_386_COPY && symname && !strcmp(symname, name)) {
if(t==R_386_COPY && symname && !strcmp(symname, name) && sym->st_size==size) {
int version2 = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[ELF32_R_SYM(rel[i].r_info)]:-1;
if(version2!=-1) version2 &= 0x7fff;
if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol
@@ -416,7 +417,7 @@ int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t*
int t = ELF32_R_TYPE(rela[i].r_info);
Elf32_Sym *sym = &h->DynSym[ELF32_R_SYM(rela[i].r_info)];
const char* symname = SymName(h, sym);
if(t==R_386_COPY && symname && !strcmp(symname, name)) {
if(t==R_386_COPY && symname && !strcmp(symname, name) && sym->st_size==size) {
int version2 = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[ELF32_R_SYM(rela[i].r_info)]:-1;
if(version2!=-1) version2 &= 0x7fff;
if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol
@@ -444,14 +445,22 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
uint32_t *p = (uint32_t*)(rel[i].r_offset + head->delta);
uintptr_t offs = 0;
uintptr_t end = 0;
size_t size = sym->st_size;
elfheader_t* h_tls = NULL;//head;
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;
if(!symname || !symname[0]) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
} else {
if(!offs && !end && local_maplib)
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
if(!offs && !end)
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
}
} else {
// this is probably very very wrong. A proprer way to get reloc need to be writen, but this hack seems ok for now
// at least it work for half-life, unreal, ut99, zsnes, Undertale, ColinMcRae Remake, FTL, ShovelKnight...
@@ -494,11 +503,11 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
globoffs = offs;
globend = end;
offs = end = 0;
GetSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, version, vername, 1, defver); // try globaldata symbols first
GetSizedSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, size, version, vername, 1, defver); // try globaldata symbols first
if(!offs && local_maplib)
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername);
if(!offs)
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername);
if(!offs) {offs = globoffs; end = globend;}
if(offs) {
// add r_addend to p?
@@ -510,7 +519,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
}
break;
case R_386_GLOB_DAT:
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, version, vername)) {
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
// set global offs / size for the symbol
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
@@ -575,8 +584,10 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
break;
case R_386_32:
if (!offs) {
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;
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start")) {
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":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, vername?vername:"(none)", *(void**)p, (void*)(offs+*(uint32_t*)p));
*p += offs;
@@ -585,7 +596,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
case R_386_TLS_TPOFF:
// Negated offset in static TLS block
{
if(!symname || !symname[0]) {
if(!symname || !symname[0] || bind==STB_LOCAL) {
h_tls = head;
offs = sym->st_value;
} else {
@@ -655,12 +666,12 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_TLS_DTPOFF32 %p (%p) in %s\n", symname, p, *(void**)p, head->name);
}
} else {
if(h_tls)
offs = sym->st_value;
if(!symname || !symname[0]) {
offs = (uintptr_t)((intptr_t)(head->tlsaddr + head->delta) - (intptr_t)offs); // negative offset
}
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":((bind==STB_WEAK)?"Weak":"Global"), p, symname, (void*)tlsoffset, (void*)offs);
*p = tlsoffset;
printf_dump(LOG_NEVER, "Apply %s R_386_TLS_DTPOFF32 %p with sym=%s (ver=%d/%s) (%zd -> %zd)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, vername?vername:"(none)", (intptr_t)*p, (intptr_t)offs);
*p = offs;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s found, but R_386_TLS_DTPOFF32 Slot Offset is NULL \n", symname);
}
@@ -685,14 +696,22 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
uint32_t *p = (uint32_t*)(rela[i].r_offset + head->delta);
uintptr_t offs = 0;
uintptr_t end = 0;
size_t size = sym->st_size;
elfheader_t* h_tls = NULL;//head;
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;
if(!symname || !symname[0]) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
} else {
if(!offs && !end && local_maplib)
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
if(!offs && !end)
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
}
} else {
// this is probably very very wrong. A proprer way to get reloc need to be writen, but this hack seems ok for now
// at least it work for half-life, unreal, ut99, zsnes, Undertale, ColinMcRae Remake, FTL, ShovelKnight...
@@ -736,9 +755,9 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
offs = end = 0;
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);
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername);
if(!offs)
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername);
if(!offs) {offs = globoffs; end = globend;}
if(offs) {
// add r_addend to p?
@@ -750,7 +769,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
}
break;
case R_386_GLOB_DAT:
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, version, vername)) {
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
// set global offs / size for the symbol
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
@@ -825,7 +844,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
case R_386_TLS_TPOFF:
// Negated offset in static TLS block
{
if(!symname || !symname[0]) {
if(!symname || !symname[0] || bind==STB_LOCAL) {
h_tls = head;
offs = sym->st_value;
} else {
@@ -895,8 +914,9 @@ 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_TLS_DTPOFF32 %p (%p) in %s\n", symname, p, *(void**)p, head->name);
}
} else {
if(h_tls)
offs = sym->st_value;
if(!symname || !symname[0]) {
offs = (uintptr_t)((intptr_t)(head->tlsaddr + head->delta) - (intptr_t)offs); // negative offset
}
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":((bind==STB_WEAK)?"Weak":"Global"), p, symname, (void*)tlsoffset, (void*)offs);
@@ -950,7 +970,7 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
return -1;
}
if(need_resolver) {
if(pltResolver==~0) {
if(pltResolver==~(uintptr_t)0) {
pltResolver = AddBridge(my_context->system, vFEv, PltResolver, 0, "(PltResolver)");
}
if(head->pltgot) {
@@ -968,7 +988,7 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
return 0;
}
void CalcStack(elfheader_t* elf, uint32_t* stacksz, int* stackalign)
void CalcStack(elfheader_t* elf, uint32_t* stacksz, uint32_t* stackalign)
{
if(*stacksz < elf->stacksz)
*stacksz = elf->stacksz;
@@ -979,7 +999,7 @@ void CalcStack(elfheader_t* elf, uint32_t* stacksz, int* stackalign)
Elf32_Sym* GetFunction(elfheader_t* h, const char* name)
{
// TODO: create a hash on named to avoid this loop
for (int i=0; i<h->numSymTab; ++i) {
for (uint32_t i=0; i<h->numSymTab; ++i) {
int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
if(type==STT_FUNC) {
const char * symname = h->StrTab+h->SymTab[i].st_name;
@@ -993,7 +1013,7 @@ Elf32_Sym* GetFunction(elfheader_t* h, const char* name)
Elf32_Sym* GetElfObject(elfheader_t* h, const char* name)
{
for (int i=0; i<h->numSymTab; ++i) {
for (uint32_t i=0; i<h->numSymTab; ++i) {
int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
if(type==STT_OBJECT) {
const char * symname = h->StrTab+h->SymTab[i].st_name;
@@ -1015,6 +1035,7 @@ uintptr_t GetFunctionAddress(elfheader_t* h, const char* name)
uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h)
{
(void)maplib;
uintptr_t ep = h->entrypoint + h->delta;
printf_log(LOG_DEBUG, "Entry Point is %p\n", (void*)ep);
if(box86_dump) {
@@ -1061,7 +1082,7 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
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)) {
&& (vis==STV_DEFAULT || vis==STV_PROTECTED || (vis==STV_HIDDEN && bind==STB_LOCAL)) && (h->SymTab[i].st_shndx!=0)) {
if(strstr(symname, "@@")) {
char symnameversionned[strlen(symname)+1];
strcpy(symnameversionned, symname);
@@ -1108,7 +1129,7 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
int type = ELF32_ST_TYPE(h->DynSym[i].st_info);
int vis = h->DynSym[i].st_other&0x3;
if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE)
&& (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) {
&& (vis==STV_DEFAULT || vis==STV_PROTECTED || (vis==STV_HIDDEN && bind==STB_LOCAL)) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) {
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;
@@ -1154,7 +1175,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, lib
{
DumpDynamicRPath(h);
// update RPATH first
for (int i=0; i<h->numDynamic; ++i)
for (uint32_t i=0; i<h->numDynamic; ++i)
if(h->Dynamic[i].d_tag==DT_RPATH || h->Dynamic[i].d_tag==DT_RUNPATH) {
char *rpathref = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
char* rpath = rpathref;
@@ -1211,12 +1232,12 @@ int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, lib
DumpDynamicNeeded(h);
int cnt = 0;
for (int i=0; i<h->numDynamic; ++i)
for (uint32_t i=0; i<h->numDynamic; ++i)
if(h->Dynamic[i].d_tag==DT_NEEDED)
++cnt;
const char* nlibs[cnt];
int j=0;
for (int i=0; i<h->numDynamic; ++i)
for (uint32_t i=0; i<h->numDynamic; ++i)
if(h->Dynamic[i].d_tag==DT_NEEDED)
nlibs[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
@@ -1233,7 +1254,7 @@ int ElfCheckIfUseTCMallocMinimal(elfheader_t* h)
{
if(!h)
return 0;
for (int i=0; i<h->numDynamic; ++i)
for (uint32_t i=0; i<h->numDynamic; ++i)
if(h->Dynamic[i].d_tag==DT_NEEDED) {
char *needed = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
if(!strcmp(needed, "libtcmalloc_minimal.so.4")) // tcmalloc needs to be the 1st lib loaded
@@ -1268,6 +1289,34 @@ void MarkElfInitDone(elfheader_t* h)
if(h)
h->init_done = 1;
}
void RunElfInitPltResolver(elfheader_t* h, x86emu_t *emu)
{
if(!h || h->init_done)
return;
uintptr_t p = h->initentry + h->delta;
h->init_done = 1;
for(int i=0; i<h->neededlibs->size; ++i) {
library_t *lib = h->neededlibs->libs[i];
elfheader_t *lib_elf = GetElf(lib);
if(lib_elf)
RunElfInitPltResolver(lib_elf, emu);
}
printf_log(LOG_DEBUG, "Calling Init for %s %p\n", ElfName(h), (void*)p);
if(h->initentry)
RunSafeFunction(my_context, p, 3, my_context->argc, my_context->argv, my_context->envv);
printf_log(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
// and check init array now
Elf32_Addr *addr = (Elf32_Addr*)(h->initarray + h->delta);
for (int i=0; i<h->initarray_sz; ++i) {
printf_log(LOG_DEBUG, "Calling Init[%d] for %s %p\n", i, ElfName(h), (void*)addr[i]);
RunSafeFunction(my_context, (uintptr_t)addr[i], 3, my_context->argc, my_context->argv, my_context->envv);
}
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;
}
void RunElfInit(elfheader_t* h, x86emu_t *emu)
{
if(!h || h->init_done)
@@ -1404,7 +1453,7 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
if(!h)
return ret;
for (int i=0; (i<h->numSymTab) && (distance!=0); ++i) {
for (uint32_t i=0; (i<h->numSymTab) && (distance!=0); ++i) {
const char * symname = h->StrTab+h->SymTab[i].st_name;
uintptr_t offs = h->SymTab[i].st_value + h->delta;
@@ -1417,7 +1466,7 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
}
}
}
for (int i=0; (i<h->numDynSym) && (distance!=0); ++i) {
for (uint32_t i=0; (i<h->numDynSym) && (distance!=0); ++i) {
const char * symname = h->DynStr+h->DynSym[i].st_name;
uintptr_t offs = h->DynSym[i].st_value + h->delta;
@@ -1538,7 +1587,7 @@ void* ElfSetBrk(void* newbrk)
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) {
if(added>0 && (uint32_t)added<h->reserve) {
my_context->brksz = added;
return newbrk;
}
@@ -1671,7 +1720,7 @@ EXPORT int my_dl_iterate_phdr(x86emu_t *emu, void* F, void *data) {
void ResetSpecialCaseMainElf(elfheader_t* h)
{
Elf32_Sym *sym = NULL;
for (int i=0; i<h->numDynSym; ++i) {
for (uint32_t i=0; i<h->numDynSym; ++i) {
if(h->DynSym[i].st_info == 17) {
sym = h->DynSym+i;
const char * symname = h->DynStr+sym->st_name;
@@ -1759,6 +1808,7 @@ typedef struct search_symbol_s{
} search_symbol_t;
int dl_iterate_phdr_findsymbol(struct dl_phdr_info* info, size_t size, void* data)
{
(void)size;
search_symbol_t* s = (search_symbol_t*)data;
for(int j = 0; j<info->dlpi_phnum; ++j) {
@@ -1823,7 +1873,7 @@ void* GetNativeSymbolUnversionned(void* lib, const char* name)
return s.addr;
}
uintptr_t pltResolver = ~0;
uintptr_t pltResolver = ~(uintptr_t)0;
EXPORT void PltResolver(x86emu_t* emu)
{
uintptr_t addr = Pop32(emu);
@@ -1855,6 +1905,12 @@ EXPORT void PltResolver(x86emu_t* emu)
emu->quit = 1;
return;
} else {
elfheader_t* sym_elf = FindElfAddress(my_context, offs);
if(sym_elf && sym_elf!=my_context->elfs[0] && !sym_elf->init_done) {
printf_dump(LOG_DEBUG, "symbol %s from %s but elf not initialized yet, run Init now (from %s)\n", symname, ElfName(sym_elf), ElfName(h));
RunElfInitPltResolver(sym_elf, emu);
}
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":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, symname, vername?"@":"", vername?vername:"",*(void**)p, (void*)offs, ElfName(FindElfAddress(my_context, offs)));
*p = offs;
+9 -9
View File
@@ -15,21 +15,21 @@ typedef struct kh_mapsymbols_s kh_mapsymbols_t;
struct elfheader_s {
char* name;
char* path; // Resolved path to file
int numPHEntries;
uint16_t numPHEntries;
Elf32_Phdr *PHEntries;
int numSHEntries;
uint16_t numSHEntries;
Elf32_Shdr *SHEntries;
int SHIdx;
int numSST;
char* SHStrTab;
char* StrTab;
Elf32_Sym* SymTab;
int numSymTab;
uint32_t numSymTab;
char* DynStr;
Elf32_Sym* DynSym;
int numDynSym;
uint32_t numDynSym;
Elf32_Dyn* Dynamic;
int numDynamic;
uint32_t numDynamic;
char* DynStrTab;
int szDynStrTab;
Elf32_Half* VerSym;
@@ -73,15 +73,15 @@ struct elfheader_s {
uintptr_t paddr;
uintptr_t vaddr;
int align;
uint32_t align;
uint32_t memsz;
uint32_t reserve;
uint32_t stacksz;
int stackalign;
uint32_t stackalign;
uintptr_t tlsaddr;
uint32_t tlssize;
uint32_t tlsfilesize;
int tlsalign;
uint32_t tlsalign;
int32_t tlsbase; // the base of the tlsdata in the global tlsdata (always negative)
@@ -116,4 +116,4 @@ struct elfheader_s {
elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec);
#endif //__ELFLOADER_PRIVATE_H_
#endif //__ELFLOADER_PRIVATE_H_
+3 -3
View File
@@ -43,7 +43,7 @@ int FindSection(Elf32_Shdr *s, int n, char* SHStrTab, const char* name)
return 0;
}
void LoadNamedSection(FILE *f, Elf32_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, int* num)
void LoadNamedSection(FILE *f, Elf32_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, uint32_t* num)
{
int n = FindSection(s, size, SHStrTab, name);
printf_dump(LOG_DEBUG, "Loading %s (idx = %d)\n", clearname, n);
@@ -136,7 +136,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->numSHEntries = section.sh_size;
}
// now read all section headers
printf_dump(LOG_DEBUG, "Read %d Section header\n", h->numSHEntries);
printf_dump(LOG_DEBUG, "Read %u 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) {
@@ -188,7 +188,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
// grab DT_REL & DT_RELA stuffs
// also grab the DT_STRTAB string table
{
for (int i=0; i<h->numDynamic; ++i) {
for (uint32_t i=0; i<h->numDynamic; ++i) {
Elf32_Dyn d = h->Dynamic[i];
Elf32_Word val = d.d_un.d_val;
Elf32_Addr ptr = d.d_un.d_ptr;
+34 -30
View File
@@ -144,16 +144,12 @@
break;
}
NEXT;
_0f_0x19: /* HINT_NOP (multi-byte) */
_0f_0x1A: /* NOP (multi-byte) / ignored BNDLDX */
nextop = F8;
GET_ED;
NEXT;
_0f_0x1B: /* NOP (multi-byte) / ignored BNDSTX */
nextop = F8;
GET_ED;
NEXT;
_0f_0x1C: /* HINT_NOP (multi-byte) */
_0f_0x1D: /* HINT_NOP (multi-byte) */
_0f_0x1E: /* HINT_NOP (multi-byte) */
_0f_0x1F: /* NOP (multi-byte) */
nextop = F8;
GET_ED;
@@ -186,31 +182,37 @@
_0f_0x2C: /* CVTTPS2PI Gm, Ex */
nextop = F8;
GET_EX;
GM.sd[1] = EX->f[1];
GM.sd[0] = EX->f[0];
if(isnanf(EX->f[1]) || isinff(EX->f[1]) || EX->f[1]>0x7fffffff)
GM.sd[1] = 0x80000000;
else
GM.sd[1] = EX->f[1];
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>0x7fffffff)
GM.sd[0] = 0x80000000;
else
GM.sd[0] = EX->f[0];
NEXT;
_0f_0x2D: /* CVTPS2PI Gm, Ex */
// rounding should be done; and indefinite integer should also be assigned if overflow or NaN/Inf
nextop = F8;
GET_EX;
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GM.sd[1] = floorf(EX->f[1]+0.5f);
GM.sd[0] = floorf(EX->f[0]+0.5f);
break;
case ROUND_Down:
GM.sd[1] = floorf(EX->f[1]);
GM.sd[0] = floorf(EX->f[0]);
break;
case ROUND_Up:
GM.sd[1] = ceilf(EX->f[1]);
GM.sd[0] = ceilf(EX->f[0]);
break;
case ROUND_Chop:
GM.sd[1] = EX->f[1];
GM.sd[0] = EX->f[0];
break;
}
for(int i=1; i>=0; --i)
if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>0x7fffffff)
GM.sd[i] = 0x80000000;
else
switch(emu->mxcsr.f.MXCSR_RC) {
case ROUND_Nearest:
GM.sd[i] = nearbyintf(EX->f[i]);
break;
case ROUND_Down:
GM.sd[i] = floorf(EX->f[i]);
break;
case ROUND_Up:
GM.sd[i] = ceilf(EX->f[i]);
break;
case ROUND_Chop:
GM.sd[i] = EX->f[i];
break;
}
NEXT;
_0f_0x2E: /* UCOMISS Gx, Ex */
// same for now
@@ -900,10 +902,12 @@
fpu_fxrstor(emu, ED);
break;
case 2: /* LDMXCSR Md */
emu->mxcsr = ED->dword[0];
emu->mxcsr.x32 = ED->dword[0];
break;
case 3: /* STMXCSR Md */
ED->dword[0] = emu->mxcsr;
ED->dword[0] = emu->mxcsr.x32;
if(box86_sse_flushto0)
applyFlushTo0(emu);
break;
default:
goto _default;
+53 -34
View File
@@ -30,25 +30,31 @@
case 0x2C: /* CVTTSD2SI Gd, Ex */
nextop = F8;
GET_EX;
GD.sdword[0] = EX->d[0];
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
GD.dword[0] = 0x80000000;
else
GD.sdword[0] = EX->d[0];
break;
case 0x2D: /* CVTSD2SI Gd, Ex */
nextop = F8;
GET_EX;
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GD.sdword[0] = floor(EX->d[0]+0.5);
break;
case ROUND_Down:
GD.sdword[0] = floor(EX->d[0]);
break;
case ROUND_Up:
GD.sdword[0] = ceil(EX->d[0]);
break;
case ROUND_Chop:
GD.sdword[0] = EX->d[0];
break;
}
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
GD.dword[0] = 0x80000000;
else
switch(emu->mxcsr.f.MXCSR_RC) {
case ROUND_Nearest:
GD.sdword[0] = nearbyint(EX->d[0]);
break;
case ROUND_Down:
GD.sdword[0] = floor(EX->d[0]);
break;
case ROUND_Up:
GD.sdword[0] = ceil(EX->d[0]);
break;
case ROUND_Chop:
GD.sdword[0] = EX->d[0];
break;
}
break;
case 0x51: /* SQRTSD Gx, Ex */
nextop = F8;
@@ -119,7 +125,7 @@
case 0x5F: /* MAXSD Gx, Ex */
nextop = F8;
GET_EX;
if (isnan(GX.d[0]) || isnan(EX->d[0]) || isgreater(EX->d[0], GX.d[0]))
if (isnan(GX.d[0]) || isnan(EX->d[0]) || isgreaterequal(EX->d[0], GX.d[0]))
GX.d[0] = EX->d[0];
break;
@@ -151,6 +157,19 @@
GX.f[3] = EX->f[2] + EX->f[3];
}
break;
case 0x7D: /* HSUBPS Gx, Ex */
nextop = F8;
GET_EX;
GX.f[0] -= GX.f[1];
GX.f[1] = GX.f[2] - GX.f[3];
if(EX==&GX) {
GX.f[2] = GX.f[0];
GX.f[3] = GX.f[1];
} else {
GX.f[2] = EX->f[0] - EX->f[1];
GX.f[3] = EX->f[2] - EX->f[3];
}
break;
#define GOCOND(BASE, PREFIX, CONDITIONAL) \
case BASE+0: \
@@ -275,24 +294,24 @@
case 0xE6: /* CVTPD2DQ Gx, Ex */
nextop = F8;
GET_EX;
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GX.sd[0] = floor(EX->d[0]+0.5);
GX.sd[1] = floor(EX->d[1]+0.5);
break;
case ROUND_Down:
GX.sd[0] = floor(EX->d[0]);
GX.sd[1] = floor(EX->d[1]);
break;
case ROUND_Up:
GX.sd[0] = ceil(EX->d[0]);
GX.sd[1] = ceil(EX->d[1]);
break;
case ROUND_Chop:
GX.sd[0] = EX->d[0];
GX.sd[1] = EX->d[1];
break;
}
for(int i=0; i<2; ++i)
if(isnan(EX->d[i]) || isinf(EX->d[i]) || EX->d[i]>0x7fffffff)
GX.ud[i] = 0x80000000;
else
switch(emu->mxcsr.f.MXCSR_RC) {
case ROUND_Nearest:
GX.sd[i] = nearbyint(EX->d[i]);
break;
case ROUND_Down:
GX.sd[i] = floor(EX->d[i]);
break;
case ROUND_Up:
GX.sd[i] = ceil(EX->d[i]);
break;
case ROUND_Chop:
GX.sd[i] = EX->d[i];
break;
}
GX.q[1] = 0;
break;
+28 -21
View File
@@ -47,25 +47,31 @@
case 0x2C: /* CVTTSS2SI Gd, Ex */
nextop = F8;
GET_EX;
GD.sdword[0] = EX->f[0];
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>0x7fffffff)
GD.dword[0] = 0x80000000;
else
GD.sdword[0] = EX->f[0];
break;
case 0x2D: /* CVTSS2SI Gd, Ex */
nextop = F8;
GET_EX;
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GD.sdword[0] = floor(EX->f[0]+0.5);
break;
case ROUND_Down:
GD.sdword[0] = floor(EX->f[0]);
break;
case ROUND_Up:
GD.sdword[0] = ceil(EX->f[0]);
break;
case ROUND_Chop:
GD.sdword[0] = EX->f[0];
break;
}
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>0x7fffffff)
GD.dword[0] = 0x80000000;
else
switch(emu->mxcsr.f.MXCSR_RC) {
case ROUND_Nearest:
GD.sdword[0] = nearbyintf(EX->f[0]);
break;
case ROUND_Down:
GD.sdword[0] = floorf(EX->f[0]);
break;
case ROUND_Up:
GD.sdword[0] = ceilf(EX->f[0]);
break;
case ROUND_Chop:
GD.sdword[0] = EX->f[0];
break;
}
break;
case 0x51: /* SQRTSS Gx, Ex */
@@ -102,10 +108,11 @@
case 0x5B: /* CVTTPS2DQ Gx, Ex */
nextop = F8;
GET_EX;
GX.sd[0] = EX->f[0];
GX.sd[1] = EX->f[1];
GX.sd[2] = EX->f[2];
GX.sd[3] = EX->f[3];
for(int i=0; i<4; ++i)
if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>0x7fffffff)
GX.ud[i] = 0x80000000;
else
GX.sd[i] = EX->f[i];
break;
case 0x5C: /* SUBSS Gx, Ex */
@@ -116,7 +123,7 @@
case 0x5D: /* MINSS Gx, Ex */
nextop = F8;
GET_EX;
if(isnan(GX.f[0]) || isnan(EX->f[0]) || isless(EX->f[0], GX.f[0]))
if(isnan(GX.f[0]) || isnan(EX->f[0]) || islessequal(EX->f[0], GX.f[0]))
GX.f[0] = EX->f[0];
break;
case 0x5E: /* DIVSS Gx, Ex */
@@ -127,7 +134,7 @@
case 0x5F: /* MAXSS Gx, Ex */
nextop = F8;
GET_EX;
if (isnan(GX.f[0]) || isnan(EX->f[0]) || isgreater(EX->f[0], GX.f[0]))
if (isnan(GX.f[0]) || isnan(EX->f[0]) || isgreaterequal(EX->f[0], GX.f[0]))
GX.f[0] = EX->f[0];
break;
+28 -3
View File
@@ -23,6 +23,13 @@
#ifdef DYNAREC
#include "custommem.h"
#endif
// for the applyFlushTo0
#ifdef __i386__
#include <immintrin.h>
#elif defined(__arm__)
#else
#warning Architecture cannot follow SSE Flush to 0 flag
#endif
typedef struct cleanup_s {
void* f;
@@ -81,13 +88,13 @@ static void internalX86Setup(x86emu_t* emu, box86context_t *context, uintptr_t s
emu->segs[_GS] = 0x33;
// setup fpu regs
reset_fpu(emu);
emu->mxcsr = 0x1f80;
emu->mxcsr.x32 = 0x1f80;
}
EXPORTDYN
x86emu_t *NewX86Emu(box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
{
printf_log(LOG_DEBUG, "Allocate a new X86 Emu, with EIP=%p and Stack=%p/0x%X\n", (void*)start, (void*)stack, stacksize);
printf_log(LOG_DEBUG, "%04d|Allocate a new X86 Emu, with EIP=%p and Stack=%p/0x%X\n", GetTID(), (void*)start, (void*)stack, stacksize);
x86emu_t *emu = (x86emu_t*)box_calloc(1, sizeof(x86emu_t));
@@ -98,7 +105,7 @@ x86emu_t *NewX86Emu(box86context_t *context, uintptr_t start, uintptr_t stack, i
x86emu_t *NewX86EmuFromStack(x86emu_t* emu, box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
{
printf_log(LOG_DEBUG, "New X86 Emu from stack, with EIP=%p and Stack=%p/0x%X\n", (void*)start, (void*)stack, stacksize);
printf_log(LOG_DEBUG, "%04d|New X86 Emu from stack, with EIP=%p and Stack=%p/0x%X\n", GetTID(), (void*)start, (void*)stack, stacksize);
internalX86Setup(emu, context, start, stack, stacksize, ownstack);
@@ -108,6 +115,7 @@ x86emu_t *NewX86EmuFromStack(x86emu_t* emu, box86context_t *context, uintptr_t s
EXPORTDYN
void SetupX86Emu(x86emu_t *emu)
{
(void)emu;
printf_log(LOG_DEBUG, "Setup X86 Emu\n");
}
@@ -128,6 +136,7 @@ void SetTraceEmu(uintptr_t start, uintptr_t end)
void AddCleanup(x86emu_t *emu, void *p)
{
(void)emu;
if(my_context->clean_sz == my_context->clean_cap) {
my_context->clean_cap += 4;
my_context->cleanups = (cleanup_t*)box_realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
@@ -139,6 +148,7 @@ void AddCleanup(x86emu_t *emu, void *p)
void AddCleanup1Arg(x86emu_t *emu, void *p, void* a)
{
(void)emu;
if(my_context->clean_sz == my_context->clean_cap) {
my_context->clean_cap += 4;
my_context->cleanups = (cleanup_t*)box_realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
@@ -458,6 +468,7 @@ static inline void init_perfcounters (int32_t do_reset, int32_t enable_divider)
uint64_t ReadTSC(x86emu_t* emu)
{
(void)emu;
// Read the TimeStamp Counter as 64bits.
// this is supposed to be the number of instructions executed since last reset
#if defined(__i386__)
@@ -497,3 +508,17 @@ void ResetSegmentsCache(x86emu_t *emu)
return;
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
}
void applyFlushTo0(x86emu_t* emu)
{
#ifdef __i386__
_mm_setcsr(_mm_getcsr() | (emu->mxcsr.x32&0x8040));
#elif defined(__arm__)
uint64_t fpscr = __builtin_arm_get_fpscr();
fpscr &= ~(1<<24); // clear bit FZ (24)
fpscr |= (emu->mxcsr.f.MXCSR_FZ)<<24; // set FZ as mxcsr FZ
__builtin_arm_set_fpscr(fpscr);
#else
(void)emu;
#endif
}
+3 -1
View File
@@ -40,7 +40,7 @@ typedef struct x86emu_s {
fpu_p_reg_t p_regs[8];
// sse
sse_regs_t xmm[8];
uint32_t mxcsr;
mmxcontrol_t mxcsr;
uintptr_t old_ip;
// defered flags
defered_flags_t df;
@@ -88,4 +88,6 @@ typedef struct x86emu_s {
//#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0; emu->quit=1;}
#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0;} // should rise a SIGFPE and not quit
void applyFlushTo0(x86emu_t* emu);
#endif //__X86EMU_PRIVATE_H_
+103 -76
View File
@@ -10,6 +10,7 @@
#include <sys/types.h>
#include <pthread.h>
#include <signal.h>
#include <wait.h>
#include "debug.h"
#include "box86stack.h"
@@ -53,7 +54,10 @@ x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
for (int i=0; i<my_context->atfork_sz; --i)
if(my_context->atforks[i].parent)
EmuCall(emu, my_context->atforks[i].parent);
if(forktype==3) {
// vfork, the parent wait the end or execve of the son
waitpid(v, NULL, WEXITED);
}
} else if(v==0) {
// execute atforks child functions
for (int i=0; i<my_context->atfork_sz; --i)
@@ -87,6 +91,8 @@ void x86Int3(x86emu_t* emu)
if(h && strstr(ElfName(h), "libMiles")) have_trace = 1;*/
if(box86_log>=LOG_DEBUG || cycle_log) {
int tid = GetTID();
const char *s = NULL;
s = GetNativeName((void*)addr);
char t_buff[256] = "\0";
char buff2[64] = "\0";
char buff3[64] = "\0";
@@ -94,213 +100,220 @@ void x86Int3(x86emu_t* emu)
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);
my_context->current_line = (my_context->current_line+1)%cycle_log;
char *tmp;
int post = 0;
int perr = 0;
uint32_t *pu32 = NULL;
const char *s = NULL;
s = GetNativeName((void*)addr);
if(addr==(uintptr_t)PltResolver) {
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));
snprintf(buff, 256, "%04d|%p: Calling %s(%s, %s)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "glColor4f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12), *(float*)(R_ESP+16));
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12), *(float*)(R_ESP+16));
} else if(strstr(s, "glTexCoord2f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
} else if(strstr(s, "glVertex2f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
} else if(strstr(s, "glVertex3f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12));
} else if(strstr(s, "__open64")==s || strcmp(s, "open64")==0) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(int*)(R_ESP+8), *(int*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(int*)(R_ESP+8), *(int*)(R_ESP+12));
perr = 1;
} else if(!strcmp(s, "opendir")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
perr = 1;
} else if(strstr(s, "__open")==s || !strcmp(s, "open") || !strcmp(s, "my_open64")) {
tmp = *(char**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
perr = 1;
} else if(!strcmp(s, "shm_open")) {
tmp = *(char**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
perr = 1;
} else if(strcmp(s, "mkdir")==0) {
tmp = *(char**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8));
perr = 1;
} else if(!strcmp(s, "fopen")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
perr = 2;
} else if(!strcmp(s, "freopen")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", %p)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\", %p)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 2;
} else if(!strcmp(s, "fopen64")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
perr = 2;
} else if(!strcmp(s, "chdir")) {
pu32=*(uint32_t**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, pu32?((pu32==(uint32_t*)1)?"/1/":(char*)pu32):"/0/");
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, pu32?((pu32==(uint32_t*)1)?"/1/":(char*)pu32):"/0/");
} else if(strstr(s, "getenv")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
post = 2;
} else if(strstr(s, "putenv")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if(strstr(s, "pread")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %u, %d)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12), *(int32_t*)(R_ESP+16));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, %u, %d)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12), *(int32_t*)(R_ESP+16));
perr = 1;
} else if(!strcmp(s, "read")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %u)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, %u)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
perr = 1;
} else if(strstr(s, "ioctl")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, 0x%x, %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(int32_t*)(R_ESP+8), *(void**)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, 0x%x, %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(int32_t*)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "statvfs64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+4), *(void**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+4), *(void**)(R_ESP+8));
} else if(strstr(s, "index")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
} else if(strstr(s, "rindex")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
} else if(strstr(s, "__xstat64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strcmp(s, "__xstat")==0) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "__lxstat64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "sem_timedwait")==s) {
pu32 = *(uint32_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %p[%d sec %d ns])", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), pu32?pu32[0]:-1, pu32?pu32[1]:-1);
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %p[%d sec %d ns])", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), pu32?(int32_t)pu32[0]:-1, pu32?(int32_t)pu32[1]:-1);
perr = 1;
} else if(strstr(s, "waitpid")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, 0x%x)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, 0x%x)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
perr = 1;
} else if(strstr(s, "clock_gettime")==s || strstr(s, "__clock_gettime")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(void**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(void**)(R_ESP+8));
post = 1;
pu32 = *(uint32_t**)(R_ESP+8);
} else if(strstr(s, "semop")==s) {
int16_t* p16 = *(int16_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p[%u/%d/0x%x], %d)", tid, *(void**)(R_ESP), s, *(int*)(R_ESP+4), p16, p16[0], p16[1], p16[2], *(int*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p[%u/%d/0x%x], %d)", tid, *(void**)(R_ESP), s, *(int*)(R_ESP+4), p16, p16[0], p16[1], p16[2], *(int*)(R_ESP+12));
perr = 1;
} else if(!strcmp(s, "mmap64")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %lld)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int64_t*)(R_ESP+24));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %lld)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int64_t*)(R_ESP+24));
perr = 3;
} else if(!strcmp(s, "mmap")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int*)(R_ESP+24));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int*)(R_ESP+24));
perr = 3;
} else if(strstr(s, "strcasecmp")==s || strstr(s, "__strcasecmp")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "gtk_signal_connect_full")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\", %p, %p, %p, %p, %d, %d)", tid, *(void**)(R_ESP), "gtk_signal_connect_full", *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16), *(void**)(R_ESP+20), *(void**)(R_ESP+24), *(int32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\", %p, %p, %p, %p, %d, %d)", tid, *(void**)(R_ESP), "gtk_signal_connect_full", *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16), *(void**)(R_ESP+20), *(void**)(R_ESP+24), *(int32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32));
} else if(strstr(s, "strcmp")==s || strstr(s, "__strcmp")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "strstr")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%.127s\", \"%.127s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%.127s\", \"%.127s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "strlen")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), ((R_ESP+4))?(*(char**)(R_ESP+4)):"nil");
snprintf(buff, 256, "%04d|%p: Calling %s(%p(\"%s\"))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), ((R_ESP+4))?(*(char**)(R_ESP+4)):"nil");
} else if(strstr(s, "vsnprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %u, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%08X, %u, %p(\"%s\")...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(void**)(R_ESP+12), *(char**)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "vsprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "__vsprintf_chk")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %d, %zu, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(int*)(R_ESP+8), *(size_t*)(R_ESP+12), *(char**)(R_ESP+16), *(void**)(R_ESP+20));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %d, %zu, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(int*)(R_ESP+8), *(size_t*)(R_ESP+12), *(char**)(R_ESP+16), *(void**)(R_ESP+20));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "__snprintf_chk")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, %d, %d, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(char**)(R_ESP+20), *(void**)(R_ESP+24));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %zu, %d, %d, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(char**)(R_ESP+20), *(void**)(R_ESP+24));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "snprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(char**)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %zu, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(char**)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "sprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "printf")==s) {
pu32 = *(uint32_t**)(R_ESP+4);
if(((uintptr_t)pu32)<0x5) // probably a _chk function
pu32 = *(uint32_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, pu32?((char*)(pu32)):"nil");
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, pu32?((char*)(pu32)):"nil");
} else if(strstr(s, "wprintf")==s) {
pu32 = *(uint32_t**)(R_ESP+4);
if(((uintptr_t)pu32)<0x5) // probably a _chk function
pu32 = *(uint32_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%S\"...)", tid, *(void**)(R_ESP), s, pu32?((wchar_t*)(pu32)):L"nil");
snprintf(buff, 256, "%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)", 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, 256, "%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));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %zu, \"%S\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(wchar_t**)(R_ESP+12), *(void**)(R_ESP+16));
pu32 = *(uint32_t**)(R_ESP+4);
post = 6;
}
} else if(strstr(s, "puts")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if(strstr(s, "fputs")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %p...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(void**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %p...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(void**)(R_ESP+8));
} else if(strstr(s, "fprintf")==s) {
pu32 = *(uint32_t**)(R_ESP+8);
if(((uintptr_t)pu32)<0x5) // probably a __fprint_chk
pu32 = *(uint32_t**)(R_ESP+12);
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
snprintf(buff, 256, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
} else if(strstr(s, "vfprintf")==s) {
pu32 = *(uint32_t**)(R_ESP+8);
if(((uintptr_t)pu32)<0x5) // probably a _chk function
pu32 = *(uint32_t**)(R_ESP+12);
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
snprintf(buff, 256, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
} else if(strstr(s, "vkGetInstanceProcAddr")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "vkGetDeviceProcAddr")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "glXGetProcAddress")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if(strstr(s, "sscanf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(!strcmp(s, "vsscanf")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "XCreateWindow")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %p, %d, %d, %u, %u, %u, %d, %u, %p, %u, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(uint32_t*)(R_ESP+20), *(uint32_t*)(R_ESP+24), *(uint32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32), *(uint32_t*)(R_ESP+36), *(void**)(R_ESP+40), *(uint32_t*)(R_ESP+44), *(void**)(R_ESP+48));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %p, %d, %d, %u, %u, %u, %d, %u, %p, %u, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(uint32_t*)(R_ESP+20), *(uint32_t*)(R_ESP+24), *(uint32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32), *(uint32_t*)(R_ESP+36), *(void**)(R_ESP+40), *(uint32_t*)(R_ESP+44), *(void**)(R_ESP+48));
} else if(strstr(s, "XLoadQueryFont")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "pthread_mutex_lock")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
snprintf(buff, 256, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
} else if(!strcmp(s, "fmodf")) {
post = 4;
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
} else if(!strcmp(s, "fmod")) {
post = 4;
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(double*)(R_ESP+4), *(double*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(double*)(R_ESP+4), *(double*)(R_ESP+12));
} else if(strstr(s, "SDL_GetWindowSurface")==s) {
post = 5;
snprintf(buff, 255, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
snprintf(buff, 256, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
} else if(strstr(s, "udev_monitor_new_from_netlink")==s) {
post = 5;
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(!strcmp(s, "syscall")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %p, %p...)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, %p, %p...)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16));
perr = 1;
} else if(strstr(s, "___tls_get_addr")) {
snprintf(buff, 256, "%04d|%p: Calling %s(%p[%d, %d])", tid, *(void**)(R_ESP), s, (void*)(R_EAX), ((int*)(R_EAX))[0], ((int*)(R_EAX))[1]);
} else if(strstr(s, "__tls_get_addr")) {
pu32 = *(uint32_t**)(R_ESP+4);
snprintf(buff, 256, "%04d|%p: Calling %s(%p[%d, %d])", tid, *(void**)(R_ESP), s, pu32, pu32[0], pu32[1]);
} else if (!strcmp(s, "XDrawImageString")) {
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %p, %p, %i, %i, %p\"%s\", %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), *(void**)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(char**)(R_ESP+24), *(char**)(R_ESP+24), *(int*)(R_ESP+28));
} else {
snprintf(buff, 255, "%04d|%p: Calling %s (%08X, %08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
snprintf(buff, 256, "%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));
}
if(!cycle_log) {
mutex_lock(&emu->context->mutex_trace);
printf_log(LOG_NONE, "%s =>", buff);
mutex_unlock(&emu->context->mutex_trace);
}
pthread_mutex_lock(&emu->context->mutex_trace);
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)
switch(post) {
case 1: snprintf(buff2, 63, " [%d sec %d nsec]", pu32?pu32[0]:-1, pu32?pu32[1]:-1);
case 1: snprintf(buff2, 63, " [%d sec %d nsec]", pu32?(int32_t)pu32[0]:-1, pu32?(int32_t)pu32[1]:-1);
break;
case 2: snprintf(buff2, 63, "(%s)", R_EAX?((char*)R_EAX):"nil");
break;
@@ -325,12 +338,13 @@ void x86Int3(x86emu_t* emu)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
else if(perr==3 && ((int)R_EAX)==-1)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
pthread_mutex_lock(&emu->context->mutex_trace);
if(cycle_log)
snprintf(buffret, 127, "0x%X%s%s", R_EAX, buff2, buff3);
else
else {
mutex_lock(&emu->context->mutex_trace);
printf_log(LOG_NONE, " return 0x%08X%s%s\n", R_EAX, buff2, buff3);
pthread_mutex_unlock(&emu->context->mutex_trace);
mutex_unlock(&emu->context->mutex_trace);
}
} else
w(emu, addr);
}
@@ -346,4 +360,17 @@ void x86Int3(x86emu_t* emu)
int GetTID()
{
return syscall(SYS_gettid);
}
}
void print_cycle_log(int loglevel) {
if(cycle_log) {
printf_log(LOG_INFO, "Last calls\n");
int j = (my_context->current_line+1)%cycle_log;
for (int i=0; i<cycle_log; ++i) {
int k = (i+j)%cycle_log;
if(my_context->log_call[k][0]) {
printf_log(loglevel, "%s => return %s\n", my_context->log_call[k], my_context->log_ret[k]);
}
}
}
}
+8 -8
View File
@@ -1044,14 +1044,14 @@ Implements the SBB instruction and side effects.
****************************************************************************/
uint16_t sbb16(x86emu_t *emu, uint16_t d, uint16_t s)
{
uint32_t res; /* all operands in native machine order */
uint32_t bc;
uint32_t res; /* all operands in native machine order */
uint32_t bc;
CHECK_FLAGS(emu);
if (ACCESS_FLAG(F_CF))
res = d - s - 1;
else
res = d - s;
res = d - s - 1;
else
res = d - s;
CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
@@ -1075,9 +1075,9 @@ uint32_t sbb32(x86emu_t *emu, uint32_t d, uint32_t s)
CHECK_FLAGS(emu);
if (ACCESS_FLAG(F_CF))
res = d - s - 1;
else
res = d - s;
res = d - s - 1;
else
res = d - s;
CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(!res, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+3
View File
@@ -247,6 +247,7 @@ Implements the NOT instruction
****************************************************************************/
static inline uint8_t not8(x86emu_t *emu, uint8_t s)
{
(void)emu;
return ~s;
}
@@ -256,6 +257,7 @@ Implements the NOT instruction
****************************************************************************/
static inline uint16_t not16(x86emu_t *emu, uint16_t s)
{
(void)emu;
return ~s;
}
@@ -265,6 +267,7 @@ Implements the NOT instruction
****************************************************************************/
static inline uint32_t not32(x86emu_t *emu, uint32_t s)
{
(void)emu;
return ~s;
}
+19 -3
View File
@@ -93,7 +93,7 @@ int Run(x86emu_t *emu, int step)
&&_0xB0, &&_0xB1, &&_0xB2, &&_0xB3, &&_0xB4, &&_0xB5, &&_0xB6, &&_0xB7,
&&_0xB8, &&_0xB9, &&_0xBA, &&_0xBB, &&_0xBC, &&_0xBD, &&_0xBE, &&_0xBF,
&&_0xC0, &&_0xC1, &&_0xC2, &&_0xC3, &&_0xC4, &&_0xC5, &&_0xC6, &&_0xC7,
&&_0xC8, &&_0xC9, &&_default, &&_0xCB, &&_0xCC, &&_0xCD, &&_default, &&_0xCF, //0xC8-0xCF
&&_0xC8, &&_0xC9, &&_default, &&_0xCB, &&_0xCC, &&_0xCD, &&_0xCE, &&_0xCF, //0xC8-0xCF
&&_0xD0, &&_0xD1, &&_0xD2, &&_0xD3, &&_0xD4, &&_0xD5, &&_0xD6, &&_0xD7,
&&_0xD8, &&_0xD9, &&_0xDA, &&_0xDB, &&_0xDC, &&_0xDD, &&_0xDE, &&_0xDF,
&&_0xE0, &&_0xE1, &&_0xE2, &&_0xE3, &&_0xE4, &&_0xE5, &&_0xE6, &&_0xE7,
@@ -106,7 +106,7 @@ int Run(x86emu_t *emu, int step)
&&_0f_0x00, &&_0f_0x01, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
&&_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
&&_0f_0x18, &&_0f_0x19, &&_0f_0x1A, &&_0f_0x1B, &&_0f_0x1C ,&&_0f_0x1D, &&_0f_0x1E, &&_0f_0x1F, //0x18-0x1F
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x20-0x27
&&_0f_0x28, &&_0f_0x29, &&_0f_0x2A, &&_0f_0x2B, &&_0f_0x2C, &&_0f_0x2D, &&_0f_0x2E, &&_0f_0x2F,
&&_default, &&_0f_0x31, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x30-0x37
@@ -979,7 +979,14 @@ _trace:
goto fini;
}
NEXT;
_0xCE: /* INTO */
emu->old_ip = R_EIP;
R_EIP = ip;
emit_signal(emu, SIGFPE, (void*)R_EIP, FPE_INTOVF);
ip = R_EIP;
if(emu->quit) goto fini;
STEP;
NEXT;
_0xCF: /* IRET */
ip = Pop(emu);
emu->segs[_CS] = Pop(emu)&0xffff;
@@ -1306,6 +1313,15 @@ _trace:
NEXT;
case 0x90: /* PAUSE */
NEXT;
case 0x64: {
nextop = F8;
switch (nextop) {
case 0xF1: /* INT1 */
NEXT;
default:
goto _default;
}
}
case 0xA4: /* REP MOVSB */
while(tmp32u) {
--tmp32u;
+35 -1
View File
@@ -1233,6 +1233,7 @@ void RunFS(x86emu_t *emu)
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = adc32(emu, ED->dword[0], GD.dword[0]);
break;
case 0x2B: /* SUB Gd, FS:Ed */
nextop = F8;
@@ -1462,6 +1463,39 @@ void RunFS(x86emu_t *emu)
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
}
break;
case 0x87:
nextop = F8;
#ifdef DYNAREC
GET_ED_OFFS(tlsdata);
if((nextop&0xC0)==0xC0) {
tmp32u = GD.dword[0];
GD.dword[0] = ED->dword[0];
ED->dword[0] = tmp32u;
} else {
if(((uintptr_t)ED)&3)
{
// not aligned, dont't try to "LOCK"
tmp32u = ED->dword[0];
ED->dword[0] = GD.dword[0];
GD.dword[0] = tmp32u;
} else {
// XCHG is supposed to automaticaly LOCK memory bus
GD.dword[0] = arm_lock_xchg(ED, GD.dword[0]);
}
}
#else
GET_ED_OFFS(tlsdata);
if((nextop&0xC0)!=0xC0)
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
tmp32u = GD.dword[0];
GD.dword[0] = ED->dword[0];
ED->dword[0] = tmp32u;
if((nextop&0xC0)!=0xC0)
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0x89: /* MOV Ed,Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
@@ -1654,4 +1688,4 @@ void RunGS0F(x86emu_t *emu, uintptr_t tlsdata)
UnimpOpcode(emu);
}
R_EIP = ip;
}
}
+57 -53
View File
@@ -224,30 +224,36 @@ void Run660F(x86emu_t *emu)
case 0x2C: /* CVTTPD2PI Gm, Ex */
nextop = F8;
GET_EX;
GM.sd[0] = EX->d[0];
GM.sd[1] = EX->d[1];
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
GM.ud[0] = 0x80000000;
else
GM.sd[0] = EX->d[0];
if(isnan(EX->d[1]) || isinf(EX->d[1]) || EX->d[1]>0x7fffffff)
GM.ud[1] = 0x80000000;
else
GM.sd[1] = EX->d[1];
break;
case 0x2D: /* CVTPD2PI Gm, Ex */
nextop = F8;
GET_EX;
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GM.sd[0] = floor(EX->d[0]+0.5);
GM.sd[1] = floor(EX->d[1]+0.5);
break;
case ROUND_Down:
GM.sd[0] = floor(EX->d[0]);
GM.sd[1] = floor(EX->d[1]);
break;
case ROUND_Up:
GM.sd[0] = ceil(EX->d[0]);
GM.sd[1] = ceil(EX->d[1]);
break;
case ROUND_Chop:
GM.sd[0] = EX->d[0];
GM.sd[1] = EX->d[1];
break;
}
for(int i=0; i<2; ++i)
if(isnan(EX->d[i]) || isinf(EX->d[i]) || EX->d[i]>0x7fffffff)
GM.ud[i] = 0x80000000;
else
switch(emu->mxcsr.f.MXCSR_RC) {
case ROUND_Nearest:
GM.sd[i] = nearbyint(EX->d[i]);
break;
case ROUND_Down:
GM.sd[i] = floor(EX->d[i]);
break;
case ROUND_Up:
GM.sd[i] = ceil(EX->d[i]);
break;
case ROUND_Chop:
GM.sd[i] = EX->d[i];
break;
}
break;
case 0x2E: /* UCOMISD Gx, Ex */
// no special check...
@@ -519,7 +525,7 @@ void Run660F(x86emu_t *emu)
nextop = F8;
GET_EX;
tmp8u = F8;
switch((tmp8u & 4) ? ((emu->mxcsr >> 13) & 3) : (tmp8u & 3))
switch((tmp8u & 4) ? (emu->mxcsr.f.MXCSR_RC) : (tmp8u & 3))
{
case ROUND_Nearest:
GX.f[0] = nearbyint(EX->f[0]);
@@ -551,7 +557,7 @@ void Run660F(x86emu_t *emu)
nextop = F8;
GET_EX;
tmp8u = F8;
switch((tmp8u & 4) ? ((emu->mxcsr >> 13) & 3) : (tmp8u & 3))
switch((tmp8u & 4) ? (emu->mxcsr.f.MXCSR_RC) : (tmp8u & 3))
{
case ROUND_Nearest:
GX.d[0] = nearbyint(EX->d[0]);
@@ -575,7 +581,7 @@ void Run660F(x86emu_t *emu)
nextop = F8;
GET_EX;
tmp8u = F8;
switch((tmp8u & 4) ? ((emu->mxcsr >> 13) & 3) : (tmp8u & 3))
switch((tmp8u & 4) ? (emu->mxcsr.f.MXCSR_RC) : (tmp8u & 3))
{
case ROUND_Nearest:
GX.f[0] = nearbyint(EX->f[0]);
@@ -595,7 +601,7 @@ void Run660F(x86emu_t *emu)
nextop = F8;
GET_EX;
tmp8u = F8;
switch((tmp8u & 4) ? ((emu->mxcsr >> 13) & 3) : (tmp8u & 3))
switch((tmp8u & 4) ? (emu->mxcsr.f.MXCSR_RC) : (tmp8u & 3))
{
case ROUND_Nearest:
GX.d[0] = nearbyint(EX->d[0]);
@@ -775,32 +781,24 @@ void Run660F(x86emu_t *emu)
case 0x5B: /* CVTPS2DQ Gx, Ex */
nextop = F8;
GET_EX;
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GX.sd[0] = floorf(EX->f[0]+0.5f);
GX.sd[1] = floorf(EX->f[1]+0.5f);
GX.sd[2] = floorf(EX->f[2]+0.5f);
GX.sd[3] = floorf(EX->f[3]+0.5f);
break;
case ROUND_Down:
GX.sd[0] = floorf(EX->f[0]);
GX.sd[1] = floorf(EX->f[1]);
GX.sd[2] = floorf(EX->f[2]);
GX.sd[3] = floorf(EX->f[3]);
break;
case ROUND_Up:
GX.sd[0] = ceilf(EX->f[0]);
GX.sd[1] = ceilf(EX->f[1]);
GX.sd[2] = ceilf(EX->f[2]);
GX.sd[3] = ceilf(EX->f[3]);
break;
case ROUND_Chop:
GX.sd[0] = EX->f[0];
GX.sd[1] = EX->f[1];
GX.sd[2] = EX->f[2];
GX.sd[3] = EX->f[3];
break;
}
for(int i=0; i<4; ++i)
if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>0x7fffffff)
GX.sd[i] = 0x80000000;
else
switch(emu->mxcsr.f.MXCSR_RC) {
case ROUND_Nearest:
GX.sd[i] = nearbyintf(EX->f[i]);
break;
case ROUND_Down:
GX.sd[i] = floorf(EX->f[i]);
break;
case ROUND_Up:
GX.sd[i] = ceilf(EX->f[i]);
break;
case ROUND_Chop:
GX.sd[i] = EX->f[i];
break;
}
break;
case 0x5C: /* SUBPD Gx, Ex */
nextop = F8;
@@ -1590,7 +1588,7 @@ void Run660F(x86emu_t *emu)
case 0xE2: /* PSRAD Gx, Ex */
nextop = F8;
GET_EX;
tmp8u=(EX->q[0]>31)?32:EX->ub[0];
tmp8u=(EX->q[0]>31)?31:EX->ub[0];
for (int i=0; i<4; ++i)
GX.sd[i] >>= tmp8u;
break;
@@ -1619,8 +1617,14 @@ void Run660F(x86emu_t *emu)
case 0xE6: /* CVTTPD2DQ Gx, Ex */
nextop = F8;
GET_EX;
GX.sd[0] = EX->d[0];
GX.sd[1] = EX->d[1];
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
GX.sd[0] = 0x80000000;
else
GX.sd[0] = EX->d[0];
if(isnan(EX->d[1]) || isinf(EX->d[1]) || EX->d[1]>0x7fffffff)
GX.sd[1] = 0x80000000;
else
GX.sd[1] = EX->d[1];
GX.q[1] = 0;
break;
case 0xE7: /* MOVNTDQ Ex, Gx */
+4 -3
View File
@@ -50,6 +50,7 @@ void EXPORT my___libc_init(x86emu_t* emu, void* raw_args __unused, void (*onexit
#else
int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
{
(void)argc; (void)ubp_av; (void)fini; (void)rtld_fini; (void)stack_end;
// let's cheat and set all args...
Push(emu, (uint32_t)my_context->envv);
Push(emu, (uint32_t)my_context->argv);
@@ -818,7 +819,7 @@ uintptr_t evalED(x86emu_t* emu, uintptr_t ip) {
if((nextop&7)==4) {
uint8_t sib = PK(0);
++ip;
uintptr_t base = ((sib&0x7)==5)?(PK32(0)):(emu->regs[(sib&0x7)].dword[0]);
uintptr_t base = ((sib&0x7)==5)?(uint32_t)(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) {
@@ -852,7 +853,7 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
(trace_end == 0)
|| ((ip >= trace_start) && (ip < trace_end))) ) {
int tid = syscall(SYS_gettid);
pthread_mutex_lock(&my_context->mutex_trace);
mutex_lock(&my_context->mutex_trace);
#ifdef DYNAREC
if((my_context->trace_tid != tid) || (my_context->trace_dynarec!=dynarec)) {
printf_log(LOG_NONE, "Thread %04d| (%s) |\n", tid, dynarec?"dyn":"int");
@@ -895,7 +896,7 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
}
printf_log(LOG_NONE, "\n");
}
pthread_mutex_unlock(&my_context->mutex_trace);
mutex_unlock(&my_context->mutex_trace);
}
}
+123 -41
View File
@@ -73,16 +73,17 @@ void* my_mmap64(x86emu_t* emu, void *addr, unsigned long length, int prot, int f
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);
int my_vfork(x86emu_t* emu);
// cannot include <fcntl.h>, it conflict with some asm includes...
#ifndef O_NONBLOCK
#define O_NONBLOCK 04000
#endif
int my_fcntl(int fd, int cmd, ... /* arg */ );
int my_fcntl(x86emu_t* emu, 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 {
int x86s;
uint32_t x86s;
int nats;
int nbpars;
} scwrap_t;
@@ -387,6 +388,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
emu->quit = 1;
return;
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
return;
}
@@ -400,21 +403,31 @@ void EXPORT x86Syscall(x86emu_t *emu)
break;
case 3: // sys_read
R_EAX = (uint32_t)read((int)R_EBX, (void*)R_ECX, (size_t)R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 4: // sys_write
R_EAX = (uint32_t)write((int)R_EBX, (void*)R_ECX, (size_t)R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 5: // sys_open
if(s==5) {printf_log(LOG_DEBUG, " => sys_open(\"%s\", %d, %d)", (char*)R_EBX, of_convert(R_ECX), R_EDX);};
//R_EAX = (uint32_t)open((void*)R_EBX, of_convert(R_ECX), R_EDX);
R_EAX = (uint32_t)my_open(emu, (void*)R_EBX, of_convert(R_ECX), R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 6: // sys_close
R_EAX = (uint32_t)close((int)R_EBX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#ifndef __NR_waitpid
case 7: //sys_waitpid
R_EAX = waitpid((pid_t)R_EBX, (int*)R_ECX, (int)R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#endif
case 11: // sys_execve
@@ -425,29 +438,43 @@ void EXPORT x86Syscall(x86emu_t *emu)
printf_log(LOG_DEBUG, " => sys_execve(\"%s\", %p(\"%s\", \"%s\", \"%s\"...), %p)\n", prog, argv, (argv && argv[0])?argv[0]:"nil", (argv && argv[0] && argv[1])?argv[1]:"nil", (argv && argv[0] && argv[1] && argv[2])?argv[2]:"nil", envv);
R_EAX = my_execve(emu, (const char*)R_EBX, (void*)R_ECX, (void*)R_EDX);
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#ifndef __NR_time
case 13: // sys_time (it's deprecated and remove on ARM EABI it seems)
R_EAX = time(NULL);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#endif
case 45: // sys_brk
R_EAX = (uintptr_t)ElfSetBrk((void*)R_EBX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 54: // sys_ioctl
R_EAX = (uint32_t)ioctl((int)R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 55: // sys_fcntl
R_EAX = (uint32_t)my_fcntl((int)R_EBX, (int)R_ECX, R_EDX);
R_EAX = (uint32_t)my_fcntl(emu, (int)R_EBX, (int)R_ECX, R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#ifndef __NR_getrlimit
case 76: // sys_getrlimit... this is the old version, using the new one. Maybe some tranform is needed?
R_EAX = getrlimit(R_EBX, (void*)R_ECX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#endif
#ifndef __NR_select
case 82: // select
R_EAX = select(R_EBX, (fd_set*)R_ECX, (fd_set*)R_EDX, (fd_set*)R_ESI, (struct timeval*)R_EDI);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#endif
case 90: // old_mmap
@@ -455,9 +482,13 @@ void EXPORT x86Syscall(x86emu_t *emu)
struct mmap_arg_struct *st = (struct mmap_arg_struct*)R_EBX;
R_EAX = (uintptr_t)my_mmap(emu, (void*)st->addr, st->len, st->prot, st->flags, st->fd, st->offset);
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 91: // munmap
R_EAX = my_munmap(emu, (void*)R_EBX, (unsigned long)R_ECX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#ifndef __NR_socketcall
case 102: {
@@ -488,8 +519,10 @@ void EXPORT x86Syscall(x86emu_t *emu)
#endif
default:
printf_log(LOG_DEBUG, "BOX86 Error on Syscall 102: Unknown Soket command %d\n", R_EBX);
R_EAX = -1;
R_EAX = -EINVAL;
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
}
break;
#endif
@@ -506,6 +539,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
memcpy(old->version, un.version, 9);
strcpy(old->machine, "i686");
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
}
break;
#endif
@@ -517,6 +552,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
#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);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#endif
case 119: // sys_sigreturn
@@ -525,44 +562,53 @@ void EXPORT x86Syscall(x86emu_t *emu)
case 120: // clone
// x86 raw syscall is long clone(unsigned long flags, void *stack, int *parent_tid, unsigned long tls, int *child_tid);
// so flags=R_EBX, stack=R_ECX, parent_tid=R_EDX, tls=R_ESI, child_tid=R_EDI
if(R_ECX)
{
void* stack_base = (void*)R_ECX;
int stack_size = 0;
if(!R_ECX) {
// allocate a new stack...
int currstack = 0;
if((R_ESP>=(uintptr_t)emu->init_stack) && (R_ESP<=((uintptr_t)emu->init_stack+emu->size_stack)))
currstack = 1;
stack_size = (currstack)?emu->size_stack:(1024*1024);
stack_base = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
// copy value from old stack to new stack
if(currstack)
memcpy(stack_base, emu->init_stack, stack_size);
else {
int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_ESP);
memcpy(stack_base+stack_size-size_to_copy, (void*)R_ESP, size_to_copy);
if((R_EBX&~0xff)==0x4100) {
// this is a case of vfork...
R_EAX = my_vfork(emu);
if(R_EAX==0xffffffff)
R_EAX = (uint32_t)-errno;
} else {
if(R_ECX)
{
void* stack_base = (void*)R_ECX;
int stack_size = 0;
if(!R_ECX) {
// allocate a new stack...
int currstack = 0;
if((R_ESP>=(uintptr_t)emu->init_stack) && (R_ESP<=((uintptr_t)emu->init_stack+emu->size_stack)))
currstack = 1;
stack_size = (currstack)?emu->size_stack:(1024*1024);
stack_base = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
// copy value from old stack to new stack
if(currstack)
memcpy(stack_base, emu->init_stack, stack_size);
else {
int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_ESP);
memcpy(stack_base+stack_size-size_to_copy, (void*)R_ESP, size_to_copy);
}
}
x86emu_t * newemu = NewX86Emu(emu->context, R_EIP, (uintptr_t)stack_base, stack_size, (R_ECX)?0:1);
SetupX86Emu(newemu);
CloneEmu(newemu, emu);
Push32(newemu, 0);
PushExit(newemu);
void* mystack = NULL;
if(my_context->stack_clone_used) {
mystack = box_malloc(1024*1024); // stack for own process... memory leak, but no practical way to remove it
} else {
if(!my_context->stack_clone)
my_context->stack_clone = box_malloc(1024*1024);
mystack = my_context->stack_clone;
my_context->stack_clone_used = 1;
}
long ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), R_EBX, newemu, R_EDX, R_ESI, R_EDI);
R_EAX = (uint32_t)ret;
}
x86emu_t * newemu = NewX86Emu(emu->context, R_EIP, (uintptr_t)stack_base, stack_size, (R_ECX)?0:1);
SetupX86Emu(newemu);
CloneEmu(newemu, emu);
Push32(newemu, 0);
PushExit(newemu);
void* mystack = NULL;
if(my_context->stack_clone_used) {
mystack = box_malloc(1024*1024); // stack for own process... memory leak, but no practical way to remove it
} else {
if(!my_context->stack_clone)
my_context->stack_clone = box_malloc(1024*1024);
mystack = my_context->stack_clone;
my_context->stack_clone_used = 1;
}
long ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), R_EBX, newemu, R_EDX, R_ESI, R_EDI);
R_EAX = (uint32_t)ret;
else
R_EAX = (uint32_t)syscall(__NR_clone, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
}
else
R_EAX = (uint32_t)syscall(__NR_clone, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
break;
case 122: // uname
{
@@ -577,15 +623,23 @@ void EXPORT x86Syscall(x86emu_t *emu)
strcpy(old->machine, "i686");
}
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 123: // SYS_modify_ldt
R_EAX = my_modify_ldt(emu, R_EBX, (thread_area_t*)R_ECX, R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 125: // mprotect
R_EAX = my_mprotect(emu, (void*)R_EBX, (unsigned long)R_ECX, R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 168: // sys_poll
R_EAX = (uint32_t)poll((void*)R_EBX, R_ECX, (int)R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 173: // sys_rt_sigreturn
emu->quit = 1; // we should be inside a DynaCall in a sigaction callback....
@@ -593,12 +647,16 @@ void EXPORT x86Syscall(x86emu_t *emu)
case 174: // sys_rt_sigaction
//printf_log(LOG_NONE, "Warning, Ignoring sys_rt_sigaction(0x%02X, %p, %p)\n", R_EBX, (void*)R_ECX, (void*)R_EDX);
R_EAX = my_syscall_sigaction(emu, R_EBX, (void*)R_ECX, (void*)R_EDX, R_ESI);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 190: // vfork
{
int r = vfork();
int r = my_vfork(emu);
R_EAX = r;
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 192: // mmap2
R_EAX = (uint32_t)my_mmap64(emu, (void*)R_EBX, (unsigned long)R_ECX, R_EDX, R_ESI, R_EDI, R_EBP);
@@ -611,6 +669,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
R_EAX = r;
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 196: // lstat64
{
@@ -620,6 +680,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
R_EAX = r;
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 197: // fstat64
{
@@ -629,40 +691,60 @@ void EXPORT x86Syscall(x86emu_t *emu)
R_EAX = r;
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 221: // sys_fcntl64
R_EAX = (uint32_t)my_fcntl((int)R_EBX, (int)R_ECX, R_EDX);
R_EAX = (uint32_t)my_fcntl(emu, (int)R_EBX, (int)R_ECX, R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 243: // set_thread_area
R_EAX = my_set_thread_area((thread_area_t*)R_EBX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#ifndef NOALIGN
case 254: // epoll_create
R_EAX = my_epoll_create(emu, (int)R_EBX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 255: // epoll_ctl
R_EAX = my_epoll_ctl(emu, (int)R_EBX, (int)R_ECX, (int)R_EDX, (void*)R_ESI);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 256: // epoll_wait
R_EAX = my_epoll_wait(emu, (int)R_EBX, (void*)R_ECX, (int)R_EDX, (int)R_ESI);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#endif
case 270: // tgkill
R_EAX = syscall(__NR_tgkill, R_EBX, R_ECX, R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#ifndef NOALIGN
case 329: // epoll_create1
R_EAX = my_epoll_create1(emu, of_convert(R_EBX));
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#endif
#ifndef __NR_getrandom
case 355: // getrandom
R_EAX = my_getrandom(emu, (void*)R_EBX, R_ECX, R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#endif
#ifndef __NR_memfd_create
case 356: // memfd_create
R_EAX = my_memfd_create(emu, (void*)R_EBX, R_ECX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#endif
default:
+60 -26
View File
@@ -24,19 +24,37 @@ typedef struct thread_area_s
unsigned int useable:1;
} thread_area_t;
static pthread_once_t thread_key_once0 = PTHREAD_ONCE_INIT;
static pthread_once_t thread_key_once1 = PTHREAD_ONCE_INIT;
static pthread_once_t thread_key_once2 = PTHREAD_ONCE_INIT;
#define SUPER() \
GO(0) \
GO(1) \
GO(2) \
GO(3) \
GO(4) \
GO(5) \
GO(6) \
GO(7) \
GO(8) \
GO(9) \
GO(10) \
GO(11) \
GO(12) \
GO(13) \
GO(14) \
GO(15) \
GO(16) \
GO(17) \
GO(18) \
static void thread_key_alloc0() {
pthread_key_create(&my_context->segtls[0].key, NULL);
}
static void thread_key_alloc1() {
pthread_key_create(&my_context->segtls[1].key, NULL);
}
static void thread_key_alloc2() {
pthread_key_create(&my_context->segtls[2].key, NULL);
#define GO(A) static pthread_once_t thread_key_once##A = PTHREAD_ONCE_INIT;
SUPER()
#undef GO
#define GO(A)\
static void thread_key_alloc##A() { \
pthread_key_create(&my_context->segtls[A].key, NULL); \
}
SUPER()
#undef GO
uint32_t my_set_thread_area(thread_area_t* td)
{
@@ -81,11 +99,11 @@ uint32_t my_set_thread_area(thread_area_t* td)
my_context->segtls[idx-7].base = td->base_addr;
my_context->segtls[idx-7].limit = td->limit;
my_context->segtls[idx-7].present = 1;
#define GO(A) case A: pthread_once(&thread_key_once##A, thread_key_alloc##A); break;
switch (idx-7) {
case 0: pthread_once(&thread_key_once0, thread_key_alloc0); break;
case 1: pthread_once(&thread_key_once1, thread_key_alloc1); break;
case 2: pthread_once(&thread_key_once2, thread_key_alloc2); break;
SUPER()
}
#undef GO
pthread_setspecific(my_context->segtls[idx-7].key, (void*)my_context->segtls[idx-7].base);
@@ -96,32 +114,45 @@ uint32_t my_set_thread_area(thread_area_t* td)
EXPORT uint32_t my_modify_ldt(x86emu_t* emu, int op, thread_area_t* td, int size)
{
(void)emu;
printf_log(/*LOG_DEBUG*/LOG_INFO, "modify_ldt(0x%x, %p[0x%x/base=%p/limit=%u/32bits:%u/%u/%u...], %d)\n", op, td, td->entry_number, (void*)td->base_addr, td->limit_in_pages, td->seg_32bit, td->contents, td->read_exec_only, size);
if(!td) {
errno = EFAULT;
return (uint32_t)-1;
}
if(op==0 && size==8) {
td->entry_number = 6;
td->base_addr = (uintptr_t)GetSegmentBase(6<<3);
return 8;
}
if(op!=0x11) {
errno = ENOSYS;
return (uint32_t)-1;
}
if(!td->seg_32bit) {
if(!td->seg_32bit && td->base_addr) {
// not handling 16bits segments for now
errno = EINVAL;
return (uint32_t)-1;
}
int idx = td->entry_number - 7;
if(idx<0 || idx>2) {
if(td->entry_number>=0x1ff0) idx=td->entry_number-0x1ff0+3;
if(idx<0 || idx>16+3-1) {
printf_log(LOG_DEBUG, "modify_ldt: idx out of range: %d\n", idx);
errno = EINVAL;
return (uint32_t)-1;
}
/*
my_context->segtls[idx].base = td->base_addr;
my_context->segtls[idx].limit = td->limit;
my_context->segtls[idx].present = td->base_addr?1:0;
#define GO(A) case A: pthread_once(&thread_key_once##A, thread_key_alloc##A); break;
switch (idx-7) {
SUPER()
}
#undef GO
pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base);
*/
ResetSegmentsCache(thread_get_emu());
@@ -136,7 +167,7 @@ static int sizeDTS(box86context_t* context)
}
static int sizeTLSData(int s)
{
uint32_t mask = box86_nogtk?0xffff:0x1fff;
uint32_t mask = 0xffff/*box64_nogtk?0xffff:0x1fff*/; // x86 does the mapping per 64K blocks, so it makes sense to have it this large
return (s+mask)&~mask;
}
@@ -175,15 +206,15 @@ static tlsdatasize_t* setupTLSData(box86context_t* context)
void* fillTLSData(box86context_t *context)
{
pthread_mutex_lock(&context->mutex_tls);
mutex_lock(&context->mutex_tls);
tlsdatasize_t *data = setupTLSData(context);
pthread_mutex_unlock(&context->mutex_tls);
mutex_unlock(&context->mutex_tls);
return data;
}
void* resizeTLSData(box86context_t *context, void* oldptr)
{
pthread_mutex_lock(&context->mutex_tls);
mutex_lock(&context->mutex_tls);
tlsdatasize_t* oldata = (tlsdatasize_t*)oldptr;
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));
@@ -191,7 +222,7 @@ void* resizeTLSData(box86context_t *context, void* oldptr)
// 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);
mutex_unlock(&context->mutex_tls);
free_tlsdatasize(oldptr);
return data;
} else {
@@ -213,7 +244,7 @@ void* resizeTLSData(box86context_t *context, void* oldptr)
}
oldata->n_elfs = context->elfsize;
}
pthread_mutex_unlock(&context->mutex_tls);
mutex_unlock(&context->mutex_tls);
return oldata;
}
}
@@ -242,11 +273,14 @@ void* GetSegmentBase(uint32_t desc)
if(base==0x6)
return GetSeg33Base();
if(base>6 && base<10 && my_context->segtls[base-7].present) {
if(base>=0x1ff0)
base = base - 0x1ff0 + 3 + 7;
if(base>6 && base<16+3+7 && my_context->segtls[base-7].present) {
void* ptr = pthread_getspecific(my_context->segtls[base-7].key);
return ptr;
}
printf_log(LOG_NONE, "Warning, accessing segment unknown 0x%x or unset\n", desc);
printf_log(LOG_NONE, "Warning, accessing segment unknown 0x%x (%d) or unset\n", desc, base);
return NULL;
}
+32 -4
View File
@@ -73,6 +73,10 @@ void fpu_fbld(x86emu_t* emu, uint8_t* s) {
// long double (80bits) -> double (64bits)
void LD2D(void* ld, void* d)
{
if(box86_x87_no80bits) {
*(uint64_t*)d = *(uint64_t*)ld;
return;
}
FPU_t result;
#pragma pack(push, 1)
struct {
@@ -112,7 +116,7 @@ void LD2D(void* ld, void* d)
*(uint64_t*)d = result.q;
return;
}
if(((uint32_t)(val.b&0x7fff)==0) || (exp64<=0)) {
if(((uint32_t)(val.b&0x7fff)==0) || (exp64<-1074)) {
//if(val.f.ll==0)
// zero
//if(val.f.ll!=0)
@@ -124,6 +128,18 @@ void LD2D(void* ld, void* d)
return;
}
if(exp64<=0 && val.f.q) {
// try to see if it can be a denormal
int one = -exp64-1022;
uint64_t r = 0;
if(val.b&0x8000)
r |= 0x8000000000000000L;
r |= val.f.q>>one;
*(uint64_t*)d = r;
return;
}
if(exp64>=0x7ff) {
// to big value...
result.d = HUGE_VAL;
@@ -144,6 +160,10 @@ void LD2D(void* ld, void* d)
// double (64bits) -> long double (80bits)
void D2LD(void* d, void* ld)
{
if(box86_x87_no80bits) {
*(uint64_t*)ld = *(uint64_t*)d;
return;
}
#pragma pack(push, 1)
struct {
FPU_t f;
@@ -180,6 +200,12 @@ void D2LD(void* d, void* ld)
if(exp80!=0){
mant80final |= 0x8000000000000000LL;
exp80final += (BIAS80 - BIAS64);
} else if(mant80final!=0) {
// denormals -> normal
exp80final = BIAS80-1023;
int one = __builtin_clz(mant80final) + 1;
exp80final -= one;
mant80final<<=one;
}
}
val.b = ((int16_t)(sign80)<<15)| (int16_t)(exp80final);
@@ -191,7 +217,9 @@ void D2LD(void* d, void* ld)
double FromLD(void* ld)
{
double ret;
if(box86_x87_no80bits)
return *(double*)ld;
double ret; // cannot add = 0;
LD2D(ld, &ret);
return ret;
}
@@ -278,7 +306,7 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
p->StatusWord = 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;
tags |= (emu->p_regs[i].tag==0b11)?0:(1<<(i*2));
p->TagWord = tags;
p->ErrorOpcode = 0;
p->ErrorOffset = 0;
@@ -302,7 +330,7 @@ void fpu_fxrstor(x86emu_t* emu, void* ed)
emu->top = emu->sw.f.F87_TOP;
uint8_t tags = p->TagWord;
for(int i=0; i<8; ++i)
emu->p_regs[i].tag = (tags>>(i*2))?0:0b11;
emu->p_regs[i].tag = ((tags>>(i*2))&0b1)?0:0b11;
// copy back MMX regs...
int top = emu->top&7;
int stack = 8-top;
+35 -11
View File
@@ -4,6 +4,9 @@
#include <pthread.h>
#include "pathcoll.h"
#include "dictionnary.h"
#ifdef DYNAREC
#include "dynarec/arm_lock_helper.h"
#endif
typedef struct elfheader_s elfheader_t;
typedef struct cleanup_s cleanup_t;
@@ -40,7 +43,6 @@ 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 {
int tlssize;
@@ -91,7 +93,7 @@ typedef struct box86context_s {
char* bashpath; // path of x86 bash (defined with BOX86_BASH or by running bash directly)
uint32_t stacksz;
int stackalign;
uint32_t stackalign;
void* stack; // alocated stack
elfheader_t **elfs; // elf headers and memory
@@ -124,18 +126,24 @@ typedef struct box86context_s {
kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols)
vkprocaddess_t vkprocaddress;
#ifndef DYNAREC
pthread_mutex_t mutex_once;
pthread_mutex_t mutex_once2;
pthread_mutex_t mutex_trace;
#ifndef DYNAREC
pthread_mutex_t mutex_lock; // dynarec build will use their own mecanism
#else
pthread_mutex_t mutex_dyndump;
int trace_dynarec;
#endif
pthread_mutex_t mutex_tls;
pthread_mutex_t mutex_thread;
pthread_mutex_t mutex_bridge;
pthread_mutex_t mutex_lock;
#else
uint32_t mutex_once;
uint32_t mutex_once2;
uint32_t mutex_trace;
uint32_t mutex_tls;
uint32_t mutex_thread;
uint32_t mutex_bridge;
uint32_t mutex_dyndump;
int trace_dynarec;
#endif
library_t *libclib; // shortcut to libc library (if loaded, so probably yes)
library_t *sdl1mixerlib;
@@ -157,7 +165,7 @@ typedef struct box86context_s {
pthread_key_t tlskey; // then tls key to have actual tlsdata
void* tlsdata; // the initial global tlsdata
int32_t tlssize; // wanted size of tlsdata
base_segment_t segtls[3]; // only handling 0/1/2 descriptors
base_segment_t segtls[3+16]; // only handling 0/1/2 descriptors + some special cases
uintptr_t *auxval_start;
@@ -188,16 +196,32 @@ typedef struct box86context_s {
int stack_clone_used;
// rolling logs
char* log_call[CYCLE_LOG];
char* log_ret[CYCLE_LOG];
char* *log_call;
char* *log_ret;
int current_line;
} box86context_t;
#ifndef DYNAREC
#define mutex_lock(A) pthread_mutex_lock(A)
#define mutex_trylock(A) pthread_mutex_trylock(A)
#define mutex_unlock(A) pthread_mutex_unlock(A)
#else
int GetTID();
#define mutex_lock(A) {int tid = GetTID(); while(arm_lock_storeifnull(A, (void*)tid)) sched_yield();}
#define mutex_trylock(A) arm_lock_storeifnull(A, (void*)GetTID())
#define mutex_unlock(A) arm_lock_storeifref(A, NULL, (void*)GetTID())
#endif
extern box86context_t *my_context; // global context
box86context_t *NewBox86Context(int argc);
void FreeBox86Context(box86context_t** context);
// Cycle log handling
void freeCycleLog(box86context_t* ctx);
void initCycleLog(box86context_t* context);
void print_cycle_log(int loglevel);
// return the index of the added header
int AddElfHeader(box86context_t* ctx, elfheader_t* head);
+1
View File
@@ -12,6 +12,7 @@ void FreeBridge(bridge_t** bridge);
uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name);
uintptr_t CheckBridged(bridge_t* bridge, void* fnc);
int IsBridge(void* func);
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name);
uintptr_t AddAutomaticBridge(x86emu_t* emu, bridge_t* bridge, wrapper_t w, void* fnc, int N);
void* GetNativeFnc(uintptr_t fnc);
+1
View File
@@ -11,4 +11,5 @@ uint64_t RunFunction64(box86context_t *context, uintptr_t fnc, int nargs, ...);
// use emu state to run function
uint32_t RunFunctionWithEmu(x86emu_t *emu, int QuitOnLongJump, uintptr_t fnc, int nargs, ...);
uint32_t RunSafeFunction(box86context_t *context, uintptr_t fnc, int nargs, ...);
#endif //__CALLBACK_H__
+4
View File
@@ -47,6 +47,10 @@ void loadProtectionFromMap();
#ifdef DYNAREC
void protectDB(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 isprotectedDB(uintptr_t addr, size_t size);
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);
+14 -2
View File
@@ -7,20 +7,24 @@ extern int box86_log; // log level
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_pagesize;
extern uintptr_t box86_load_addr;
extern int box86_backtrace;
extern int box86_showbt;
#ifdef DYNAREC
extern int box86_dynarec_dump;
extern int box86_dynarec_trace;
extern int box86_dynarec_forced;
extern int box86_dynarec_largest;
extern int box86_dynarec_bigblock;
extern int box86_dynarec_forward;
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;
extern int box86_dynarec_fastround;
extern int box86_dynarec_hotpage;
extern int box86_dynarec_bleeding_edge;
#ifdef ARM
extern int arm_vfp; // vfp version (3 or 4), with 32 registers is mendatory
extern int arm_swap;
@@ -31,6 +35,8 @@ 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 box86_sse_flushto0;
extern int box86_x87_no80bits;
extern int allow_missing_libs;
extern int box86_prefer_wrapped;
extern int box86_prefer_emulated;
@@ -44,10 +50,16 @@ extern int box86_showsegv;
extern int allow_missing_symbols;
extern uintptr_t trace_start, trace_end;
extern char* trace_func;
extern char* trace_init;
extern char* box86_trace;
extern uint64_t start_cnt;
extern uintptr_t fmod_smc_start, fmod_smc_end; // to handle libfmod (from Unreal) SMC (self modifying code)
extern uint32_t default_fs;
extern int jit_gdb; // launch gdb when a segfault is trapped
extern int box86_tcmalloc_minimal; // when using tcmalloc_minimal
extern int box86_x11threads;
extern int box86_x11glx;
extern char* box86_libGL;
#define LOG_NONE 0
#define LOG_INFO 1
#define LOG_DEBUG 2
+1 -1
View File
@@ -26,7 +26,7 @@ int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head);
int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head);
int RelocateElf(lib_t* maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
int RelocateElfPlt(lib_t* maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
void CalcStack(elfheader_t* h, uint32_t* stacksz, int* stackalign);
void CalcStack(elfheader_t* h, uint32_t* stacksz, uint32_t* stackalign);
uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h);
uintptr_t GetLastByte(elfheader_t* h);
void AddSymbols(lib_t* maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h);
+5 -2
View File
@@ -21,8 +21,11 @@ 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)
// will lower case the string and return a copy. Nothing fancy here, just A..Z transformed to a..z, rest is untouched
char* LowerCase(const char* s);
#if defined(RPI) || defined(RK3399) || defined(GOA_CLONE) || defined(PYRA)
void sanitize_mojosetup_gtk_background();
#endif
#endif //__FILEUTILS_H_
#endif //__FILEUTILS_H_
+1 -1
View File
@@ -26,7 +26,7 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, in
library_t* GetLibMapLib(lib_t* maplib, const char* name);
library_t* GetLibInternal(const char* name);
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername);
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername);
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername);
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername);
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
+3 -3
View File
@@ -24,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 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);
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int *weak, int version, const char* vername, int local);
int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local);
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local);
void fillGLProcWrapper(box86context_t* context);
void freeGLProcWrapper(box86context_t* context);
void fillALProcWrapper(box86context_t* context);
+10
View File
@@ -0,0 +1,10 @@
#ifndef __RCFILE_H__
#define __RCFILE_H__
typedef struct path_collection_s path_collection_t;
void LoadRCFile(const char* filename);
void DeleteParams();
void ApplyParams(const char* name, path_collection_t* preload);
#endif //__RCFILE_H__
+47 -25
View File
@@ -178,41 +178,63 @@ typedef enum {
typedef union {
struct __attribute__ ((__packed__)) {
unsigned int F87_IE:1;
unsigned int F87_DE:1;
unsigned int F87_ZE:1;
unsigned int F87_OE:1;
unsigned int F87_UE:1;
unsigned int F87_PE:1;
unsigned int F87_SF:1;
unsigned int F87_ES:1;
unsigned int F87_C0:1;
unsigned int F87_C1:1;
unsigned int F87_C2:1;
unsigned int F87_TOP:3;
unsigned int F87_C3:1;
unsigned int F87_B:1;
uint16_t F87_IE:1;
uint16_t F87_DE:1;
uint16_t F87_ZE:1;
uint16_t F87_OE:1;
uint16_t F87_UE:1;
uint16_t F87_PE:1;
uint16_t F87_SF:1;
uint16_t F87_ES:1;
uint16_t F87_C0:1;
uint16_t F87_C1:1;
uint16_t F87_C2:1;
uint16_t F87_TOP:3;
uint16_t F87_C3:1;
uint16_t F87_B:1;
} f;
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
uint16_t C87_IM:1; // interupt masks
uint16_t C87_DM:1;
uint16_t C87_ZM:1;
uint16_t C87_OM:1;
uint16_t C87_UM:1;
uint16_t C87_PM:1;
uint16_t C87_R1:2; // reserved
uint16_t C87_PC:2; // precision control (24bits, reserved, 53bits, 64bits)
uint16_t C87_RD:2; // Rounds
uint16_t C87_IC:1;
uint16_t C87_R2:3; // reserved
} f;
uint16_t x16;
} x87control_t;
typedef union {
struct __attribute__ ((__packed__)) {
uint32_t MXCSR_IE:1;
uint32_t MXCSR_DE:1;
uint32_t MXCSR_ZE:1;
uint32_t MXCSR_OE:1;
uint32_t MXCSR_UE:1;
uint32_t MXCSR_PE:1;
uint32_t MXCSR_DAZ:1;
uint32_t MXCSR_IM:1;
uint32_t MXCSR_DM:1;
uint32_t MXCSR_ZM:1;
uint32_t MXCSR_OM:1;
uint32_t MXCSR_UM:1;
uint32_t MXCSR_PM:1;
uint32_t MXCSR_RC:2;
uint32_t MXCSR_FZ:1;
uint32_t MXCSR_RES:16;
} f;
uint32_t x32;
} mmxcontrol_t;
typedef union {
uint64_t q;
int64_t sq;
+1
View File
@@ -18,6 +18,7 @@ uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, con
// don't add if already there
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);
int GetSizedSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, size_t size, 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
+2
View File
@@ -20,7 +20,9 @@ void fini_pthread_helper(box86context_t* context);
// prepare an "emuthread structure" in pet and return address of function pointer for a "thread creation routine"
void* my_prepare_thread(x86emu_t *emu, void* f, void* arg, int ssize, void** pet);
#ifndef DYNAREC
//check and unlock if a mutex is locked by current thread (works only for PTHREAD_MUTEX_ERRORCHECK typed mutex)
int checkUnlockMutex(void* m);
#endif
#endif //_THREADS_H_
+1 -1
View File
@@ -7,7 +7,7 @@ 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* weak, int version, const char* vername, int local);
typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, size_t size, 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)
+25 -16
View File
@@ -20,6 +20,7 @@ KHASH_MAP_IMPL_INT(mapoffsets, cstr_t);
lib_t *NewLibrarian(box86context_t* context, int ownlibs)
{
(void)context;
lib_t *maplib = (lib_t*)box_calloc(1, sizeof(lib_t));
maplib->mapoffsets = kh_init(mapoffsets);
@@ -110,6 +111,7 @@ void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
box86context_t* GetLibrarianContext(lib_t* maplib)
{
(void)maplib;
return my_context;
}
@@ -294,6 +296,7 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, library_t* lib, box86context_t* box86, x86emu_t* emu)
{
(void)neededlibs; (void)deplib;
if(!maplib)
maplib = (local)?lib->maplib:my_context->maplib;
@@ -385,7 +388,7 @@ static int isLocal(elfheader_t* self, library_t* l)
return 0;
}
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername)
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername)
{
assert(self); // need self for this one
//search for the self, to start "next"
@@ -399,13 +402,13 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
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(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &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);
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0);
// loop done, weak symbol found
if(weak && *start)
return 1;
@@ -413,23 +416,23 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
if(self) {
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(GetSizedSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, defver))
if(*start)
return 1;
defver = GetDefaultVersion(my_context->weakdefver, name);
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, defver))
if(GetSizedSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, defver))
if(*start)
weak = 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(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &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);
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1);
}
if(weak && *start)
return 1;
@@ -440,6 +443,7 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
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;
size_t size = 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)
@@ -449,12 +453,12 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin
// 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(GetLibGlobalSymbolStartEnd(my_context->neededlibs.libs[i], name, start, end, &weak, version, vername, isLocal(self, my_context->neededlibs.libs[i])))
if(GetLibGlobalSymbolStartEnd(my_context->neededlibs.libs[i], name, start, end, size, &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(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, &weak, version, vername, isLocal(self, maplib->libraries[i])))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i])))
if(*start)
return 1;
}
@@ -468,7 +472,7 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin
ok = 1;
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, &weak, version, vername, isLocal(self, maplib->libraries[i])))
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i])))
if(*start)
ok = 1;
}
@@ -514,6 +518,7 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
{
uintptr_t start = 0;
uintptr_t end = 0;
size_t size = 0;
int weak = 0;
elfheader_t* ret = NULL;
// check with default version...
@@ -522,7 +527,7 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
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(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, &weak, version, vername, 1)) {
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &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]));
@@ -539,7 +544,7 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
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)) {
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &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]));
@@ -558,6 +563,7 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername)
{
int weak = 0;
size_t size = 0;
// check with default version...
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
@@ -565,7 +571,7 @@ int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* st
if(*start || *end)
return 1;
for(int i=0; i<maplib->libsz; ++i)
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, &weak, version, vername, 1))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1))
if(*start || *end)
return 1;
// nope, not found
@@ -575,11 +581,12 @@ 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;
size_t size = 0;
int weak;
// check with default version...
for(int i=0; i<maplib->libsz; ++i)
if(GetElfIndex(maplib->libraries[i])==-1)
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, &weak, version, vername, 1))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1))
if(start || end)
return 1;
// nope, not found
@@ -591,6 +598,7 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui
{
// check with default version...
int weak;
size_t size = 0;
if(my_context->elfs[0]==self || !self) {
if(GetSymbolStartEnd(GetLocalSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, NULL))
@@ -601,8 +609,8 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui
}
for(int i=0; i<maplib->libsz; ++i) {
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)
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1))
if(*start || *end)
return 1;
if(self)
return 0;
@@ -615,6 +623,7 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, const char** libname, void** base, library_t** lib)
{
(void)maplib;
// first, search in self...
const char* ret = NULL;
uintptr_t offs = 0;
+54 -48
View File
@@ -101,6 +101,7 @@ void WrappedLib_CommonInit(library_t* lib)
void EmuLib_Fini(library_t* lib)
{
(void)lib;
}
void WrappedLib_FinishFini(library_t* lib)
{
@@ -117,12 +118,13 @@ void WrappedLib_FinishFini(library_t* lib)
FreeBridge(&lib->w.bridge);
}
int WrappedLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, int *weak, int version, const char* vername, int local)
int WrappedLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, size_t asked_size, int *weak, int version, const char* vername, int local)
{
// ignoring asked size on wrapped libs
(void)asked_size;
uintptr_t addr = 0;
uint32_t size = 0;
int wk = 0;
void* symbol = NULL;
if (!getSymbolInMaps(lib, name, 0, &addr, &size, &wk, version, vername, local)) {
return 0;
}
@@ -135,12 +137,12 @@ int WrappedLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uint32
*weak = wk;
return 1;
}
int EmuLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, int* weak, int version, const char* vername, int local)
int EmuLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local)
{
uintptr_t start, end;
const char* defver = GetDefaultVersion(my_context->weakdefver, name);
// weak symbols...
if(GetSymbolStartEnd(GetWeakSymbols(lib->e.elf), name, &start, &end, version, vername, local, defver))
if(GetSizedSymbolStartEnd(GetWeakSymbols(lib->e.elf), name, &start, &end, asked_size, version, vername, local, defver))
{
*offs = start;
*sz = end-start;
@@ -149,12 +151,13 @@ int EmuLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uint32_t *
}
return 0;
}
int WrappedLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, int* weak, int version, const char* vername, int local)
int WrappedLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local)
{
// ignoring asked size on wrapped libs
(void)asked_size;
uintptr_t addr = 0;
uint32_t size = 0;
int wk = 0;
void* symbol = NULL;
if (!getSymbolInMaps(lib, name, 1, &addr, &size, &wk, version, vername, local)) {
return 0;
}
@@ -167,11 +170,11 @@ int WrappedLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uint
*weak = 0;
return 1;
}
int EmuLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, int *weak, int version, const char* vername, int local)
int EmuLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, size_t asked_size, int *weak, int version, const char* vername, int local)
{
uintptr_t start, end;
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
if(GetSymbolStartEnd(GetMapSymbols(lib->e.elf), name, &start, &end, version, vername, local, defver))
if(GetSizedSymbolStartEnd(GetMapSymbols(lib->e.elf), name, &start, &end, asked_size, version, vername, local, defver))
{
*offs = start;
*sz = end-start;
@@ -180,12 +183,12 @@ int EmuLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uint32_t
}
return 0;
}
int EmuLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, int *weak, int version, const char* vername, int local)
int EmuLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, size_t asked_size, int *weak, int version, const char* vername, int local)
{
uintptr_t start, end;
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
if(!defver) defver = GetDefaultVersion(my_context->weakdefver, name);
if(GetSymbolStartEnd(GetLocalSymbols(lib->e.elf), name, &start, &end, version, vername, local, defver))
if(GetSizedSymbolStartEnd(GetLocalSymbols(lib->e.elf), name, &start, &end, asked_size, version, vername, local, defver))
{
*offs = start;
*sz = end-start;
@@ -195,8 +198,9 @@ int EmuLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uint32_t
return 0;
}
int WrappedLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, int* weak, int version, const char* vername, int local)
int WrappedLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local)
{
(void)lib; (void)name; (void)offs; (void)sz; (void)asked_size; (void)weak; (void)version; (void)vername; (void)local;
return 0;
}
@@ -304,12 +308,23 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box86context_t*
printf_log(LOG_INFO, "Using emulated %s\n", libname);
#ifdef DYNAREC
if(libname && strstr(libname, "libmonobdwgc-2.0.so")) {
if(libname && box86_dynarec_bleeding_edge && strstr(libname, "libmonobdwgc-2.0.so")) {
printf_log(LOG_INFO, "MonoBleedingEdge detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n");
box86_dynarec_bigblock = 0;
box86_dynarec_strongmem = 1;
}
#endif
// spacial case for spd_readdir, to allow override a few symbols
if(libname && strstr(libname, "spd_readdir.so")) {
printf_log(LOG_INFO, "spd_readdir detected, hacking wrapped libc\n");
const char* symbols[] = {"opendir", "readdir", "readdir_r", "readdir64", "closedir", "telldir", "seekdir", "dirfd"};
for(unsigned int i=0; i<sizeof(symbols)/sizeof(symbols[0]); ++i) {
const char* symname = AddDictionnary(my_context->versym, symbols[i]);
const char* vername = AddDictionnary(my_context->versym, "GLIBC_2.0");
AddDefaultVersion(my_context->globaldefver, symname, vername);
}
}
return 1;
}
return 0;
@@ -346,13 +361,12 @@ static const char* essential_libs[] = {
"ld-linux-x86-64.so.2", "crashhandler.so", "libtcmalloc_minimal.so.0", "libtcmalloc_minimal.so.4"
};
static int isEssentialLib(const char* name) {
for (int i=0; i<sizeof(essential_libs)/sizeof(essential_libs[0]); ++i)
for (unsigned int i=0; i<sizeof(essential_libs)/sizeof(essential_libs[0]); ++i)
if(!strcmp(name, essential_libs[i]))
return 1;
return 0;
}
extern char* libGL;
library_t *NewLibrary(const char* path, box86context_t* context)
{
printf_log(LOG_DEBUG, "Trying to load \"%s\"\n", path);
@@ -360,7 +374,7 @@ library_t *NewLibrary(const char* path, box86context_t* context)
lib->path = box_realpath(path, NULL);
if(!lib->path)
lib->path = box_strdup(path);
if(libGL && !strcmp(path, libGL))
if(box86_libGL && !strcmp(path, box86_libGL))
lib->name = box_strdup("libGL.so.1");
else
lib->name = Path2Name(path);
@@ -420,6 +434,7 @@ library_t *NewLibrary(const char* path, box86context_t* context)
}
int AddSymbolsLibrary(lib_t *maplib, library_t* lib, x86emu_t* emu)
{
(void)emu;
lib->active = 1;
if(lib->type==LIB_EMULATED) {
elfheader_t *elf_header = lib->e.elf;
@@ -451,7 +466,7 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x86emu_t*
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
box_free(trace_func);
trace_func = NULL;
} else if(GetLibLocalSymbolStartEnd(lib, trace_func, &trace_start, &trace_end, &weak, -1, NULL, 0)) {
} else if(GetLibLocalSymbolStartEnd(lib, trace_func, &trace_start, &trace_end, 0, &weak, -1, NULL, 0)) {
SetTraceEmu(trace_start, trace_end);
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
box_free(trace_func);
@@ -621,34 +636,24 @@ int IsSameLib(library_t* lib, const char* path)
box_free(name);
return ret;
}
int GetLibWeakSymbolStartEnd(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, size_t size, int* weak, int version, const char* vername, int local)
{
if(!name[0] || !lib || !lib->active)
return 0;
khint_t k;
// check first if already in the map
k = kh_get(bridgemap, lib->wbridgemap, VersionnedName(name, version, vername));
if(k!=kh_end(lib->wbridgemap)) {
*start = kh_value(lib->wbridgemap, k).start;
*end = kh_value(lib->wbridgemap, k).end;
*weak = 1;
return 1;
}
if(local) {
k = kh_get(bridgemap, lib->lbridgemap, VersionnedName(name, version, vername));
if(k!=kh_end(lib->lbridgemap)) {
*start = kh_value(lib->lbridgemap, k).start;
*end = kh_value(lib->lbridgemap, k).end;
*weak = 0;
// get a new symbol
if(lib->getweak(lib, name, start, end, size, weak, version, vername, local)) {
*end += *start; // lib->get(...) gives size, not end
kh_bridgemap_t *map = local?lib->lbridgemap:((*weak)?lib->wbridgemap:lib->gbridgemap);
// check first if already in the map
k = kh_get(bridgemap, map, VersionnedName(name, version, vername));
if(k!=kh_end(map)) {
*start = kh_value(map, k).start;
*end = kh_value(map, k).end;
return 1;
}
}
// get a new symbol
if(lib->getweak(lib, name, start, end, weak, version, vername, local)) {
*end += *start; // lib->get(...) gives size, not end
char* symbol = box_strdup(VersionnedName(name, version, vername));
int ret;
kh_bridgemap_t *map = local?lib->lbridgemap:((*weak)?lib->wbridgemap:lib->gbridgemap);
k = kh_put(bridgemap, map, symbol, &ret);
kh_value(map, k).name = symbol;
kh_value(map, k).start = *start;
@@ -658,13 +663,13 @@ int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start,
// nope
return 0;
}
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int *weak, int version, const char* vername, int local)
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int *weak, int version, const char* vername, int local)
{
if(!name[0] || !lib || !lib->active)
return 0;
khint_t k;
// get a new symbol
if(lib->getglobal(lib, name, start, end, weak, version, vername, local)) {
if(lib->getglobal(lib, name, start, end, size, weak, version, vername, local)) {
*end += *start; // lib->get(...) gives size, not end
kh_bridgemap_t *map = local?lib->lbridgemap:((*weak)?lib->wbridgemap:lib->gbridgemap);
// check if already in the map
@@ -685,21 +690,21 @@ int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* star
// nope
return 0;
}
int GetLibLocalSymbolStartEnd(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, size_t size, int* weak, int version, const char* vername, int local)
{
if(!name[0] || !lib || !lib->active)
return 0;
khint_t k;
// check first if already in the map
k = kh_get(bridgemap, lib->lbridgemap, VersionnedName(name, version, vername));
if(k!=kh_end(lib->lbridgemap)) {
*start = kh_value(lib->lbridgemap, k).start;
*end = kh_value(lib->lbridgemap, k).end;
return 1;
}
// get a new symbol
if(lib->getlocal(lib, name, start, weak, end, version, vername, local)) {
if(lib->getlocal(lib, name, start, end, size, weak, version, vername, local)) {
*end += *start; // lib->get(...) gives size, not end
// check first if already in the map
k = kh_get(bridgemap, lib->lbridgemap, VersionnedName(name, version, vername));
if(k!=kh_end(lib->lbridgemap)) {
*start = kh_value(lib->lbridgemap, k).start;
*end = kh_value(lib->lbridgemap, k).end;
return 1;
}
char* symbol = box_strdup(VersionnedName(name, version, vername));
int ret;
k = kh_put(bridgemap, lib->lbridgemap, symbol, &ret);
@@ -934,6 +939,7 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui
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)
{
(void)local;
if(!lib->active)
return 0;
if(version==-2) // don't send global native symbol for a version==-2 search
@@ -1097,4 +1103,4 @@ void setNeededLibs(library_t* lib, int n, ...)
lib->w.neededlibs[i] = box_strdup(va_arg(va, char*));
}
va_end (va);
}
}
+48 -31
View File
@@ -58,89 +58,89 @@ static int SameVersion(versymbol_t* s, int ver, const char* vername)
}
static versymbol_t* FindVersionLocal(versymbols_t* s)
static versymbol_t* FindVersionLocal(versymbols_t* s, size_t size)
{
if(!s || !s->sz)
return NULL;
for (int i=0; i<s->sz; ++i)
if(s->syms[i].version==0)
if(s->syms[i].version==0 && (!size || (size==s->syms[i].sym.sz)))
return &s->syms[i];
return NULL;
}
static versymbol_t* FindNoVersion(versymbols_t* s)
static versymbol_t* FindNoVersion(versymbols_t* s, size_t size)
{
if(!s || !s->sz)
return NULL;
for (int i=0; i<s->sz; ++i)
if(s->syms[i].version==-1)
if(s->syms[i].version==-1 && (!size || (size==s->syms[i].sym.sz)))
return &s->syms[i];
return NULL;
}
static versymbol_t* FindVersionGlobal(versymbols_t* s)
static versymbol_t* FindVersionGlobal(versymbols_t* s, size_t size)
{
if(!s || !s->sz)
return NULL;
for (int i=0; i<s->sz; ++i)
if(s->syms[i].version==1)
if(s->syms[i].version==1 && (!size || (size==s->syms[i].sym.sz)))
return &s->syms[i];
return NULL;
}
static versymbol_t* FindVersion(versymbols_t* s, const char* vername)
static versymbol_t* FindVersion(versymbols_t* s, size_t size, const char* vername)
{
if(!s || !s->sz)
return NULL;
for (int i=0; i<s->sz; ++i)
if(s->syms[i].vername && !strcmp(s->syms[i].vername, vername))
if(s->syms[i].vername && !strcmp(s->syms[i].vername, vername) && (!size || (size==s->syms[i].sym.sz)))
return &s->syms[i];
return NULL;
}
static versymbol_t* FindFirstVersion(versymbols_t* s)
/* static versymbol_t* FindFirstVersion(versymbols_t* s, size_t size)
{
if(!s || !s->sz)
return NULL;
for (int i=0; i<s->sz; ++i)
if(s->syms[i].version>1)
if(s->syms[i].version>1 && (!size || (size==s->syms[i].sym.sz)))
return &s->syms[i];
return NULL;
}
} */
// 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, const char* defver)
static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername, size_t size, int local, const char* defver)
{
if(!s || !s->sz)
return NULL;
versymbol_t* ret = NULL;
if(ver==0) {
if(local) ret = FindVersionLocal(s);
if(!ret) ret = FindNoVersion(s);
if(!ret) ret = FindVersionGlobal(s);
if(!ret && defver) ret = FindVersion(s, defver);
if(local) ret = FindVersionLocal(s, size);
if(!ret) ret = FindNoVersion(s, size);
if(!ret) ret = FindVersionGlobal(s, size);
if(!ret && defver) ret = FindVersion(s, size, defver);
return ret;
}
if(ver==-1) {
if(local) ret = FindVersionLocal(s);
if(!ret) ret = FindNoVersion(s);
if(!ret) ret = FindVersionGlobal(s);
if(!ret && defver) ret = FindVersion(s, defver);
if(local) ret = FindVersionLocal(s, size);
if(!ret) ret = FindNoVersion(s, size);
if(!ret) ret = FindVersionGlobal(s, size);
if(!ret && defver) ret = FindVersion(s, size, defver);
//if(!ret) ret = FindFirstVersion(s);
return ret;
}
if(ver==-2) {
if(local) ret = FindVersionLocal(s);
if(!ret) ret = FindVersionGlobal(s);
if(local) ret = FindVersionLocal(s, size);
if(!ret) ret = FindVersionGlobal(s, size);
return ret;
}
if(ver==1) {
if(local) ret = FindVersionLocal(s);
if(!ret) ret = FindVersionGlobal(s);
if(!ret) ret = FindNoVersion(s);
if(!ret && defver) ret = FindVersion(s, defver);
if(local) ret = FindVersionLocal(s, size);
if(!ret) ret = FindVersionGlobal(s, size);
if(!ret) ret = FindNoVersion(s, size);
if(!ret && defver) ret = FindVersion(s, size, defver);
//if(!ret) ret = FindFirstVersion(s);
return ret;
}
ret = FindVersion(s, vername);
if(local && !ret) ret = FindVersionLocal(s);
if(!ret && defver && vername && !strcmp(defver, vername)) ret = FindVersionGlobal(s);
ret = FindVersion(s, size, vername);
if(local && !ret) ret = FindVersionLocal(s, size);
if(!ret && defver && vername && !strcmp(defver, vername)) ret = FindVersionGlobal(s, size);
//if(!ret) return FindVersionGlobal(s);
return ret;
}
@@ -178,7 +178,7 @@ 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, defver);
versymbol_t * s = MatchVersion(v, ver, vername, 0, local, defver);
if(s)
return s->sym.offs;
return 0;
@@ -215,7 +215,24 @@ 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, defver);
versymbol_t* s = MatchVersion(v, ver, vername, 0, local, defver);
if(s) {
*start = s->sym.offs;
*end = *start + s->sym.sz;
return 1;
}
return 0;
}
int GetSizedSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int ver, const char* vername, int local, const char* defver)
{
if(!mapsymbols)
return 0;
khint_t k = kh_get(mapsymbols, mapsymbols, name);
if(k==kh_end(mapsymbols))
return 0;
versymbols_t * v = &kh_val(mapsymbols, k);
versymbol_t* s = MatchVersion(v, ver, vername, size, local, defver);
if(s) {
*start = s->sym.offs;
*end = *start + s->sym.sz;
+5
View File
@@ -39,6 +39,7 @@ GO("libXext.so.6", libxext)
GO("libXfixes.so.3", libxfixes)
GO("libXcursor.so.1", libxcursor)
GO("libXrender.so.1", libxrender)
GO("libXpresent.so.1", libxpresent)
GO("libXft.so.2", libxft)
GO("libXi.so.6", libxi)
GO("libXss.so.1", libxss)
@@ -112,10 +113,14 @@ GO("libpangoft2-1.0.so", pangoft2)
GO("libpangoft2-1.0.so.0", pangoft2)
GO("libpangocairo-1.0.so.0", pangocairo)
GO("libcairo.so.2", cairo)
GO("libcairo.so", cairo)
GO("libcairo-gobject.so.2", cairogobject)
GO("libpango-1.0.so.0", pango)
GO("libpango-1.0.so", pango)
GO("libnm.so.0", libnm)
GO("libnm-glib.so.4", libnm)
GO("libnm-util.so.2", libnm)
GO("libibus-1.0.so.5", libibus)
GO("libfontconfig.so.1", fontconfig)
GO("libbz2.so.1", bz2)
GO("libexpat.so.1", expat)
+2 -1
View File
@@ -23,6 +23,7 @@
static uintptr_t* auxval_start = NULL;
int init_auxval(int argc, const char **argv, char **env) {
(void)argc; (void)argv;
// auxval vector is after envs...
while(*env)
env++;
@@ -56,4 +57,4 @@ EXPORT unsigned long my_getauxval(x86emu_t* emu, unsigned long type)
p+=2;
}
return 0;
}
}
+20 -12
View File
@@ -35,10 +35,12 @@ void myStackAlign(const char* fmt, uint32_t* st, uint32_t* mystack)
case 2: // l
case 3: // ll
case 4: // L
case 5: // z
switch(*p) {
case '%': state = 0; ++p; break; //%% = back to 0
case 'l': ++state; if (state>3) state=3; ++p; break;
case 'L': state = 4; ++p; break;
case 'z': state = 5; ++p; break;
case 'a':
case 'A':
case 'e':
@@ -66,6 +68,7 @@ void myStackAlign(const char* fmt, uint32_t* st, uint32_t* mystack)
case '8':
case '9':
case '.':
case '#':
case '+':
case '-': ++p; break; // formating, ignored
case 'm': state = 0; ++p; break; // no argument
@@ -83,6 +86,7 @@ void myStackAlign(const char* fmt, uint32_t* st, uint32_t* mystack)
case 11: //double
case 12: //%lg, still double
case 13: //%llg, still double
case 15: //%zg, meh... double?
case 23: // 64bits int
if((((uint32_t)mystack)&0x7)!=0)
mystack++;
@@ -93,6 +97,7 @@ void myStackAlign(const char* fmt, uint32_t* st, uint32_t* mystack)
break;
case 14: //%LG long double
#ifdef HAVE_LD80BITS
(void)d;
if((((uint32_t)mystack)&0x7)!=0)
mystack++;
memcpy(mystack, st, 10);
@@ -112,6 +117,7 @@ void myStackAlign(const char* fmt, uint32_t* st, uint32_t* mystack)
case 21:
case 22:
case 24: // normal int / pointer
case 25: // size_t int
case 30:
*mystack = *st;
++mystack;
@@ -293,9 +299,11 @@ void myStackAlignGVariantNew(const char* fmt, uint32_t* st, uint32_t* mystack)
++st;
state = 0;
} else state = 0; //???
break;
case 8: // ^&
if (*p == 'a') state = 9;
else state = 0; //???
break;
case 9: // ^&a
if (*p == 'y') {
*mystack = *st;
@@ -303,6 +311,7 @@ void myStackAlignGVariantNew(const char* fmt, uint32_t* st, uint32_t* mystack)
++st;
state = 0;
} else state = 0; //???
break;
}
++p;
} while (*p && (inblocks || state));
@@ -328,10 +337,12 @@ void myStackAlignW(const char* fmt, uint32_t* st, uint32_t* mystack)
case 2: // l
case 3: // ll
case 4: // L
case 5: // z
switch(*p) {
case '%': state = 0; ++p; break; //%% = back to 0
case 'l': ++state; if (state>3) state=3; ++p; break;
case 'L': state = 4; ++p; break;
case 'z': state = 5; ++p; break;
case 'a':
case 'A':
case 'e':
@@ -359,6 +370,7 @@ void myStackAlignW(const char* fmt, uint32_t* st, uint32_t* mystack)
case '8':
case '9':
case '.':
case '#':
case '+':
case '-': ++p; break; // formating, ignored
case 'm': state = 0; ++p; break; // no argument
@@ -376,6 +388,7 @@ void myStackAlignW(const char* fmt, uint32_t* st, uint32_t* mystack)
case 11: //double
case 12: //%lg, still double
case 13: //%llg, still double
case 15: //%zg, meh.. double?
case 23: // 64bits int
if((((uint32_t)mystack)&0x7)!=0)
mystack++;
@@ -386,6 +399,7 @@ void myStackAlignW(const char* fmt, uint32_t* st, uint32_t* mystack)
break;
case 14: //%LG long double
#ifdef HAVE_LD80BITS
(void)d;
if((((uint32_t)mystack)&0x7)!=0)
mystack++;
memcpy(mystack, st, 10);
@@ -405,6 +419,7 @@ void myStackAlignW(const char* fmt, uint32_t* st, uint32_t* mystack)
case 21:
case 22:
case 24: // normal int / pointer
case 25: // size_t int
case 30:
*mystack = *st;
++mystack;
@@ -754,16 +769,9 @@ void AlignVorbisBlock(void* dest, void* source)
#undef TRANSFERT
typedef union __attribute__((packed)) x86_epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} x86_epoll_data_t;
struct __attribute__((packed)) x86_epoll_event {
uint32_t events;
x86_epoll_data_t data;
uint32_t events;
uint64_t data;
};
// Arm -> x86
void UnalignEpollEvent(void* dest, void* source, int nbr)
@@ -772,7 +780,7 @@ void UnalignEpollEvent(void* dest, void* source, int nbr)
struct epoll_event *arm_struct = (struct epoll_event*)source;
while(nbr) {
x86_struct->events = arm_struct->events;
x86_struct->data.u64 = arm_struct->data.u64;
x86_struct->data = arm_struct->data.u64;
++x86_struct;
++arm_struct;
--nbr;
@@ -786,7 +794,7 @@ void AlignEpollEvent(void* dest, void* source, int nbr)
struct epoll_event *arm_struct = (struct epoll_event*)dest;
while(nbr) {
arm_struct->events = x86_struct->events;
arm_struct->data.u64 = x86_struct->data.u64;
arm_struct->data.u64 = x86_struct->data;
++x86_struct;
++arm_struct;
--nbr;
@@ -908,4 +916,4 @@ void unalignNGValue(void* value, my_GValue_t* v, int n)
value+=4+2*sizeof(double);
--n;
}
}
}
+9 -1
View File
@@ -146,6 +146,7 @@ void freeFts(box86context_t* context, void* ftsp)
#endif
EXPORT void* my_fts_open(x86emu_t* emu, void* path, int options, void* compare_fn)
{
(void)emu;
return fts_open(path, options, findcompareFct(compare_fn));
}
@@ -153,6 +154,8 @@ EXPORT int my_fts_close(x86emu_t* emu, void* ftsp)
{
#ifndef NOALIGN
freeFts(emu->context, ftsp);
#else
(void)emu;
#endif
return fts_close(ftsp);
}
@@ -160,6 +163,7 @@ EXPORT int my_fts_close(x86emu_t* emu, void* ftsp)
EXPORT void* my_fts_read(x86emu_t* emu, void* ftsp)
{
#ifdef NOALIGN
(void)emu;
return fts_read(ftsp);
#else
return getFtsent(getFtsentMap(emu->context, ftsp), fts_read(ftsp), 0);
@@ -169,6 +173,7 @@ EXPORT void* my_fts_read(x86emu_t* emu, void* ftsp)
EXPORT void* my_fts_children(x86emu_t* emu, void* ftsp, int options)
{
#ifdef NOALIGN
(void)emu;
return fts_children(ftsp, options);
#else
return getFtsent(getFtsentMap(emu->context, ftsp), fts_children(ftsp, options), 1);
@@ -179,6 +184,8 @@ void InitFTSMap(box86context_t* context)
{
#ifndef NOALIGN
context->ftsmap = kh_init(fts);
#else
(void)context;
#endif
}
void FreeFTSMap(box86context_t* context)
@@ -189,6 +196,7 @@ void FreeFTSMap(box86context_t* context)
(void)ftsentMap;
kh_foreach(context->ftsmap, ptr, ftsentMap, freeFts(context, (FTSENT*)ptr));
kh_destroy(fts, context->ftsmap);
#else
(void)context;
#endif
}
+1
View File
@@ -189,6 +189,7 @@ EXPORT void my__obstack_newchunk(struct i386_obstack* obstack, int s)
EXPORT int32_t my_obstack_vprintf(x86emu_t* emu, struct i386_obstack* obstack, void* fmt, uint32_t* b, va_list V)
{
(void)emu; (void)V;
struct obstack native = {0};
from_i386_obstack(obstack, &native);
#ifndef NOALIGN
+89 -64
View File
@@ -32,6 +32,7 @@
#ifdef DYNAREC
#include "dynablock.h"
#include "../dynarec/dynablock_private.h"
#include "dynarec_arm.h"
#endif
@@ -131,35 +132,19 @@ struct i386_fpstate
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;
emu->sw.f.F87_TOP = emu->top&7;
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;
state->cw = emu->cw.x16;
// save SSE and MMX regs
fpu_fxsave(emu, &state->ControlWord);
}
static void load_fpreg(x86emu_t* emu, struct i386_fpstate* state)
{
// copy SSE and MMX regs
fpu_fxrstor(emu, &state->ControlWord);
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);
emu->top = emu->sw.f.F87_TOP&7;
}
typedef struct i386_fpstate *i386_fpregset_t;
@@ -280,7 +265,9 @@ static void sigstack_key_alloc() {
pthread_key_create(&sigstack_key, sigstack_destroy);
}
uint32_t RunFunctionHandler(int* exit, i386_ucontext_t* sigcontext, uintptr_t fnc, int nargs, ...)
//1<<8 is mutex_dyndump
#define is_dyndump_locked (1<<8)
uint32_t RunFunctionHandler(int* exit, int dynarec, i386_ucontext_t* sigcontext, uintptr_t fnc, int nargs, ...)
{
if(fnc==0 || fnc==1) {
printf_log(LOG_NONE, "BOX86: Warning, calling Signal function handler %s with %d args \n", fnc?"SIG_DFL":"SIG_IGN", nargs);
@@ -313,7 +300,10 @@ uint32_t RunFunctionHandler(int* exit, i386_ucontext_t* sigcontext, uintptr_t fn
int oldquitonlongjmp = emu->quitonlongjmp;
emu->quitonlongjmp = 2;
EmuCall(emu, fnc); // avoid DynaCall for now
if(dynarec)
DynaCall(emu, fnc);
else
EmuCall(emu, fnc);
uint32_t ret = R_EAX;
emu->quitonlongjmp = oldquitonlongjmp;
@@ -366,7 +356,7 @@ EXPORT int my_sigaltstack(x86emu_t* emu, const i386_stack_t* ss, i386_stack_t* o
return -1;
}
i386_stack_t *new_ss = (i386_stack_t*)pthread_getspecific(sigstack_key);
if(!ss) {
if(oss) {
if(!new_ss) {
oss->ss_flags = SS_DISABLE;
oss->ss_sp = emu->init_stack;
@@ -376,6 +366,8 @@ EXPORT int my_sigaltstack(x86emu_t* emu, const i386_stack_t* ss, i386_stack_t* o
oss->ss_sp = new_ss->ss_sp;
oss->ss_size = new_ss->ss_size;
}
}
if(!ss) {
return 0;
}
printf_log(LOG_DEBUG, "%04d|sigaltstack called ss=%p[flags=0x%x, sp=%p, ss=0x%x], oss=%p\n", GetTID(), ss, ss->ss_flags, ss->ss_sp, ss->ss_size, oss);
@@ -391,19 +383,9 @@ EXPORT int my_sigaltstack(x86emu_t* emu, const i386_stack_t* ss, i386_stack_t* o
return 0;
}
if(oss) {
if(!new_ss) {
oss->ss_flags = SS_DISABLE;
oss->ss_sp = emu->init_stack;
oss->ss_size = emu->size_stack;
} else {
oss->ss_flags = new_ss->ss_flags;
oss->ss_sp = new_ss->ss_sp;
oss->ss_size = new_ss->ss_size;
}
}
if(!new_ss)
new_ss = (i386_stack_t*)box_calloc(1, sizeof(i386_stack_t));
new_ss->ss_flags = 0;
new_ss->ss_sp = ss->ss_sp;
new_ss->ss_size = ss->ss_size;
@@ -497,6 +479,8 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
if(db) {
frame = (uintptr_t*)p->uc_mcontext.arm_r8;
}
#else
(void)ucntx; (void)cur_db;
#endif
// stack tracking
i386_stack_t *new_ss = my_context->onstack[sig]?(i386_stack_t*)pthread_getspecific(sigstack_key):NULL;
@@ -571,7 +555,8 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
sigcontext->uc_stack.ss_sp = new_ss->ss_sp;
sigcontext->uc_stack.ss_size = new_ss->ss_size;
sigcontext->uc_stack.ss_flags = new_ss->ss_flags;
}
} else
sigcontext->uc_stack.ss_flags = SS_DISABLE;
// Try to guess some REG_TRAPNO
/*
TRAP_x86_DIVIDE = 0, // Division by zero exception
@@ -614,8 +599,13 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
}
if(info->si_code == SEGV_ACCERR && old_code)
*old_code = -1;
} else if(sig==SIGFPE)
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 19;
} else if(sig==SIGFPE) {
if (info->si_code == FPE_INTOVF) {
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 4;
} else {
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 19;
}
}
else if(sig==SIGILL)
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 6;
// call the signal handler
@@ -633,11 +623,18 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
int exits = 0;
int ret;
int dynarec = 0;
#ifdef DYNAREC
if(sig!=SIGSEGV && !(Locks&is_dyndump_locked))
dynarec = 1;
#endif
if(simple)
ret = RunFunctionHandler(&exits, sigcontext, my_context->signals[sig], 1, sig);
ret = RunFunctionHandler(&exits, dynarec, sigcontext, my_context->signals[sig], 1, sig);
else
ret = RunFunctionHandler(&exits, sigcontext, my_context->signals[sig], 3, sig, info2, sigcontext);
ret = RunFunctionHandler(&exits, dynarec, sigcontext, my_context->signals[sig], 3, sig, info2, sigcontext);
// restore old value from emu
if(used_stack) // release stack
new_ss->ss_flags = 0;
#define GO(R) R_##R = old_##R
GO(EAX);
GO(ECX);
@@ -677,6 +674,10 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
if(used_stack) // release stack
new_ss->ss_flags = 0;
//relockMutex(Locks); // do not relock mutex, because of the siglongjmp, whatever was running is canceled
#ifdef DYNAREC
if(Locks & is_dyndump_locked)
CancelBlock();
#endif
siglongjmp(ejb->jmpbuf, 1);
}
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)":"");
@@ -705,16 +706,18 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
printf_log(LOG_DEBUG, "Sigactionhanlder main function returned (exit=%d, restorer=%p)\n", exits, (void*)restorer);
if(exits) {
//relockMutex(Locks); // the thread will exit, so no relock there
#ifdef DYNAREC
if(Locks & is_dyndump_locked)
CancelBlock();
#endif
exit(ret);
}
if(restorer)
RunFunctionHandler(&exits, NULL, restorer, 0);
if(used_stack) // release stack
new_ss->ss_flags = 0;
RunFunctionHandler(&exits, 0, NULL, restorer, 0);
relockMutex(Locks);
}
extern __thread void* current_helper;
extern void* current_helper;
void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
{
@@ -736,9 +739,18 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
#endif
int Locks = unlockMutex();
uint32_t prot = getProtection((uintptr_t)addr);
#ifdef BAD_SIGNAL
// try to see if the si_code makes sense
// the RK3588 tend to need a special Kernel that seems to have a weird behaviour sometimes
if((sig==SIGSEGV) && (addr) && (info->si_code == 1) && prot&(PROT_READ|PROT_WRITE|PROT_EXEC)) {
printf_log(LOG_DEBUG, "Workaround for suspicious si_code for %p / prot=0x%x\n", addr, prot);
info->si_code = 2;
}
#endif
#ifdef DYNAREC
if((Locks & (1<<8)) && (sig==SIGSEGV) && current_helper) { //1<<8 is mutex_dyndump
if((Locks & is_dyndump_locked) && (sig==SIGSEGV) && current_helper) {
relockMutex(Locks);
CancelBlock();
cancelFillBlock(); // Segfault inside a Fillblock
}
dynablock_t* db = NULL;
@@ -750,6 +762,16 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
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;
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;
}
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();
@@ -777,6 +799,10 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
dynarec_log(LOG_INFO, "Dynablock %p(%p) unprotected, getting out (arm pc=%p, x86_pc=%p, special=%d)!\n", db, db->x86_addr, pc, (void*)ejb->emu->ip.dword[0], special);
}
//relockMutex(Locks); // do not relock because of he siglongjmp
#ifdef DYNAREC
if(Locks & is_dyndump_locked)
CancelBlock();
#endif
siglongjmp(ejb->jmpbuf, 2);
}
dynarec_log(LOG_INFO, "Warning, Auto-SMC (%p for db %p/%p) detected, but jmpbuffer not ready!\n", (void*)addr, db, (void*)db->x86_addr);
@@ -804,6 +830,7 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
glitch_addr = addr;
glitch_prot = prot;
relockMutex(Locks);
sched_yield(); // give time to the other process
return; // try again
}
glitch_pc = NULL;
@@ -811,21 +838,24 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
glitch_prot = 0;
}
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;
if((glitch_pc!=pc || glitch_addr!=addr || glitch_prot!=prot)) {
static void* glitch2_pc = NULL;
static void* glitch2_addr = NULL;
static int glitch2_prot = 0;
if((glitch2_pc!=pc || glitch2_addr!=addr || glitch2_prot!=prot)) {
dynarec_log(LOG_INFO, "Is that a multi process glitch too?\n");
glitch_pc = pc;
glitch_addr = addr;
glitch_prot = prot;
//printf_log(LOG_INFO, "Is that a multi process glitch too?\n");
glitch2_pc = pc;
glitch2_addr = addr;
glitch2_prot = prot;
sched_yield(); // give time to the other process
forceProtection((uintptr_t)addr, 1, prot); // force the protection
relockMutex(Locks);
sched_yield(); // give time to the other process
return; // try again
}
glitch_pc = NULL;
glitch_addr = NULL;
glitch_prot = 0;
glitch2_pc = NULL;
glitch2_addr = NULL;
glitch2_prot = 0;
}
}
#else
@@ -887,13 +917,7 @@ 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]);
}
}
print_cycle_log(log_minimum);
}
#ifdef DYNAREC
uint32_t hash = 0;
@@ -933,7 +957,7 @@ exit(-1);
else
printf_log(log_minimum, "\n");
#ifndef ANDROID
if(box86_backtrace && (log_minimum<=box86_log)) {
if(box86_showbt && (log_minimum<=box86_log)) {
int nptrs;
void *buffer[200];
char **strings;
@@ -1269,6 +1293,7 @@ EXPORT int my_setcontext(x86emu_t* emu, void* ucp)
EXPORT int my_makecontext(x86emu_t* emu, void* ucp, void* fnc, int32_t argc, int32_t* argv)
{
(void)emu;
// printf_log(LOG_NONE, "Warning: call to unimplemented makecontext\n");
i386_ucontext_t *u = (i386_ucontext_t*)ucp;
// setup stack
+71 -40
View File
@@ -85,50 +85,50 @@ void CleanStackSize(box86context_t* context)
threadstack_t *ts;
if(!context || !context->stacksizes)
return;
pthread_mutex_lock(&context->mutex_thread);
mutex_lock(&context->mutex_thread);
kh_foreach_value(context->stacksizes, ts, box_free(ts));
kh_destroy(threadstack, context->stacksizes);
context->stacksizes = NULL;
pthread_mutex_unlock(&context->mutex_thread);
mutex_unlock(&context->mutex_thread);
}
void FreeStackSize(kh_threadstack_t* map, uintptr_t attr)
{
pthread_mutex_lock(&my_context->mutex_thread);
mutex_lock(&my_context->mutex_thread);
khint_t k = kh_get(threadstack, map, attr);
if(k!=kh_end(map)) {
box_free(kh_value(map, k));
kh_del(threadstack, map, k);
}
pthread_mutex_unlock(&my_context->mutex_thread);
mutex_unlock(&my_context->mutex_thread);
}
void AddStackSize(kh_threadstack_t* map, uintptr_t attr, void* stack, size_t stacksize)
{
khint_t k;
int ret;
pthread_mutex_lock(&my_context->mutex_thread);
mutex_lock(&my_context->mutex_thread);
k = kh_put(threadstack, map, attr, &ret);
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);
mutex_unlock(&my_context->mutex_thread);
}
// return stack from attr (or from current emu if attr is not found..., wich is wrong but approximate enough?)
int GetStackSize(x86emu_t* emu, uintptr_t attr, void** stack, size_t* stacksize)
{
if(emu->context->stacksizes && attr) {
pthread_mutex_lock(&my_context->mutex_thread);
mutex_lock(&my_context->mutex_thread);
khint_t k = kh_get(threadstack, emu->context->stacksizes, attr);
if(k!=kh_end(emu->context->stacksizes)) {
threadstack_t* ts = kh_value(emu->context->stacksizes, k);
*stack = ts->stack;
*stacksize = ts->stacksize;
pthread_mutex_unlock(&my_context->mutex_thread);
mutex_unlock(&my_context->mutex_thread);
return 1;
}
pthread_mutex_unlock(&my_context->mutex_thread);
mutex_unlock(&my_context->mutex_thread);
}
// should a Warning be emited?
*stack = emu->init_stack;
@@ -183,16 +183,9 @@ static void emuthread_destroy(void* p)
}
static pthread_key_t thread_key;
static pthread_once_t thread_key_once = PTHREAD_ONCE_INIT;
static void thread_key_alloc() {
pthread_key_create(&thread_key, emuthread_destroy);
}
void thread_set_emu(x86emu_t* emu)
{
// create the key
pthread_once(&thread_key_once, thread_key_alloc);
emuthread_t *et = (emuthread_t*)pthread_getspecific(thread_key);
if(!et) {
et = (emuthread_t*)box_calloc(1, sizeof(emuthread_t));
@@ -207,8 +200,6 @@ void thread_set_emu(x86emu_t* emu)
x86emu_t* thread_get_emu()
{
// create the key
pthread_once(&thread_key_once, thread_key_alloc);
emuthread_t *et = (emuthread_t*)pthread_getspecific(thread_key);
if(!et) {
int stacksize = 2*1024*1024;
@@ -233,8 +224,6 @@ x86emu_t* thread_get_emu()
static void* pthread_routine(void* p)
{
// create the key
pthread_once(&thread_key_once, thread_key_alloc);
// free current emuthread if it exist
{
void* t = pthread_getspecific(thread_key);
@@ -361,8 +350,9 @@ void my_longjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int32_t
static __thread x86emu_t* cancel_emu[CANCEL_MAX] = {0};
static __thread x86_unwind_buff_t* cancel_buff[CANCEL_MAX] = {0};
static __thread int cancel_deep = 0;
EXPORT void my___pthread_register_cancel(void* E, void* B)
EXPORT void my___pthread_register_cancel(x86emu_t* emu, void* B)
{
(void)B;
// get a stack local copy of the args, as may be live in some register depending the architecture (like ARM)
if(cancel_deep<0) {
printf_log(LOG_NONE/*LOG_INFO*/, "BOX86: Warning, inconsistant value in __pthread_register_cancel (%d)\n", cancel_deep);
@@ -373,14 +363,14 @@ EXPORT void my___pthread_register_cancel(void* E, void* B)
else
{printf_log(LOG_NONE/*LOG_INFO*/, "BOX86: Warning, calling __pthread_register_cancel(...) too many time\n");}
cancel_emu[cancel_deep] = (x86emu_t*)E;
cancel_emu[cancel_deep] = emu;
// on i386, the function as __cleanup_fct_attribute attribute: so 1st parameter is in register
x86_unwind_buff_t* buff = cancel_buff[cancel_deep] = (x86_unwind_buff_t*)((x86emu_t*)E)->regs[_AX].dword[0];
x86_unwind_buff_t* buff = cancel_buff[cancel_deep] = (x86_unwind_buff_t*)R_EAX;
__pthread_unwind_buf_t * pbuff = AddCancelThread(buff);
if(__sigsetjmp((struct __jmp_buf_tag*)(void*)pbuff->__cancel_jmp_buf, 0)) {
//DelCancelThread(cancel_buff); // no del here, it will be delete by unwind_next...
int i = cancel_deep--;
x86emu_t* emu = cancel_emu[i];
emu = cancel_emu[i];
my_longjmp(emu, cancel_buff[i]->__cancel_jmp_buf, 1);
DynaRun(emu); // resume execution
return;
@@ -402,6 +392,7 @@ EXPORT void my___pthread_unregister_cancel(x86emu_t* emu, x86_unwind_buff_t* buf
EXPORT void my___pthread_unwind_next(x86emu_t* emu, void* p)
{
(void)p;
// on i386, the function as __cleanup_fct_attribute attribute: so 1st parameter is in register
x86_unwind_buff_t* buff = (x86_unwind_buff_t*)R_EAX;
__pthread_unwind_buf_t pbuff = *GetCancelThread(buff);
@@ -496,7 +487,6 @@ static void* findcleanup_routineFct(void* fct)
// custom implementation of pthread_once...
static __thread uintptr_t my_once_callback_fct = 0;
int EXPORT my_pthread_once(x86emu_t* emu, int* once, void* cb)
{
#ifdef DYNAREC
@@ -514,13 +504,14 @@ int EXPORT my_pthread_once(x86emu_t* emu, int* once, void* cb)
#endif
if(old)
return 0;
EmuCall(emu, (uintptr_t)cb); // avoid DynaCall for now, functions are only used once after all
DynaCall(emu, (uintptr_t)cb); // using DynaCall now, speedup wine 7.21 (proabbly other too) init
return 0;
}
EXPORT int my___pthread_once(x86emu_t* emu, void* once, void* cb) __attribute__((alias("my_pthread_once")));
EXPORT int my_pthread_key_create(x86emu_t* emu, void* key, void* dtor)
{
(void)emu;
return pthread_key_create(key, findkey_destructorFct(dtor));
}
EXPORT int my___pthread_key_create(x86emu_t* emu, void* key, void* dtor) __attribute__((alias("my_pthread_key_create")));
@@ -537,7 +528,7 @@ kh_mapcond_t *mapcond = NULL;
static pthread_cond_t* add_cond(void* cond)
{
pthread_mutex_lock(&my_context->mutex_thread);
mutex_lock(&my_context->mutex_thread);
khint_t k;
int ret;
pthread_cond_t *c;
@@ -547,14 +538,14 @@ static pthread_cond_t* add_cond(void* cond)
else
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);
mutex_unlock(&my_context->mutex_thread);
return c;
}
static pthread_cond_t* get_cond(void* cond)
{
pthread_cond_t* ret;
int r;
pthread_mutex_lock(&my_context->mutex_thread);
mutex_lock(&my_context->mutex_thread);
khint_t k = kh_get(mapcond, mapcond, *(uintptr_t*)cond);
if(k==kh_end(mapcond)) {
khint_t k = kh_get(mapcond, mapcond, (uintptr_t)cond);
@@ -569,30 +560,32 @@ static pthread_cond_t* get_cond(void* cond)
ret = kh_value(mapcond, k);
} else
ret = kh_value(mapcond, k);
pthread_mutex_unlock(&my_context->mutex_thread);
mutex_unlock(&my_context->mutex_thread);
return ret;
}
static void del_cond(void* cond)
{
if(!mapcond)
return;
pthread_mutex_lock(&my_context->mutex_thread);
mutex_lock(&my_context->mutex_thread);
khint_t k = kh_get(mapcond, mapcond, *(uintptr_t*)cond);
if(k!=kh_end(mapcond)) {
box_free(kh_value(mapcond, k));
kh_del(mapcond, mapcond, k);
}
pthread_mutex_unlock(&my_context->mutex_thread);
mutex_unlock(&my_context->mutex_thread);
}
pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m);
EXPORT int my_pthread_cond_broadcast_old(x86emu_t* emu, void* cond)
{
(void)emu;
pthread_cond_t * c = get_cond(cond);
return pthread_cond_broadcast(c);
}
EXPORT int my_pthread_cond_destroy_old(x86emu_t* emu, void* cond)
{
(void)emu;
pthread_cond_t * c = get_cond(cond);
int ret = pthread_cond_destroy(c);
if(c!=cond) del_cond(cond);
@@ -600,42 +593,50 @@ EXPORT int my_pthread_cond_destroy_old(x86emu_t* emu, void* cond)
}
EXPORT int my_pthread_cond_init_old(x86emu_t* emu, void* cond, void* attr)
{
(void)emu;
pthread_cond_t *c = add_cond(cond);
return pthread_cond_init(c, (const pthread_condattr_t*)attr);
}
EXPORT int my_pthread_cond_signal_old(x86emu_t* emu, void* cond)
{
(void)emu;
pthread_cond_t * c = get_cond(cond);
return pthread_cond_signal(c);
}
EXPORT int my_pthread_cond_timedwait_old(x86emu_t* emu, void* cond, void* mutex, void* abstime)
{
(void)emu;
pthread_cond_t * c = get_cond(cond);
return pthread_cond_timedwait(c, getAlignedMutex((pthread_mutex_t*)mutex), (const struct timespec*)abstime);
}
EXPORT int my_pthread_cond_wait_old(x86emu_t* emu, void* cond, void* mutex)
{
(void)emu;
pthread_cond_t * c = get_cond(cond);
return pthread_cond_wait(c, getAlignedMutex((pthread_mutex_t*)mutex));
}
EXPORT int my_pthread_cond_timedwait(x86emu_t* emu, void* cond, void* mutex, void* abstime)
{
(void)emu;
return pthread_cond_timedwait((pthread_cond_t*)cond, getAlignedMutex((pthread_mutex_t*)mutex), (const struct timespec*)abstime);
}
EXPORT int my_pthread_cond_wait(x86emu_t* emu, void* cond, void* mutex)
{
(void)emu;
return pthread_cond_wait((pthread_cond_t*)cond, getAlignedMutex((pthread_mutex_t*)mutex));
}
EXPORT int my_pthread_mutexattr_setkind_np(x86emu_t* emu, void* t, int kind)
{
(void)emu;
// does "kind" needs some type of translation?
return pthread_mutexattr_settype(t, kind);
}
EXPORT int my_pthread_attr_setscope(x86emu_t* emu, void* attr, int scope)
{
(void)emu;
if(scope!=PTHREAD_SCOPE_SYSTEM) printf_log(LOG_INFO, "Warning, scope of call to pthread_attr_setscope(...) changed from %d to PTHREAD_SCOPE_SYSTEM\n", scope);
return pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM);
//The scope is either PTHREAD_SCOPE_SYSTEM or PTHREAD_SCOPE_PROCESS
@@ -645,27 +646,32 @@ EXPORT int my_pthread_attr_setscope(x86emu_t* emu, void* attr, int scope)
#ifndef ANDROID
EXPORT void my__pthread_cleanup_push_defer(x86emu_t* emu, void* buffer, void* routine, void* arg)
{
(void)emu;
real_pthread_cleanup_push_defer(buffer, findcleanup_routineFct(routine), arg);
}
EXPORT void my__pthread_cleanup_push(x86emu_t* emu, void* buffer, void* routine, void* arg)
{
(void)emu;
_pthread_cleanup_push(buffer, findcleanup_routineFct(routine), arg);
}
EXPORT void my__pthread_cleanup_pop_restore(x86emu_t* emu, void* buffer, int exec)
{
(void)emu;
real_pthread_cleanup_pop_restore(buffer, exec);
}
EXPORT void my__pthread_cleanup_pop(x86emu_t* emu, void* buffer, int exec)
{
(void)emu;
_pthread_cleanup_pop(buffer, exec);
}
// getaffinity_np (pthread or attr) hav an "old" version (glibc-2.3.3) that only have 2 args, cpusetsize is omited
EXPORT int my_pthread_getaffinity_np(x86emu_t* emu, pthread_t thread, int cpusetsize, void* cpuset)
{
(void)emu;
if(cpusetsize>0x1000) {
// probably old version of the function, that didn't have cpusetsize....
cpuset = (void*)cpusetsize;
@@ -682,6 +688,7 @@ EXPORT int my_pthread_getaffinity_np(x86emu_t* emu, pthread_t thread, int cpuset
EXPORT int my_pthread_setaffinity_np(x86emu_t* emu, pthread_t thread, int cpusetsize, void* cpuset)
{
(void)emu;
if(cpusetsize>0x1000) {
// probably old version of the function, that didn't have cpusetsize....
cpuset = (void*)cpusetsize;
@@ -698,6 +705,7 @@ EXPORT int my_pthread_setaffinity_np(x86emu_t* emu, pthread_t thread, int cpuset
EXPORT int my_pthread_attr_setaffinity_np(x86emu_t* emu, void* attr, uint32_t cpusetsize, void* cpuset)
{
(void)emu;
if(cpusetsize>0x1000) {
// probably old version of the function, that didn't have cpusetsize....
cpuset = (void*)cpusetsize;
@@ -715,6 +723,7 @@ 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)
{
(void)emu;
// 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))
@@ -724,6 +733,7 @@ EXPORT int my_pthread_kill(x86emu_t* emu, void* thread, int sig)
EXPORT int my_pthread_kill_old(x86emu_t* emu, void* thread, int sig)
{
(void)emu;
// check for old "is everything ok?"
if(!thread)
thread = (void*)pthread_self();
@@ -732,6 +742,7 @@ EXPORT int my_pthread_kill_old(x86emu_t* emu, void* thread, int sig)
EXPORT int my_pthread_join(x86emu_t* emu, void* thread, void** ret)
{
(void)emu;
if(!thread)
return ESRCH;
return pthread_join((pthread_t)thread, ret);
@@ -739,6 +750,7 @@ EXPORT int my_pthread_join(x86emu_t* emu, void* thread, void** ret)
//EXPORT void my_pthread_exit(x86emu_t* emu, void* retval)
//{
// (void)emu;
// emu->quit = 1; // to be safe
// pthread_exit(retval);
//}
@@ -790,7 +802,11 @@ typedef struct mutexes_block_s {
} mutexes_block_t;
static mutexes_block_t *mutexes = NULL;
#ifndef DYNAREC
static pthread_mutex_t mutex_mutexes = PTHREAD_MUTEX_INITIALIZER;
#else
static uint32_t mutex_mutexes = 0;
#endif
static mutexes_block_t* NewMutexesBlock()
{
@@ -800,7 +816,7 @@ static mutexes_block_t* NewMutexesBlock()
}
static int NewMutex() {
pthread_mutex_lock(&mutex_mutexes);
mutex_lock(&mutex_mutexes);
if(!mutexes) {
mutexes = NewMutexesBlock();
}
@@ -817,10 +833,10 @@ static int NewMutex() {
for (int i=0; i<MUTEXES_SIZE; ++i)
if(!m->taken[i]) {
m->taken[i] = 1;
pthread_mutex_unlock(&mutex_mutexes);
mutex_unlock(&mutex_mutexes);
return j*MUTEXES_SIZE + i;
}
pthread_mutex_unlock(&mutex_mutexes);
mutex_unlock(&mutex_mutexes);
printf_log(LOG_NONE, "Error: NewMutex unreachable part reached\n");
return (int)-1; // error!!!!
}
@@ -829,13 +845,13 @@ void FreeMutex(int k)
{
if(!mutexes)
return; //???
pthread_mutex_lock(&mutex_mutexes);
mutex_lock(&mutex_mutexes);
mutexes_block_t* m = mutexes;
for(int i=0; i<k/MUTEXES_SIZE; ++i)
m = m->next;
m->taken[k%MUTEXES_SIZE] = 0;
++m->n_free;
pthread_mutex_unlock(&mutex_mutexes);
mutex_unlock(&mutex_mutexes);
}
void FreeAllMutexes(mutexes_block_t* m)
@@ -996,6 +1012,9 @@ void init_pthread_helper()
InitCancelThread();
mapcond = kh_init(mapcond);
pthread_key_create(&jmpbuf_key, emujmpbuf_destroy);
pthread_setspecific(jmpbuf_key, NULL);
pthread_key_create(&thread_key, emuthread_destroy);
pthread_setspecific(thread_key, NULL);
#if !defined(NOALIGN) && defined(ANDROID)
unaligned_mutex = kh_init(mutex);
#endif
@@ -1026,16 +1045,16 @@ void fini_pthread_helper(box86context_t* context)
#endif
emu_jmpbuf_t *ejb = (emu_jmpbuf_t*)pthread_getspecific(jmpbuf_key);
if(ejb) {
emujmpbuf_destroy(ejb);
pthread_setspecific(jmpbuf_key, NULL);
emujmpbuf_destroy(ejb);
}
emuthread_t *et = (emuthread_t*)pthread_getspecific(thread_key);
if(et) {
emuthread_destroy(et);
pthread_setspecific(thread_key, NULL);
emuthread_destroy(et);
}
}
#ifndef DYNAREC
int checkUnlockMutex(void* m)
{
pthread_mutex_t* mutex = (pthread_mutex_t*)m;
@@ -1045,3 +1064,15 @@ int checkUnlockMutex(void* m)
}
return 0;
}
int checkLockMutex(void* m)
{
pthread_mutex_t* mutex = (pthread_mutex_t*)m;
int ret = pthread_mutex_unlock(mutex);
if(ret==0) {
pthread_mutex_lock(mutex); // how to check the lock without unlock?
return 1;
}
return 0;
}
#endif
+106 -37
View File
@@ -254,25 +254,26 @@ typedef enum VkStructureType {
VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT = 1000022000,
VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT = 1000022001,
VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT = 1000022002,
VK_STRUCTURE_TYPE_VIDEO_PROFILE_KHR = 1000023000,
VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR = 1000023000,
VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR = 1000023001,
VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_KHR = 1000023002,
VK_STRUCTURE_TYPE_VIDEO_GET_MEMORY_PROPERTIES_KHR = 1000023003,
VK_STRUCTURE_TYPE_VIDEO_BIND_MEMORY_KHR = 1000023004,
VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR = 1000023002,
VK_STRUCTURE_TYPE_VIDEO_SESSION_MEMORY_REQUIREMENTS_KHR = 1000023003,
VK_STRUCTURE_TYPE_BIND_VIDEO_SESSION_MEMORY_INFO_KHR = 1000023004,
VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR = 1000023005,
VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000023006,
VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR = 1000023007,
VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR = 1000023008,
VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR = 1000023009,
VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR = 1000023010,
VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_KHR = 1000023011,
VK_STRUCTURE_TYPE_VIDEO_QUEUE_FAMILY_PROPERTIES_2_KHR = 1000023012,
VK_STRUCTURE_TYPE_VIDEO_PROFILES_KHR = 1000023013,
VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR = 1000023011,
VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR = 1000023012,
VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR = 1000023013,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR = 1000023014,
VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR = 1000023015,
VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_2_KHR = 1000023016,
VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR = 1000023016,
VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR = 1000024000,
VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR = 1000024001,
VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR = 1000024002,
VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000,
VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001,
VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002,
@@ -289,27 +290,26 @@ typedef enum VkStructureType {
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT = 1000038002,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_VCL_FRAME_INFO_EXT = 1000038003,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT = 1000038004,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_EXT = 1000038005,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_EXT = 1000038006,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_EXT = 1000038007,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_INFO_EXT = 1000038005,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_INFO_EXT = 1000038006,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_EXT = 1000038007,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT = 1000038008,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT = 1000038009,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_REFERENCE_LISTS_EXT = 1000038010,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_REFERENCE_LISTS_INFO_EXT = 1000038010,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_EXT = 1000039000,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000039001,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT = 1000039002,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_VCL_FRAME_INFO_EXT = 1000039003,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_EXT = 1000039004,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_EXT = 1000039005,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_EXT = 1000039006,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_EXT = 1000039007,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_REFERENCE_LISTS_EXT = 1000039008,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_EXT = 1000039005,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_INFO_EXT = 1000039006,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_EXT = 1000039007,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_REFERENCE_LISTS_INFO_EXT = 1000039008,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT = 1000039009,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_EXT = 1000039010,
VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_EXT = 1000040000,
VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_EXT = 1000040001,
VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_MVC_EXT = 1000040002,
VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_EXT = 1000040003,
VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_EXT = 1000040003,
VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000040004,
VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT = 1000040005,
VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_EXT = 1000040006,
@@ -474,7 +474,7 @@ typedef enum VkStructureType {
VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_EXT = 1000187000,
VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000187001,
VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT = 1000187002,
VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_EXT = 1000187003,
VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_EXT = 1000187003,
VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_EXT = 1000187004,
VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_EXT = 1000187005,
VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR = 1000174000,
@@ -575,12 +575,16 @@ typedef enum VkStructureType {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT = 1000287001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT = 1000287002,
VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR = 1000290000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_BARRIER_FEATURES_NV = 1000292000,
VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_PRESENT_BARRIER_NV = 1000292001,
VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_BARRIER_CREATE_INFO_NV = 1000292002,
VK_STRUCTURE_TYPE_PRESENT_ID_KHR = 1000294000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR = 1000294001,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR = 1000299000,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR = 1000299001,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR = 1000299002,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR = 1000299003,
VK_STRUCTURE_TYPE_VIDEO_ENCODE_USAGE_INFO_KHR = 1000299004,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000,
VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001,
VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT = 1000311000,
@@ -610,6 +614,8 @@ typedef enum VkStructureType {
VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV = 1000327000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV = 1000327001,
VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV = 1000327002,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT = 1000328000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_EXT = 1000328001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT = 1000330000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT = 1000332000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT = 1000332001,
@@ -622,15 +628,17 @@ typedef enum VkStructureType {
VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT = 1000338004,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT = 1000339000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT = 1000340000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM = 1000342000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT = 1000341000,
VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT = 1000341001,
VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT = 1000341002,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT = 1000344000,
VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT = 1000346000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE = 1000351000,
VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE = 1000351002,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT = 1000352000,
VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT = 1000352001,
VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT = 1000352002,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT = 1000353000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ADDRESS_BINDING_REPORT_FEATURES_EXT = 1000354000,
VK_STRUCTURE_TYPE_DEVICE_ADDRESS_BINDING_CALLBACK_DATA_EXT = 1000354001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT = 1000355000,
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT = 1000355001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT = 1000356000,
@@ -671,12 +679,23 @@ typedef enum VkStructureType {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT = 1000392000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT = 1000392001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT = 1000393000,
VK_STRUCTURE_TYPE_MICROMAP_BUILD_INFO_EXT = 1000396000,
VK_STRUCTURE_TYPE_MICROMAP_VERSION_INFO_EXT = 1000396001,
VK_STRUCTURE_TYPE_COPY_MICROMAP_INFO_EXT = 1000396002,
VK_STRUCTURE_TYPE_COPY_MICROMAP_TO_MEMORY_INFO_EXT = 1000396003,
VK_STRUCTURE_TYPE_COPY_MEMORY_TO_MICROMAP_INFO_EXT = 1000396004,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_FEATURES_EXT = 1000396005,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_PROPERTIES_EXT = 1000396006,
VK_STRUCTURE_TYPE_MICROMAP_CREATE_INFO_EXT = 1000396007,
VK_STRUCTURE_TYPE_MICROMAP_BUILD_SIZES_INFO_EXT = 1000396008,
VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT = 1000396009,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT = 1000411000,
VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT = 1000411001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT = 1000412000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE = 1000420000,
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_BINDING_REFERENCE_VALVE = 1000420001,
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_HOST_MAPPING_INFO_VALVE = 1000420002,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT = 1000421000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT = 1000422000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM = 1000425000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM = 1000425001,
@@ -686,6 +705,8 @@ typedef enum VkStructureType {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM = 1000440000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM = 1000440001,
VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM = 1000440002,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT = 1000455000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT = 1000455001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_MERGE_FEEDBACK_FEATURES_EXT = 1000458000,
VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT = 1000458001,
VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT = 1000458002,
@@ -694,10 +715,24 @@ typedef enum VkStructureType {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_PROPERTIES_EXT = 1000462001,
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT = 1000462002,
VK_STRUCTURE_TYPE_SHADER_MODULE_IDENTIFIER_EXT = 1000462003,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT = 1000342000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV = 1000464000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV = 1000464001,
VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_INFO_NV = 1000464002,
VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_PROPERTIES_NV = 1000464003,
VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_INFO_NV = 1000464004,
VK_STRUCTURE_TYPE_OPTICAL_FLOW_EXECUTE_INFO_NV = 1000464005,
VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_PRIVATE_DATA_INFO_NV = 1000464010,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT = 1000465000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT = 1000466000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM = 1000484000,
VK_STRUCTURE_TYPE_TILE_PROPERTIES_QCOM = 1000484001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC = 1000485000,
VK_STRUCTURE_TYPE_AMIGO_PROFILING_SUBMIT_INFO_SEC = 1000485001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT = 1000351000,
VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT = 1000351002,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_FEATURES_ARM = 1000497000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM = 1000497001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES,
VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
@@ -860,6 +895,9 @@ typedef enum VkStructureType {
VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR = VK_STRUCTURE_TYPE_IMAGE_BLIT_2,
VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2,
VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT,
VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE = VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT,
VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3,
VK_STRUCTURE_TYPE_PIPELINE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR,
@@ -891,10 +929,8 @@ typedef struct my_vkhead_s {
case VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO: \
case VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO: \
case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO: \
case VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO: \
case VK_STRUCTURE_TYPE_EVENT_CREATE_INFO: \
case VK_STRUCTURE_TYPE_FENCE_CREATE_INFO: \
case VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO: \
case VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO: \
case VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO: \
case VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO: \
@@ -998,6 +1034,20 @@ typedef struct my_vkhead_s {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_PROPERTIES_EXT: \
case VK_STRUCTURE_TYPE_SHADER_MODULE_IDENTIFIER_EXT: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES: \
case VK_STRUCTURE_TYPE_BUFFER_COPY_2: \
case VK_STRUCTURE_TYPE_OPTICAL_FLOW_EXECUTE_INFO_NV: \
case VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_INFO_NV: \
case VK_STRUCTURE_TYPE_IMAGE_COPY_2: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT: \
case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: \
#define CH(C, B, A) \
case C: \
@@ -1006,12 +1056,13 @@ typedef struct my_vkhead_s {
break;
#define CHANGE(A) \
CH(VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, "uPuuQupupp", A) \
CH(VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, "uPiUiiup", A) \
CH(VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, "uPiUiUU",A) \
CH(VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,"uPiiiiuuUiuuuu", A) \
CH(VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, "uPiUupuuu", A) \
CH(VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, "uPiuppppppppppUUuUi", A) \
CH(VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, "uPiUiiiiiiiuuuu", A) \
CH(VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, "uPiUiiSiiiiSiuuuu", A) \
CH(VK_STRUCTURE_TYPE_SUBMIT_INFO, "uPuppupup", A) \
CH(VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, "uPUuuuippp", A) \
CH(VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET, "uPUuuUuuu", A) \
@@ -1019,7 +1070,7 @@ typedef struct my_vkhead_s {
CH(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, "uP" \
"uuuuiYB" \
"SuuuuuuuuuuuUUuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuffuuuffuLUUUiuiuffuuuuiiiiuiiiiiuifuuuuffffffiiUUU"\
"Siiiii",A) \
"iiiii",A) \
CH(VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, "uPipu", A) \
CH(VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, "uPipu", A) \
CH(VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR, "uPUUUUu", A) \
@@ -1038,12 +1089,12 @@ typedef struct my_vkhead_s {
CH(VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2, "uPUUuQ", A) \
CH(VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2, "uPUiUiuQi", A) \
CH(VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2, "uPUiUiuQ", A) \
CH(VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2, "uPUUiuQ", A) \
CH(VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2, "uPUUiuQ", A) \
CH(VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2, "uPUiUuQ", A) \
CH(VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2, "uPUiUiuQ", A) \
CH(VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_EXT, "uPU", A) \
CH(VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO, "uPU", A) \
CH(VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, "uPiSuPiiUppUUi", A) \
CH(VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, "uPiuPiiUppUUi", A) \
CH(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR, "uPUUUuuuuu", A)\
CH(VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, "uPibp", A) \
CH(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT, "uPfffiiiiii", A)\
@@ -1052,6 +1103,20 @@ typedef struct my_vkhead_s {
CH(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES, "uPBBBuiuiiiiuuiuU", A) \
CH(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES, "uPiYYSuiiiiiiiiiiiiiiiiiuiiiiiiiuuuuuuuuuuuuuuuuuiiiiUu", A)\
CH(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES, "uPuuuuuuuuuuiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiUiUiU", A)\
CH(VK_STRUCTURE_TYPE_RENDERING_INFO, "uPiiiuuuuuPPP", A) \
CH(VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS, "uPP", A) \
CH(VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS, "uPPi", A) \
CH(VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, "uPiiiuuuuuiiiiupi", A) \
CH(VK_STRUCTURE_TYPE_DEPENDENCY_INFO, "uPiuQuQuQ", A) \
CH(VK_STRUCTURE_TYPE_MEMORY_BARRIER_2, "uPUUUU", A) \
CH(VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2, "uPUUUUuuUUU", A) \
CH(VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, "uPUUUUiiuuUSiuuuu", A) \
CH(VK_STRUCTURE_TYPE_SUBMIT_INFO_2, "upiuQuQuQ", A) \
CH(VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, "uPUUUu", A) \
CH(VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2, "uPUuuSiuuuiiiuuu", A) \
CH(VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, "uPpu", A) \
CH(VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, "uPUiiUiiiffff", A) \
CH(VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_PROPERTIES_NV, "uPi", A) \
//--------------------------------------------------------------
@@ -1101,10 +1166,9 @@ static void* reverse_vkDebugReportCallback_Fct(void* fct)
//--------------------------------------------------------------
//--------- TOOLS --------
//--------------------------------------------------------------
static int needAlign(my_vkhead_t* x86)
/* static int needAlign(my_vkhead_t* x86)
{
const char* s;
const char** src = &s;
int dst = 0;
while(x86) {
switch(x86->sType) {
@@ -1118,7 +1182,7 @@ static int needAlign(my_vkhead_t* x86)
x86 = x86->pNext;
}
return 0;
}
} */
//--------------------------------------------------------------
//--------- ALIGN x86 -> ARM --------
@@ -1183,14 +1247,16 @@ static my_vkhead_t* alignFromx86(my_vkhead_t* src, uint32_t cnt);
void* vkalignStruct(void* src, const char* desc, int cnt)
{
if(!src)
return src;
int sz = vkalignSize(desc);
int count=(cnt)?cnt:1;
int count=cnt;
void* dst = (void*)box_malloc(sz*count+sizeof(void*)*count);
int c = 0;
int a = 0;
uint32_t* psrc = (uint32_t*)src;
uint32_t* pdst = (uint32_t*)dst;
uint32_t* sign = (uint32_t*)(dst+sz*count);
// uint32_t* sign = (uint32_t*)(dst+sz*count);
void** save = (void**)(dst+sz*count);
uint32_t q;
while(count) {
@@ -1268,6 +1334,7 @@ static my_vkhead_t* alignFromx86(my_vkhead_t* src, uint32_t cnt)
{
if(!src)
return src;
//printf_log(LOG_INFO, "alignFromx86(%p:%d, %d)\n", src, src->sType, cnt);
my_vkhead_t *dst = src;
const char* s;
switch(src->sType) {
@@ -1275,7 +1342,7 @@ static my_vkhead_t* alignFromx86(my_vkhead_t* src, uint32_t cnt)
// no need to align, but follow next...
dst->pNext = alignFromx86(src->pNext, 1);
break;
CHANGE(dst=vkalignStruct(src, s, 1)) // will follow next
CHANGE(dst=vkalignStruct(src, s, cnt)) // will follow next
default:
// unknow
printf_log(LOG_INFO, "BOX86: Warning, unknown Vulkan structure type %d\n", src->sType);
@@ -1298,6 +1365,8 @@ void* VulkanFromx86(void* src)
static void* unalignTox86(my_vkhead_t* src, int cnt);
void* vkunalignStruct(void* src, const char* desc, int cnt)
{
if(!src)
return src;
int c = 0;
int a = 1;
int sz = vkalignSize(desc);
@@ -1381,7 +1450,7 @@ void* vkunalignNewStruct(void* dst, void* src, const char* desc, int cnt)
{
int c = 0;
int a = 1;
int sz = vkalignSize(desc);
// int sz = vkalignSize(desc);
uint32_t q;
uint32_t* psrc = (uint32_t*)src;
uint32_t* pdst = (uint32_t*)dst;
@@ -1564,10 +1633,10 @@ static void* unalignTox86(my_vkhead_t* src, int cnt)
{
if(!cnt || !src)
return src;
void* ret = NULL;
//printf_log(LOG_INFO, "unalignTox86(%p:%d, %d)\n", src, src->sType, cnt);
const char* s;
switch(src->sType) {
CHANGE( return vkunalignStruct(src, s, cnt))
CHANGE(return vkunalignStruct(src, s, cnt))
default:
// no need to unalign, but follow next...
if(cnt>1) printf_log(LOG_INFO, "Warning, unalignTox86 of %d struct %d not uspported\n", cnt, src->sType);
+177 -140
View File
@@ -41,25 +41,30 @@
#include "library.h"
#include "auxval.h"
#include "wine_tools.h"
#include "rcfile.h"
box86context_t *my_context = NULL;
int box86_log = LOG_NONE;
int box86_dump = 0;
int box86_nobanner = 0;
int box86_dynarec_log = LOG_NONE;
int box86_pagesize;
uintptr_t box86_pagesize;
uintptr_t box86_load_addr = 0;
int box86_backtrace = 0;
int box86_showbt = 0;
#ifdef DYNAREC
int box86_dynarec = 1;
int box86_dynarec_dump = 0;
int box86_dynarec_forced = 0;
int box86_dynarec_largest = 0;
int box86_dynarec_bigblock = 1;
int box86_dynarec_forward = 128;
int box86_dynarec_strongmem = 0;
int box86_dynarec_x87double = 0;
int box86_dynarec_fastnan = 1;
int box86_dynarec_fastround = 1;
int box86_dynarec_safeflags = 1;
int box86_dynarec_hotpage = 16;
int box86_dynarec_bleeding_edge = 1;
uintptr_t box86_nodynarec_start = 0;
uintptr_t box86_nodynarec_end = 0;
#ifdef ARM
@@ -75,6 +80,8 @@ int dlsym_error = 0;
int cycle_log = 0;
int trace_xmm = 0;
int trace_emm = 0;
char* trace_init = NULL;
char* box86_trace = NULL;
#ifdef HAVE_TRACE
uint64_t start_cnt = 0;
#ifdef DYNAREC
@@ -90,8 +97,10 @@ int box86_tokitori2 = 0;
int box86_sc3u = 0;
int box86_mapclean = 0;
int box86_zoom = 0;
int x11threads = 0;
int x11glx = 1;
int box86_x11threads = 0;
int box86_x11glx = 1;
int box86_sse_flushto0 = 0;
int box86_x87_no80bits = 0;
int allow_missing_libs = 0;
int allow_missing_symbols = 0;
int fix_64bit_inodes = 0;
@@ -103,7 +112,7 @@ int box86_nopulse = 0;
int box86_nogtk = 0;
int box86_novulkan = 0;
int box86_showsegv = 0;
char* libGL = NULL;
char* box86_libGL = NULL;
uintptr_t trace_start = 0, trace_end = 0;
char* trace_func = NULL;
uint32_t default_fs = 0;
@@ -113,11 +122,11 @@ int box86_tcmalloc_minimal = 0;
FILE* ftrace = NULL;
int ftrace_has_pid = 0;
void openFTrace()
void openFTrace(const char* newtrace)
{
char* t = getenv("BOX86_TRACE_FILE");
const char* t = newtrace?newtrace:getenv("BOX86_TRACE_FILE");
char tmp[500];
char* p = t;
const char* p = t;
if(p && strstr(t, "%pid")) {
int next = 0;
do {
@@ -158,12 +167,13 @@ void my_child_fork()
if(ftrace_has_pid) {
// open a new ftrace...
fclose(ftrace);
openFTrace();
openFTrace(NULL);
}
}
#ifdef DYNAREC
int getNCpu();
const char* getCpuName();
#ifdef DYNAREC
void GatherDynarecExtensions()
{
if(box86_dynarec==0) // no need to check if no dynarec
@@ -222,9 +232,7 @@ void GatherDynarecExtensions()
if(arm_div)
printf_log(LOG_INFO, " IDIVA");
printf_log(LOG_INFO, " PageSize:%d", box86_pagesize);
int ncpu = getNCpu();
printf_log(LOG_INFO, " Cores:%d\n", ncpu);
printf_log(LOG_INFO, " PageSize:%zd ", box86_pagesize);
#endif
}
#endif
@@ -242,7 +250,7 @@ void LoadLogEnv()
}
}
// grab BOX86_TRACE_FILE envvar, and change %pid to actual pid is present in the name
openFTrace();
openFTrace(NULL);
//box86_log = isatty(fileno(ftrace))?LOG_INFO:LOG_NONE; //default LOG value different if stdout is redirected or not
p = getenv("BOX86_LOG");
if(p) {
@@ -271,17 +279,20 @@ void LoadLogEnv()
}
p = getenv("BOX86_ROLLING_LOG");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[0]<='1')
cycle_log = p[0]-'0';
}
int cycle = 0;
if(sscanf(p, "%d", &cycle)==1)
cycle_log = cycle;
if(cycle_log==1)
cycle_log = 16;
if(cycle_log<0)
cycle_log = 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);
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) {
@@ -345,6 +356,18 @@ void LoadLogEnv()
else if (box86_dynarec_bigblock>1)
printf_log(LOG_INFO, "Dynarec will try to make bigger blocks\n");
}
p = getenv("BOX86_DYNAREC_FORWARD");
if(p) {
int val = -1;
if(sscanf(p, "%d", &val)==1) {
if(val>=0)
box86_dynarec_forward = val;
}
if(box86_dynarec_forward)
printf_log(LOG_INFO, "Dynarec will continue block for %d bytes on forward jump\n", box86_dynarec_forward);
else
printf_log(LOG_INFO, "Dynarec will not continue block on forward jump\n");
}
p = getenv("BOX86_DYNAREC_STRONGMEM");
if(p) {
if(strlen(p)==1) {
@@ -372,6 +395,15 @@ void LoadLogEnv()
if(!box86_dynarec_fastnan)
printf_log(LOG_INFO, "Dynarec will try to normalize generated NAN\n");
}
p = getenv("BOX86_DYNAREC_FASTROUND");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[0]<='1')
box86_dynarec_fastround = p[0]-'0';
}
if(!box86_dynarec_fastround)
printf_log(LOG_INFO, "Dynarec will try to generate x86 precise IEEE->int rounding\n");
}
p = getenv("BOX86_DYNAREC_SAFEFLAGS");
if(p) {
if(strlen(p)==1) {
@@ -383,6 +415,27 @@ void LoadLogEnv()
else
printf_log(LOG_INFO, "Dynarec will play %s safe with x86 flags\n", (box86_dynarec_safeflags==1)?"moderatly":"it");
}
p = getenv("BOX86_DYNAREC_HOTPAGE");
if(p) {
int val = -1;
if(sscanf("%d", p, &val)==1) {
if(val>=0)
box86_dynarec_hotpage = val;
}
if(!box86_dynarec_hotpage)
printf_log(LOG_INFO, "Dynarec will have HotPage tagged for %d attempts\n", box86_dynarec_hotpage);
else
printf_log(LOG_INFO, "Dynarec will not tag HotPage\n");
}
p = getenv("BOX86_DYNAREC_BLEEDING_EDGE");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[0]<='1')
box86_dynarec_bleeding_edge = p[0]-'0';
}
if(!box86_dynarec_bleeding_edge)
printf_log(LOG_INFO, "Dynarec will not detect MonoBleedingEdge\n");
}
p = getenv("BOX86_NODYNAREC");
if(p) {
if (strchr(p,'-')) {
@@ -458,31 +511,31 @@ void LoadLogEnv()
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[0]<='0'+1)
x11threads = p[0]-'0';
box86_x11threads = p[0]-'0';
}
if(x11threads)
if(box86_x11threads)
printf_log(LOG_INFO, "Try to Call XInitThreads if libX11 is loaded\n");
}
p = getenv("BOX86_X11GLX");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[0]<='0'+1)
x11glx = p[0]-'0';
box86_x11glx = p[0]-'0';
}
if(x11glx)
if(box86_x11glx)
printf_log(LOG_INFO, "Hack to force libX11 GLX extension present\n");
else
printf_log(LOG_INFO, "Disabled Hack to force libX11 GLX extension present\n");
}
p = getenv("BOX86_LIBGL");
if(p)
libGL = box_strdup(p);
if(!libGL) {
box86_libGL = box_strdup(p);
if(!box86_libGL) {
p = getenv("SDL_VIDEO_GL_DRIVER");
if(p)
libGL = box_strdup(p);
box86_libGL = box_strdup(p);
}
if(libGL) {
if(box86_libGL) {
printf_log(LOG_INFO, "BOX86 using \"%s\" as libGL.so.1\n", p);
}
p = getenv("BOX86_ALLOWMISSING_LIBS");
@@ -559,13 +612,13 @@ void LoadLogEnv()
if(box86_showsegv)
printf_log(LOG_INFO, "Show Segfault signal even if a signal handler is present\n");
}
p = getenv("BOX86_BACKTRACE");
p = getenv("BOX86_SHOWBT");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[0]<='0'+1)
box86_backtrace = p[0]-'0';
box86_showbt = p[0]-'0';
}
if(box86_backtrace)
if(box86_showbt)
printf_log(LOG_INFO, "Show Backtrace for signals\n");
}
box86_pagesize = sysconf(_SC_PAGESIZE);
@@ -574,6 +627,9 @@ void LoadLogEnv()
#ifdef DYNAREC
GatherDynarecExtensions();
#endif
int ncpu = getNCpu();
const char* cpuname = getCpuName();
printf_log(LOG_INFO, "Running on %s with %d Cores\n", cpuname, ncpu);
}
EXPORTDYN
@@ -602,9 +658,11 @@ int CountEnv(char** env)
char** p = env;
int c = 0;
while(*p) {
if(strncmp(*p, "BOX86_", 6)!=0)
//if(!(strncmp(*p, "PATH=", 5)==0 || strncmp(*p, "LD_LIBRARY_PATH=", 16)==0))
++c;
if(strncmp(*p, "BOX86_PATH=", 11)==0) {
} else if(strncmp(*p, "BOX86_LD_LIBRARY_PATH=", 22)==0) {
} else if(strncmp(*p, "BOX86_", 6)!=0) {
++c;
}
++p;
}
return c+2;
@@ -612,14 +670,11 @@ int CountEnv(char** env)
EXPORTDYN
int GatherEnv(char*** dest, char** env, const char* prog)
{
// Add all but BOX86_* environnement
// but add 2 for default BOX86_PATH and BOX86_LD_LIBRARY_PATH
// Add every BOX86_* environment variables
char** p = env;
int idx = 0;
int box86_path = 0;
int box86_ld_path = 0;
char* path = NULL;
char* ld_path = NULL;
while(*p) {
if(strncmp(*p, "BOX86_PATH=", 11)==0) {
(*dest)[idx++] = box_strdup(*p);
@@ -627,27 +682,19 @@ int GatherEnv(char*** dest, char** env, const char* prog)
} else if(strncmp(*p, "BOX86_LD_LIBRARY_PATH=", 22)==0) {
(*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++] = box_strdup(tmp);*/
} else if(strncmp(*p, "BOX86_", 6)!=0) {
(*dest)[idx++] = box_strdup(*p);
/*if(!(strncmp(*p, "PATH=", 5)==0 || strncmp(*p, "LD_LIBRARY_PATH=", 16)==0)) {
}*/
}
++p;
}
// update the calloc of envv when adding new variables here
// Add default values for BOX86_PATH and BOX86_LD_LIBRARY_PATH
if(!box86_path) {
(*dest)[idx++] = box_strdup("BOX86_PATH=.:bin");
}
if(!box86_ld_path) {
(*dest)[idx++] = box_strdup("BOX86_LD_LIBRARY_PATH=.:lib");
}
// add "_=prog" at the end...
// Add "_=prog" at the end...
if(prog) {
int l = strlen(prog);
char tmp[l+3];
@@ -726,7 +773,7 @@ void addNewEnvVar(const char* s)
char* p = box_strdup(s);
char* e = strchr(p, '=');
if(!e) {
printf_log(LOG_INFO, "Invalid speicifc env. var. '%s'\n", s);
printf_log(LOG_INFO, "Invalid specific env. var. '%s'\n", s);
box_free(p);
return;
}
@@ -739,22 +786,21 @@ void addNewEnvVar(const char* s)
EXPORTDYN
void LoadEnvVars(box86context_t *context)
{
char *p;
// Check custom env. var. and add them if needed
{
char* p = getenv("BOX86_ENV");
if(p)
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);
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);
}
++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
@@ -795,46 +841,37 @@ void LoadEnvVars(box86context_t *context)
AddPath("libssl.so.1.0.0", &context->box86_emulated_libs, 0);
AddPath("libcrypto.so.1", &context->box86_emulated_libs, 0);
AddPath("libcrypto.so.1.0.0", &context->box86_emulated_libs, 0);
if(getenv("BOX86_PREFER_WRAPPED")) {
if (strcmp(getenv("BOX86_PREFER_WRAPPED"), "1")==0) {
box86_prefer_wrapped = 1;
printf_log(LOG_INFO, "BOX86: Prefer Wrapped libs\n");
}
}
if(getenv("BOX86_PREFER_EMULATED")) {
if (strcmp(getenv("BOX86_PREFER_EMULATED"), "1")==0) {
box86_prefer_emulated = 1;
printf_log(LOG_INFO, "BOX86: Prefer Emulated libs\n");
}
}
if(getenv("BOX86_NOSIGSEGV")) {
if (strcmp(getenv("BOX86_NOSIGSEGV"), "1")==0) {
context->no_sigsegv = 1;
printf_log(LOG_INFO, "BOX86: Disabling handling of SigSEGV\n");
}
}
if(getenv("BOX86_NOSIGILL")) {
if (strcmp(getenv("BOX86_NOSIGILL"), "1")==0) {
context->no_sigill = 1;
printf_log(LOG_INFO, "BOX86: Disabling handling of SigILL\n");
}
}
// check BOX86_PATH and load it
LoadEnvPath(&context->box86_path, ".:bin", "BOX86_PATH");
if(getenv("PATH"))
AppendList(&context->box86_path, getenv("PATH"), 1); // in case some of the path are for x86 world
#define READENV(v, name, dest, eqn) \
do { \
p = getenv(name); \
if (p) { \
if (!strcmp(p, v)) { \
dest = 1; \
eqn; \
} \
} \
} while (0)
#define READENV0(name, dest, eqn) READENV("0", name, dest, eqn)
#define READENV1(name, dest, log) READENV("1", name, dest, printf_log(LOG_INFO, log))
READENV1("BOX86_SSE_FLUSHTO0", box86_sse_flushto0, "BOX86: Direct apply of SSE Flush to 0 flag\n");
READENV1("BOX86_X87_NO80BITS", box86_x87_no80bits, "BOX86: all 80bits x87 long double will be handle as double\n");
READENV1("BOX86_PREFER_WRAPPED", box86_prefer_wrapped, "BOX86: Prefer Wrapped libs\n");
READENV1("BOX86_PREFER_EMULATED", box86_prefer_emulated, "BOX86: Prefer Emulated libs\n");
READENV1("BOX86_NOSIGSEGV", context->no_sigsegv, "BOX86: Disabling handling of SigSEGV\n");
READENV1("BOX86_NOSIGILL", context->no_sigill, "BOX86: Disabling handling of SigILL\n");
#ifdef HAVE_TRACE
char* p = getenv("BOX86_TRACE");
if(p) {
if (strcmp(p, "0"))
context->x86trace = 1;
}
p = getenv("BOX86_TRACE_INIT");
if(p) {
if (strcmp(p, "0"))
context->x86trace = 1;
}
p = getenv("BOX86_TRACE");
if(p && strcmp(p, "0")) {
context->x86trace = 1;
box86_trace = p;
};
READENV0("BOX86_TRACE_INIT", context->x86trace, trace_init = p);
if(my_context->x86trace) {
printf_log(LOG_INFO, "Initializing Zydis lib\n");
if(InitX86Trace(my_context)) {
@@ -843,6 +880,9 @@ void LoadEnvVars(box86context_t *context)
}
}
#endif
#undef READENV
#undef READENV0
#undef READENV1
#ifdef BUILD_LIB
context->argc = 1; // need 1
context->argv = (char**)box_malloc(sizeof(char*));
@@ -854,7 +894,7 @@ EXPORTDYN
void setupTraceInit(box86context_t* context)
{
#ifdef HAVE_TRACE
char* p = getenv("BOX86_TRACE_INIT");
char* p = trace_init;
if(p) {
setbuf(stdout, NULL);
uintptr_t trace_start=0, trace_end=0;
@@ -877,11 +917,13 @@ void setupTraceInit(box86context_t* context)
}
}
} else {
p = getenv("BOX86_TRACE");
p = box86_trace;
if(p)
if (strcmp(p, "0"))
SetTraceEmu(0, 1);
}
#else
(void)context;
#endif
}
@@ -889,7 +931,7 @@ EXPORTDYN
void setupTrace(box86context_t* context)
{
#ifdef HAVE_TRACE
char* p = getenv("BOX86_TRACE");
char* p = box86_trace;
if(p) {
setbuf(stdout, NULL);
uintptr_t trace_start=0, trace_end=0;
@@ -918,10 +960,14 @@ 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
if(trace_func)
box_free(trace_func);
trace_func = box_strdup(p);
}
}
}
#else
(void)context;
#endif
}
@@ -940,7 +986,7 @@ void endBox86()
FreeLibrarian(&my_context->maplib, emu); // unload all libs
// waiting for all thread except this one to finish
int this_thread = GetTID();
int pid = getpid();
// int pid = getpid();
int running = 1;
int attempt = 0;
printf_log(LOG_DEBUG, "Waiting for all threads to finish before unloading box86context\n");
@@ -978,9 +1024,27 @@ void endBox86()
}
// all done, free context
FreeBox86Context(&my_context);
if(libGL) {
box_free(libGL);
libGL = NULL;
if(box86_libGL) {
box_free(box86_libGL);
box86_libGL = NULL;
}
}
static void load_rcfiles()
{
if(FileExist("/etc/box86.box86rc", IS_FILE))
LoadRCFile("/etc/box86.box86rc");
#ifdef PANDORA
if(FileExist("/mnt/utmp/codeblocks/usr/etc/box86.box86rc", IS_FILE))
LoadRCFile("/mnt/utmp/codeblocks/usr/etc/box86.box86rc");
#endif
char* p = getenv("HOME");
if(p) {
char tmp[4096];
strncpy(tmp, p, 4096);
strncat(tmp, "/.box86rc", 4095);
if(FileExist(tmp, IS_FILE))
LoadRCFile(tmp);
}
}
@@ -1057,6 +1121,9 @@ int main(int argc, const char **argv, char **env)
// check BOX86_LOG debug level
LoadLogEnv();
if(!getenv("BOX64_NORCFILES")) {
load_rcfiles();
}
char* bashpath = NULL;
{
char* p = getenv("BOX86_BASH");
@@ -1169,8 +1236,8 @@ int main(int argc, const char **argv, char **env)
// prepare all other env. var
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**)box_calloc(my_context->envc+4, sizeof(char*));
// allocate extra space for the new environment variable _ and the null terminator
my_context->envv = (char**)box_calloc(my_context->envc+2, sizeof(char*));
GatherEnv(&my_context->envv, environ?environ:env, my_context->box86path);
if(box86_dump) {
for (int i=0; i<my_context->envc; ++i)
@@ -1224,44 +1291,17 @@ int main(int argc, const char **argv, char **env)
if(box86_wine) {
AddPath("libdl.so.2", &ld_preload, 0);
}
// special case for LittleInferno that use an old libvorbis
if(strstr(prgname, "LittleInferno.bin.x86")==prgname) {
printf_log(LOG_INFO, "LittleInferno detected, forcing emulated libvorbis\n");
AddPath("libvorbis.so.0", &my_context->box86_emulated_libs, 0);
}
// special case for dontstarve that use an old SDL2
if(strstr(prgname, "dontstarve")) {
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);
printf_log(LOG_INFO, "steam detected\n");
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) {
printf_log(LOG_INFO, "steam-runtime-check-requirements detected, faking All is good!\n");
exit(0); // exiting, not testing anything
}
// special case for streaming_client to use emulated libSDL2
if(strstr(prgname, "streaming_client")==prgname) {
printf_log(LOG_INFO, "streaming_client detected, using emulated libSDL2!\n");
AddPath("libSDL2-2.0.so.0", &my_context->box86_emulated_libs, 0);
AddPath("libSDL2_ttf-2.0.so.0", &my_context->box86_emulated_libs, 0);
}
// special case for UnrealLinux.bin, it doesn't like "full path resolution"
if(!strcmp(prog, "UnrealLinux.bin") && my_context->argv[0]) {
box_free(my_context->argv[0]);
@@ -1288,11 +1328,6 @@ int main(int argc, const char **argv, char **env)
printf_log(LOG_INFO, "Zoom detected, trying to use system libturbojpeg if possible\n");
box86_zoom = 1;
}
// special case for X3Reunion to use emulated libjpeg62
if(strstr(prgname, "X3R_main")) {
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");
@@ -1315,6 +1350,8 @@ int main(int argc, const char **argv, char **env)
/*if(!strcmp(prgname, "gdb")) {
exit(-1);
}*/
ApplyParams("*", &ld_preload); // [*] is a special setting for all process
ApplyParams(prgname, &ld_preload);
for(int i=1; i<my_context->argc; ++i) {
my_context->argv[i] = box_strdup(argv[i+nextarg]);
@@ -1459,7 +1496,7 @@ 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)
#if defined(RPI) || defined(RK3399) || defined(GOA_CLONE) || defined(PYRA)
// 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")) {
+39 -12
View File
@@ -98,7 +98,7 @@ GO2(tc_malloc_skip_new_handler_weak, pFL); \
GO2(tc_mallocopt, iFii); \
GO2(tc_malloc_stats, vFv); \
GO2(tc_malloc_skip_new_handler, pFL); \
GO2(tc_mallinfo, pFv); \
GO2S(tc_mallinfo, pFp); \
GO2(tc_posix_memalign, iFpLL); \
GO2(tc_realloc, pFpL); \
@@ -155,7 +155,7 @@ char* box_realpath(const char* path, char* ret)
static size_t pot(size_t l) {
size_t ret = 0;
while (l>(1<<ret)) ++ret;
while (l>(1u<<ret)) ++ret;
return 1<<ret;
}
#ifndef ANDROID
@@ -230,6 +230,7 @@ EXPORT void* my__Znwm(size_t sz) //operator new(size_t)
EXPORT void* my__ZnwmRKSt9nothrow_t(size_t sz, void* p) //operator new(size_t, std::nothrow_t const&)
{
(void)p;
return box_malloc(sz);
}
@@ -240,6 +241,7 @@ EXPORT void* my__Znam(size_t sz) //operator new[](size_t)
EXPORT void* my__ZnamRKSt9nothrow_t(size_t sz, void* p) //operator new[](size_t, std::nothrow_t const&)
{
(void)p;
return box_malloc(sz);
}
@@ -251,11 +253,13 @@ EXPORT void my__ZdaPv(void* p) //operator delete[](void*)
EXPORT void my__ZdaPvm(void* p, size_t sz) //operator delete[](void*, size_t)
{
(void)sz;
box_free(p);
}
EXPORT void my__ZdaPvmSt11align_val_t(void* p, size_t sz, size_t align) //operator delete[](void*, unsigned long, std::align_val_t)
{
(void)sz; (void)align;
box_free(p);
}
@@ -266,6 +270,7 @@ EXPORT void my__ZdlPv(void* p) //operator delete(void*)
EXPORT void my__ZdlPvm(void* p, size_t sz) //operator delete(void*, size_t)
{
(void)sz;
box_free(p);
}
@@ -276,6 +281,7 @@ EXPORT void* my__ZnwmSt11align_val_t(size_t sz, size_t align) //// operator new
EXPORT void* my__ZnwmSt11align_val_tRKSt9nothrow_t(size_t sz, size_t align, void* p) //// operator new(unsigned long, std::align_val_t, std::nothrow_t const&)
{
(void)p;
return box_memalign(align, sz);
}
@@ -286,41 +292,49 @@ EXPORT void* my__ZnamSt11align_val_t(size_t sz, size_t align) //// operator new
EXPORT void* my__ZnamSt11align_val_tRKSt9nothrow_t(size_t sz, size_t align, void* p) //// operator new[](unsigned long, std::align_val_t, std::nothrow_t const&)
{
(void)p;
return box_memalign(align, sz);
}
EXPORT void my__ZdlPvRKSt9nothrow_t(void* p, void* n) //operator delete(void*, std::nothrow_t const&)
{
(void)n;
box_free(p);
}
EXPORT void my__ZdaPvSt11align_val_tRKSt9nothrow_t(void* p, size_t align, void* n) //operator delete[](void*, std::align_val_t, std::nothrow_t const&)
{
(void)align; (void)n;
box_free(p);
}
EXPORT void my__ZdlPvmSt11align_val_t(void* p, size_t sz, size_t align) //operator delete(void*, unsigned long, std::align_val_t)
{
(void)sz; (void)align;
box_free(p);
}
EXPORT void my__ZdaPvRKSt9nothrow_t(void* p, void* n) //operator delete[](void*, std::nothrow_t const&)
{
(void)n;
box_free(p);
}
EXPORT void my__ZdaPvSt11align_val_t(void* p, size_t align) //operator delete[](void*, std::align_val_t)
{
(void)align;
box_free(p);
}
EXPORT void my__ZdlPvSt11align_val_t(void* p, size_t align) //operator delete(void*, std::align_val_t)
{
(void)align;
box_free(p);
}
EXPORT void my__ZdlPvSt11align_val_tRKSt9nothrow_t(void* p, size_t align, void* n) //operator delete(void*, std::align_val_t, std::nothrow_t const&)
{
(void)align; (void)n;
box_free(p);
}
@@ -346,11 +360,13 @@ EXPORT void my_tc_deletearray(void* p)
EXPORT void my_tc_deletearray_nothrow(void* p, void* n)
{
(void)n;
box_free(p);
}
EXPORT void my_tc_delete_nothrow(void* p, void* n)
{
(void)n;
box_free(p);
}
@@ -376,17 +392,19 @@ EXPORT void* my_tc_new(size_t s)
EXPORT void* my_tc_new_nothrow(size_t s, void* n)
{
return box_calloc(1, s);
(void)n;
return box_calloc(1, s);
}
EXPORT void* my_tc_newarray(size_t s)
{
return box_calloc(1, s);
return box_calloc(1, s);
}
EXPORT void* my_tc_newarray_nothrow(size_t s, void* n)
{
return box_calloc(1, s);
(void)n;
return box_calloc(1, s);
}
EXPORT void* my_tc_pvalloc(size_t size)
@@ -411,6 +429,7 @@ EXPORT void* my_tc_malloc_skip_new_handler_weak(size_t s)
EXPORT int my_tc_mallocopt(int param, int value)
{
(void)param; (void)value;
// ignoring...
return 1;
}
@@ -434,11 +453,11 @@ EXPORT void* my_tc_malloc_skip_new_handler(size_t s)
return box_calloc(1, s);
}
EXPORT void* my_tc_mallinfo(void)
EXPORT void* my_tc_mallinfo(void* p)
{
// ignored, returning null stuffs
static size_t faked[10] = {0};
return faked;
memset(p, 0, sizeof(size_t)*10);
return p;
}
EXPORT int my_tc_posix_memalign(void** p, size_t align, size_t size)
@@ -459,6 +478,7 @@ EXPORT void* my_tc_realloc(void* p, size_t s)
/*
EXPORT int my_tc_version(int i)
{
(void)i;
return 2;
}
*/
@@ -492,29 +512,32 @@ static void addRelocJmp(void* offs, void* where, size_t size, const char* name)
void checkHookedSymbols(lib_t *maplib, elfheader_t* h)
{
(void)maplib;
int hooked = 0;
for (size_t i=0; i<h->numDynSym && hooked<2; ++i) {
for (uint32_t i=0; i<h->numDynSym && hooked<2; ++i) {
const char * symname = h->DynStr+h->DynSym[i].st_name;
int bind = ELF64_ST_BIND(h->DynSym[i].st_info);
int type = ELF64_ST_TYPE(h->DynSym[i].st_info);
int vis = h->DynSym[i].st_other&0x3;
if((type==STT_FUNC)
&& (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) {
uintptr_t offs = h->DynSym[i].st_value + h->delta;
// uintptr_t offs = h->DynSym[i].st_value + h->delta;
size_t sz = h->DynSym[i].st_size;
if(bind!=STB_LOCAL && bind!=STB_WEAK && sz>=sizeof(simple_jmp_t)) {
#define GO(A, B) if(!strcmp(symname, #A)) ++hooked;
#define GO2(A, B)
#define GO2S(A, B)
SUPER()
#undef GO
#undef GO2
#undef GO2S
}
}
}
if(hooked<2)
return; // only redirect on lib that hooked / redefined the operators
printf_log(LOG_INFO, "Redirecting overriden malloc function for %s\n", ElfName(h));
for (size_t i=0; i<h->numDynSym; ++i) {
for (uint32_t i=0; i<h->numDynSym; ++i) {
const char * symname = h->DynStr+h->DynSym[i].st_name;
int bind = ELF64_ST_BIND(h->DynSym[i].st_info);
int type = ELF64_ST_TYPE(h->DynSym[i].st_info);
@@ -526,14 +549,18 @@ void checkHookedSymbols(lib_t *maplib, elfheader_t* h)
if(bind!=STB_LOCAL && bind!=STB_WEAK) {
#define GO(A, B) if(!strcmp(symname, "__libc_" #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, A, 0, #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, #A);}
#define GO2(A, B)
#define GO2S(A, B)
SUPER()
#undef GO
#undef GO2
#undef GO2S
#define GO(A, B) if(!strcmp(symname, #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, A, 0, #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, #A);}
#define GO2(A, B) if(!strcmp(symname, #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, my_##A, 0, #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, #A);}
#define GO2S(A, B) if(!strcmp(symname, #A)) {uintptr_t alt = AddCheckBridge(my_context->system, B, my_##A, 4, #A); printf_log(LOG_DEBUG, "Redirecting %s function from %p (%s)\n", symname, (void*)offs, ElfName(h)); addRelocJmp((void*)offs, (void*)alt, sz, #A);}
SUPER()
#undef GO
#undef GO2
#undef GO2S
}
}
}
@@ -552,4 +579,4 @@ void init_malloc_hook() {
#endif
}
#undef SUPER
#undef SUPER
+47 -41
View File
@@ -42,9 +42,9 @@ brick_t* NewBrick(void* old)
brick_t* ret = (brick_t*)box_calloc(1, sizeof(brick_t));
if(old)
old = old + NBRICK * sizeof(onebridge_t);
void* ptr = my_mmap(thread_get_emu(), old, NBRICK * sizeof(onebridge_t), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
void* ptr = my_mmap(NULL, old, NBRICK * sizeof(onebridge_t), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(ptr == MAP_FAILED)
ptr = my_mmap(thread_get_emu(), NULL, NBRICK * sizeof(onebridge_t), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
ptr = my_mmap(NULL, NULL, NBRICK * sizeof(onebridge_t), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(ptr == MAP_FAILED) {
printf_log(LOG_NONE, "Warning, cannot allocate 0x%x aligned bytes for bridge, will probably crash later\n", NBRICK*sizeof(onebridge_t));
}
@@ -71,14 +71,13 @@ void FreeBridge(bridge_t** bridge)
*bridge = NULL;
brick_t *b = br->head;
x86emu_t* emu = thread_get_emu();
while(b) {
brick_t *n = b->next;
#ifdef DYNAREC
if(getProtection((uintptr_t)b->b)&(PROT_DYNAREC|PROT_DYNAREC_R))
unprotectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t), 0);
#endif
my_munmap(emu, b->b, NBRICK*sizeof(onebridge_t));
my_munmap(NULL, b->b, NBRICK*sizeof(onebridge_t));
box_free(b);
b = n;
}
@@ -95,27 +94,21 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
if(!bridge) return 0;
brick_t *b = NULL;
int sz = -1;
mutex_lock(&my_context->mutex_bridge);
b = bridge->last;
if(b->sz == NBRICK) {
b->next = NewBrick(b->b);
b = b->next;
bridge->last = b;
}
sz = b->sz;
#ifdef DYNAREC
int prot = 0;
do {
#endif
pthread_mutex_lock(&my_context->mutex_bridge);
b = bridge->last;
if(b->sz == NBRICK) {
b->next = NewBrick(b->b);
b = b->next;
bridge->last = b;
}
sz = b->sz;
#ifdef DYNAREC
pthread_mutex_unlock(&my_context->mutex_bridge);
if(box86_dynarec) {
prot=(getProtection((uintptr_t)&b->b[sz])&(PROT_DYNAREC|PROT_DYNAREC_R))?1:0;
if(prot)
unprotectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t), 0); // don't mark blocks, it's only new one
}
} while(sz!=b->sz); // this while loop if someone took the slot when the bridge mutex was unlocked doing memory protection managment
pthread_mutex_lock(&my_context->mutex_bridge);
if(box86_dynarec) {
int prot = 0;
prot=(getProtection((uintptr_t)&b->b[sz])&(PROT_DYNAREC|PROT_DYNAREC_R))?1:0;
if(prot)
unprotectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t), 0); // don't mark blocks, it's only new one
}
#endif
b->sz++;
b->b[sz].CC = 0xCC;
@@ -128,16 +121,17 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
int ret;
khint_t k = kh_put(bridgemap, bridge->bridgemap, (uintptr_t)fnc, &ret);
kh_value(bridge->bridgemap, k) = (uintptr_t)&b->b[sz].CC;
pthread_mutex_unlock(&my_context->mutex_bridge);
#ifdef DYNAREC
// only reprotect the block when stuffs are running
if(!my_context->deferedInit && box86_dynarec)
#ifdef DYNAREC
if(box86_dynarec)
protectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
#endif
#ifdef HAVE_TRACE
#endif
mutex_unlock(&my_context->mutex_bridge);
#ifdef HAVE_TRACE
if(name)
addBridgeName(fnc, name);
#endif
#else
(void)name;
#endif
return (uintptr_t)&b->b[sz].CC;
}
@@ -145,12 +139,21 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
uintptr_t CheckBridged(bridge_t* bridge, void* fnc)
{
// check if function alread have a bridge (the function wrapper will not be tested)
if (!fnc) return 0;
khint_t k = kh_get(bridgemap, bridge->bridgemap, (uint32_t)fnc);
if(k==kh_end(bridge->bridgemap))
return 0;
return kh_value(bridge->bridgemap, k);
}
int IsBridge(void* fnc) {
onebridge_t *b = (onebridge_t*)fnc;
if(!b || b->CC != 0xCC || b->S!='S' || b->C!='C' || (b->C3!=0xC3 && b->C3!=0xC2)) {
return 0;
}
return 1;
}
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name)
{
if(!fnc && w)
@@ -171,10 +174,12 @@ uintptr_t AddAutomaticBridge(x86emu_t* emu, bridge_t* bridge, wrapper_t w, void*
if(!hasAlternate(fnc)) {
printf_log(LOG_DEBUG, "Adding AutomaticBridge for %p to %p\n", fnc, (void*)ret);
addAlternate(fnc, (void*)ret);
#ifdef DYNAREC
#ifdef DYNAREC
// now, check if dynablock at native address exist
DBAlternateBlock(emu, (uintptr_t)fnc, ret);
#endif
#else
(void)emu;
#endif
}
return ret;
}
@@ -205,18 +210,19 @@ void* GetNativeFnc(uintptr_t fnc)
#undef PK
#undef PK32
// check if bridge exist
onebridge_t *b = (onebridge_t*)fnc;
if(b->CC != 0xCC || b->S!='S' || b->C!='C' || (b->C3!=0xC3 && b->C3!=0xC2))
return NULL; // not a bridge?!
return (void*)b->f;
if (IsBridge((void*)fnc)) {
return (void*)((onebridge_t*)fnc)->f;
}
return NULL;
}
void* GetNativeFncOrFnc(uintptr_t fnc)
{
onebridge_t *b = (onebridge_t*)fnc;
if(b->CC != 0xCC || b->S!='S' || b->C!='C' || (b->C3!=0xC3 && b->C3!=0xC2))
return (void*)fnc; // not a bridge?!
return (void*)b->f;
if (IsBridge((void*)fnc)) {
return (void*)((onebridge_t*)fnc)->f;
} else {
return (void*)fnc;
}
}
#ifdef HAVE_TRACE
+50
View File
@@ -13,9 +13,58 @@
#include "box86stack.h"
#include "dynarec.h"
EXPORTDYN
uint32_t RunSafeFunction(box86context_t *context, uintptr_t fnc, int nargs, ...)
{
(void)context;
x86emu_t *emu = thread_get_emu();
Push(emu, R_EBP); // push rbp
uintptr_t old_ebp = R_EBP = R_ESP; // mov rbp, rsp
Push(emu, R_EDI);
Push(emu, R_ESI);
Push(emu, R_EDX);
Push(emu, R_ECX);
Push(emu, R_EBX);
Push(emu, R_EAX);
R_ESP -= nargs*4; // need to push in reverse order
uint32_t *p = (uint32_t*)R_ESP;
va_list va;
va_start (va, nargs);
for (int i=0; i<nargs; ++i) {
*p = va_arg(va, uint32_t);
p++;
}
va_end (va);
uintptr_t oldip = R_EIP;
DynaCall(emu, fnc);
R_ESP+=(nargs*4);
uint32_t ret = R_EAX;
R_EIP = oldip;
R_EAX = Pop(emu);
R_EBX = Pop(emu);
R_ECX = Pop(emu);
R_EDX = Pop(emu);
R_ESI = Pop(emu);
R_EDI = Pop(emu);
R_ESP = old_ebp; // mov rsp, rbp
R_EBP = Pop(emu); // pop rbp
return ret;
}
EXPORTDYN
uint32_t RunFunction(box86context_t *context, uintptr_t fnc, int nargs, ...)
{
(void)context;
x86emu_t *emu = thread_get_emu();
R_ESP -= nargs*4; // need to push in reverse order
@@ -41,6 +90,7 @@ uint32_t RunFunction(box86context_t *context, uintptr_t fnc, int nargs, ...)
EXPORTDYN
uint64_t RunFunction64(box86context_t *context, uintptr_t fnc, int nargs, ...)
{
(void)context;
x86emu_t *emu = thread_get_emu();
R_ESP -= nargs*4; // need to push in reverse order
+14 -1
View File
@@ -132,7 +132,20 @@ const char* GetTmpDir() {
return "/tmp"; // meh...
}
#if defined(RPI) || defined(RK3399) || defined(GOA_CLONE)
char* LowerCase(const char* s) {
if(!s)
return NULL;
char* ret = box_calloc(1, strlen(s)+1);
size_t i=0;
while(*s) {
ret[i++] = (*s>='A' && *s<='Z')?(*s-'A'+'a'):(*s);
++s;
}
return ret;
}
#if defined(RPI) || defined(RK3399) || defined(GOA_CLONE) || defined(PYRA)
void sanitize_mojosetup_gtk_background()
{
// get GTK2_RC_FILES folder
+1 -1
View File
@@ -1759,7 +1759,7 @@ static void* find_signal7_Fct(void* fct)
printf_log(LOG_NONE, "Warning, no more slot for GTypeInfo signal7 callback\n");
return NULL;
}
static const wrapper_t wrappers[] = {pFpp, pFppp, pFpppp, pFpppp, pFppppp, pFpppppp};
//static const wrapper_t wrappers[] = {pFpp, pFppp, pFpppp, pFpppp, pFppppp, pFpppppp};
typedef void* (*finder_t)(void*);
static const finder_t finders[] = {find_signal2_Fct, find_signal3_Fct, find_signal4_Fct, find_signal5_Fct, find_signal6_Fct, find_signal7_Fct};
#define MAX_SIGNAL_N 7
+35 -27
View File
@@ -25,9 +25,31 @@ int get_cpuMhz()
return MHz;
}
int getNCpu(); // defined in wrappedlibc.c
const char* getCpuName(); // same
void my_cpuid(x86emu_t* emu, uint32_t tmp32u)
{
static char branding[3*4*4+1] = "";
static int done = 0;
if(!done) {
done = 1;
const char* name = getCpuName();
if(strstr(name, "MHz") || strstr(name, "GHz")) {
// name already have the speed in it
snprintf(branding, 3*4*4, "Box86 on %s", name);
} else {
int MHz = get_cpuMhz();
if(MHz>15000) { // swiches to GHz display...
snprintf(branding, 3*4*4, "Box86 on %s @%1.2f GHz", name, MHz/1000.);
} else {
snprintf(branding, 3*4*4, "Box86 on %s @%04d MHz", name, MHz);
}
}
while(strlen(branding)<3*4*4) {
memmove(branding+1, branding, strlen(branding));
branding[0] = ' ';
}
}
int ncpu = getNCpu();
if(ncpu>255) ncpu = 255;
if(!ncpu) ncpu = 1;
@@ -153,37 +175,23 @@ void my_cpuid(x86emu_t* emu, uint32_t tmp32u)
R_ECX = (1<<5) | (1<<8); // LZCNT | PREFETCHW
R_EDX = 0;
break;
case 0x80000002: // Brand part 1 (P4 signature)
R_EAX = 0x20202020;
R_EBX = 0x20202020;
R_ECX = 0x20202020;
R_EDX = 0x6E492020;
case 0x80000002: // Brand part 1 (branding signature)
R_EAX = ((uint32_t*)branding)[0];
R_EBX = ((uint32_t*)branding)[1];
R_ECX = ((uint32_t*)branding)[2];
R_EDX = ((uint32_t*)branding)[3];
break;
case 0x80000003: // Brand part 2
R_EAX = 0x286C6574;
R_EBX = 0x50202952;
R_ECX = 0x69746E65;
R_EDX = 0x52286D75;
R_EAX = ((uint32_t*)branding)[4];
R_EBX = ((uint32_t*)branding)[5];
R_ECX = ((uint32_t*)branding)[6];
R_EDX = ((uint32_t*)branding)[7];
break;
case 0x80000004: // Brand part 3, with frequency
R_EAX = 0x20342029;
R_EBX = 0x20555043;
{
static int MHz = 0;
if(!MHz)
MHz = get_cpuMhz();
if(MHz>15000) { // swiches to GHz display...
char tmp[12];
sprintf(tmp, "%1.2f", MHz/1000.);
R_ECX = *(uint32_t*)tmp;
R_EDX = 0x007A4847; // GHz
} else {
char tmp[12];
sprintf(tmp, "%04d", MHz);
R_ECX = *(uint32_t*)tmp;
R_EDX = 0x007A484D; // MHz
}
}
R_EAX = ((uint32_t*)branding)[8];
R_EBX = ((uint32_t*)branding)[9];
R_ECX = ((uint32_t*)branding)[10];
R_EDX = ((uint32_t*)branding)[11];
break;
case 0x80000005:
R_EAX = 0;
+517
View File
@@ -0,0 +1,517 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include "debug.h"
#include "rcfile.h"
#include "box86context.h"
#include "pathcoll.h"
#include "fileutils.h"
#ifdef HAVE_TRACE
#include "x86trace.h"
#endif
#include "custommem.h"
#include "khash.h"
// This file handle the box86rc files
// file are basicaly ini file, with section [XXXX] defining the name of the process
// and BOX86_XXXX=YYYY entry like the env. var. variables
// list of all entries
#define SUPER1() \
ENTRYINTPOS(BOX86_ROLLING_LOG, new_cycle_log) \
ENTRYSTRING_(BOX86_LD_LIBRARY_PATH, ld_library_path) \
ENTRYSTRING_(BOX86_PATH, box86_path) \
ENTRYSTRING_(BOX86_TRACE_FILE, trace_file) \
ENTRYADDR(BOX86_LOAD_ADDR, box86_load_addr) \
ENTRYINT(BOX86_LOG, box86_log, 0, 3, 2) \
ENTRYBOOL(BOX86_DUMP, box86_dump) \
ENTRYBOOL(BOX86_DLSYM_ERROR, dlsym_error) \
CENTRYBOOL(BOX86_NOSIGSEGV, no_sigsegv) \
CENTRYBOOL(BOX86_NOSIGILL, no_sigill) \
ENTRYBOOL(BOX86_SHOWSEGV, box86_showsegv) \
ENTRYBOOL(BOX86_SHOWBT, box86_showbt) \
ENTRYBOOL(BOX86_X11THREADS, box86_x11threads) \
ENTRYBOOL(BOX86_X11GLX, box86_x11glx) \
ENTRYDSTRING(BOX86_LIBGL, box86_libGL) \
ENTRYBOOL(BOX86_SSE_FLUSHTO0, box86_sse_flushto0) \
ENTRYBOOL(BOX86_X87_NO80BITS, box86_x87_no80bits) \
ENTRYSTRING_(BOX86_EMULATED_LIBS, emulated_libs) \
ENTRYBOOL(BOX86_ALLOWMISSINGLIBS, allow_missing_libs) \
ENTRYBOOL(BOX86_ALLOWMISSING_SYMBOLS, allow_missing_symbols) \
ENTRYBOOL(BOX86_PREFER_WRAPPED, box86_prefer_wrapped) \
ENTRYBOOL(BOX86_PREFER_EMULATED, box86_prefer_emulated) \
ENTRYBOOL(BOX86_NOPULSE, box86_nopulse) \
ENTRYBOOL(BOX86_NOGTK, box86_nogtk) \
ENTRYBOOL(BOX86_NOVULKAN, box86_novulkan) \
ENTRYBOOL(BOX86_FIX_64BIT_INODES, fix_64bit_inodes) \
ENTRYSTRING_(BOX86_BASH, bash) \
ENTRYINT(BOX86_JITGDB, jit_gdb, 0, 2, 2) \
ENTRYSTRING_(BOX86_BOX64, box64) \
ENTRYSTRING_(BOX86_LD_PRELOAD, ld_preload) \
#ifdef HAVE_TRACE
#define SUPER2() \
ENTRYSTRING_(BOX86_TRACE, trace) \
ENTRYULONG(BOX86_TRACE_START, start_cnt) \
ENTRYSTRING_(BOX86_TRACE_INIT, trace_init) \
ENTRYBOOL(BOX86_TRACE_XMM, trace_xmm) \
ENTRYBOOL(BOX86_TRACE_EMM, trace_emm) \
#else
#define SUPER2() \
IGNORE(BOX86_TRACE) \
IGNORE(BOX86_TRACE_START) \
IGNORE(BOX86_TRACE_INIT) \
IGNORE(BOX86_TRACE_XMM) \
IGNORE(BOX86_TRACE_EMM) \
#endif
#ifdef DYNAREC
#define SUPER3() \
ENTRYBOOL(BOX86_DYNAREC, box86_dynarec) \
ENTRYINT(BOX86_DYNAREC_DUMP, box86_dynarec_dump, 0, 2, 2) \
ENTRYINT(BOX86_DYNAREC_LOG, box86_dynarec_log, 0, 3, 2) \
ENTRYINT(BOX86_DYNAREC_BIGBLOCK, box86_dynarec_bigblock, 0, 3, 2) \
ENTRYSTRING_(BOX86_DYNAREC_FORWARD, box86_dynarec_forward) \
ENTRYINT(BOX86_DYNAREC_STRONGMEM, box86_dynarec_strongmem, 0, 2, 2) \
ENTRYBOOL(BOX86_DYNAREC_X87DOUBLE, box86_dynarec_x87double) \
ENTRYBOOL(BOX86_DYNAREC_FASTNAN, box86_dynarec_fastnan) \
ENTRYBOOL(BOX86_DYNAREC_FASTROUND, box86_dynarec_fastround) \
ENTRYINT(BOX86_DYNAREC_SAFEFLAGS, box86_dynarec_safeflags, 0, 2, 2) \
ENTRYINT(BOX86_DYNAREC_HOTPAGE, box86_dynarec_hotpage, 0, 255, 8) \
ENTRYBOOL(BOX86_DYNAREC_BLEEDING_EDGE, box86_dynarec_bleeding_edge) \
ENTRYSTRING_(BOX86_NODYNAREC, box86_nodynarec) \
#else
#define SUPER3() \
IGNORE(BOX86_DYNAREC) \
IGNORE(BOX86_DYNAREC_DUMP) \
IGNORE(BOX86_DYNAREC_LOG) \
IGNORE(BOX86_DYNAREC_BIGBLOCK) \
IGNORE(BOX64_DYNAREC_FORWARD) \
IGNORE(BOX86_DYNAREC_STRONGMEM) \
IGNORE(BOX86_DYNAREC_X87DOUBLE) \
IGNORE(BOX86_DYNAREC_FASTNAN) \
IGNORE(BOX86_DYNAREC_FASTROUND) \
IGNORE(BOX86_DYNAREC_SAFEFLAGS) \
IGNORE(BOX86_DYNAREC_HOTPAGE) \
IGNORE(BOX86_DYNAREC_BLEEDING_EDGE) \
IGNORE(BOX86_NODYNAREC) \
#endif
#if defined(HAVE_TRACE) && defined(DYNAREC)
#define SUPER4() \
ENTRYBOOL(BOX86_DYNAREC_TRACE, box86_dynarec_trace) \
#else
#define SUPER4() \
IGNORE(BOX86_DYNAREC_TRACE) \
#endif
#ifdef PANDORA
#define SUPER5() \
ENTRYBOOL(BOX86_X11COLOR16, x11color16)
#else
#define SUPER5() \
IGNORE(BOX86_X11COLOR16)
#endif
#define SUPER() \
SUPER1() \
SUPER2() \
SUPER3() \
SUPER4() \
SUPER5()
typedef struct my_params_s {
// is present part
#define ENTRYBOOL(NAME, name) uint8_t is_##name##_present:1;
#define CENTRYBOOL(NAME, name) uint8_t is_##name##_present:1;
#define ENTRYINT(NAME, name, minval, maxval, bits) uint8_t is_##name##_present:1;
#define ENTRYINTPOS(NAME, name) uint8_t is_##name##_present:1;
#define ENTRYSTRING(NAME, name) uint8_t is_##name##_present:1;
#define ENTRYSTRING_(NAME, name) uint8_t is_##name##_present:1;
#define ENTRYDSTRING(NAME, name) uint8_t is_##name##_present:1;
#define ENTRYADDR(NAME, name) uint8_t is_##name##_present:1;
#define ENTRYULONG(NAME, name) uint8_t is_##name##_present:1;
#define IGNORE(NAME)
SUPER()
// done
#undef ENTRYBOOL
#undef CENTRYBOOL
#undef ENTRYINT
#undef ENTRYINTPOS
#undef ENTRYSTRING
#undef ENTRYSTRING_
#undef ENTRYDSTRING
#undef ENTRYADDR
#undef ENTRYULONG
// the actual fields
#define ENTRYBOOL(NAME, name) uint8_t name:1;
#define CENTRYBOOL(NAME, name) uint8_t name:1;
#define ENTRYINT(NAME, name, minval, maxval, bits) uint8_t name:bits;
#define ENTRYINTPOS(NAME, name) uint32_t name;
#define ENTRYSTRING(NAME, name) char* name;
#define ENTRYSTRING_(NAME, name) char* name;
#define ENTRYDSTRING(NAME, name) char* name;
#define ENTRYADDR(NAME, name) uintptr_t name;
#define ENTRYULONG(NAME, name) uint64_t name;
SUPER()
// done
#undef ENTRYBOOL
#undef CENTRYBOOL
#undef ENTRYINT
#undef ENTRYINTPOS
#undef ENTRYSTRING
#undef ENTRYSTRING_
#undef ENTRYDSTRING
#undef ENTRYADDR
#undef ENTRYULONG
} my_params_t;
KHASH_MAP_INIT_STR(params, my_params_t)
static kh_params_t *params = NULL;
#ifdef PANDORA
extern int x11color16;
#endif
extern int fix_64bit_inodes;
static void clearParam(my_params_t* param)
{
#define ENTRYBOOL(NAME, name)
#define CENTRYBOOL(NAME, name)
#define ENTRYINT(NAME, name, minval, maxval, bits)
#define ENTRYINTPOS(NAME, name)
#define ENTRYSTRING(NAME, name) free(param->name);
#define ENTRYSTRING_(NAME, name) free(param->name);
#define ENTRYDSTRING(NAME, name) free(param->name);
#define ENTRYADDR(NAME, name)
#define ENTRYULONG(NAME, name)
SUPER()
#undef ENTRYBOOL
#undef CENTRYBOOL
#undef ENTRYINT
#undef ENTRYINTPOS
#undef ENTRYSTRING
#undef ENTRYSTRING_
#undef ENTRYDSTRING
#undef ENTRYADDR
#undef ENTRYULONG
}
static void addParam(const char* name, my_params_t* param)
{
khint_t k;
k = kh_get(params, params, name);
if(k==kh_end(params)) {
int ret;
k = kh_put(params, params, strdup(name), &ret);
} else {
clearParam(&kh_value(params, k));
}
my_params_t *p = &kh_value(params, k);
memcpy(p, param, sizeof(my_params_t));
}
static void trimString(char* s)
{
if(!s)
return;
// trim right space/tab
size_t len = strlen(s);
while(len && (s[len-1]==' ' || s[len-1]=='\t' || s[len-1]=='\n'))
s[--len] = '\0';
// trim left space/tab
while(s[0]==' ' || s[0]=='\t')
memmove(s, s+1, strlen(s));
}
void LoadRCFile(const char* filename)
{
FILE *f = fopen(filename, "r");
if(!f) {
printf_log(LOG_INFO, "Cannot open RC file %s\n", filename);
return;
}
// init the hash table if needed
if(!params)
params = kh_init(params);
// prepare to parse the file
char* line = NULL;
size_t lsize = 0;
my_params_t current_param = {0};
char* current_name = NULL;
int dummy;
size_t len;
char* p;
// parsing
while ((dummy = getline(&line, &lsize, f)) != -1) {
// remove comments
if((p=strchr(line, '#')))
*p = '\0';
trimString(line);
len = strlen(line);
// check the line content
if(line[0]=='[' && strchr(line, ']')) {
// new entry, will need to add current one
if(current_name)
addParam(current_name, &current_param);
// prepare a new entry
memset(&current_param, 0, sizeof(current_param));
free(current_name);
current_name = LowerCase(line+1);
*strchr(current_name, ']') = '\0';
trimString(current_name);
} else if(strchr(line, '=')) {
// actual parameters
//get the key and val
char* key = line;
char* val = strchr(key, '=')+1;
*strchr(key, '=') = '\0';
trimString(key);
trimString(val);
// extract, check and set arg
#define ENTRYBOOL(NAME, name) ENTRYINT(NAME, name, 0, 1, 1)
#define CENTRYBOOL(NAME, name) ENTRYBOOL(NAME, name)
#define ENTRYINT(NAME, name, minval, maxval, bits) \
else if(!strcmp(key, #NAME)) { \
int v = strtol(val, &p, 0); \
if(p!=val && v>=minval && v<=maxval) { \
current_param.is_##name##_present = 1; \
current_param.name = v; \
} \
}
#define ENTRYINTPOS(NAME, name) \
else if(!strcmp(key, #NAME)) { \
int v = strtol(val, &p, 0); \
if(p!=val) { \
current_param.is_##name##_present = 1; \
current_param.name = v; \
} \
}
#define ENTRYSTRING(NAME, name) \
else if(!strcmp(key, #NAME)) { \
current_param.is_##name##_present = 1; \
if(current_param.name) free(current_param.name); \
current_param.name = strdup(val); \
}
#define ENTRYSTRING_(NAME, name) ENTRYSTRING(NAME, name)
#define ENTRYDSTRING(NAME, name) ENTRYSTRING(NAME, name)
#define ENTRYADDR(NAME, name) \
else if(!strcmp(key, #NAME)) { \
uintptr_t v = strtoul(val, &p, 0); \
if(p!=val) { \
current_param.is_##name##_present = 1; \
current_param.name = v; \
} \
}
#define ENTRYULONG(NAME, name) \
else if(!strcmp(key, #NAME)) { \
uint64_t v = strtoull(val, &p, 0); \
if(p!=val) { \
current_param.is_##name##_present = 1; \
current_param.name = v; \
} \
}
#undef IGNORE
#define IGNORE(NAME) else if(!strcmp(key, #NAME)) ;
if(0) ;
SUPER()
else if(len && current_name) {
printf_log(LOG_INFO, "Warning, unsupported %s=%s for [%s] in %s", key, val, current_name, filename);
}
#undef ENTRYBOOL
#undef CENTRYBOOL
#undef ENTRYINT
#undef ENTRYINTPOS
#undef ENTRYSTRING
#undef ENTRYSTRING_
#undef ENTRYDSTRING
#undef ENTRYADDR
#undef ENTRYULONG
#undef IGNORE
#define IGNORE(NAME)
}
}
// last entry to be pushed too
if(current_name)
addParam(current_name, &current_param);
free(line);
printf_log(LOG_INFO, "Params database has %d entries\n", kh_size(params));
}
void DeleteParams()
{
if(!params)
return;
// free strings
my_params_t* p;
// need to free duplicated strings
kh_foreach_value_ref(params, p, clearParam(p));
const char* key;
kh_foreach_key(params, key, free((void*)key));
// free the hash itself
kh_destroy(params, params);
params = NULL;
}
extern int ftrace_has_pid;
void openFTrace(const char* newtrace);
#ifdef DYNAREC
void GatherDynarecExtensions();
#endif
#ifdef HAVE_TRACE
void setupTraceInit();
void setupTrace();
#endif
void ApplyParams(const char* name, path_collection_t* preload)
{
if(!name || !params)
return;
static const char* old_name = NULL;
int new_cycle_log = cycle_log;
if(old_name && !strcmp(name, old_name))
return;
old_name = name;
khint_t k;
{
char* lname = LowerCase(name);
k = kh_get(params, params, lname);
free(lname);
}
if(k == kh_end(params))
return;
my_params_t* param = &kh_value(params, k);
#ifdef DYNAREC
int olddynarec = box86_dynarec;
#endif
printf_log(LOG_INFO, "Apply RC params for %s\n", name);
#define ENTRYBOOL(NAME, name) ENTRYINT(NAME, name, 0, 1, 1)
#define CENTRYBOOL(NAME, name) if(param->is_##name##_present) {my_context->name = param->name; printf_log(LOG_INFO, "Applying %s=%d\n", #NAME, param->name);}
#define ENTRYINT(NAME, name, minval, maxval, bits) if(param->is_##name##_present) {name = param->name; printf_log(LOG_INFO, "Applying %s=%d\n", #NAME, param->name);}
#define ENTRYINTPOS(NAME, name) if(param->is_##name##_present) {name = param->name; printf_log(LOG_INFO, "Applying %s=%d\n", #NAME, param->name);}
#define ENTRYSTRING(NAME, name) if(param->is_##name##_present) {name = param->name; printf_log(LOG_INFO, "Applying %s=%s\n", #NAME, param->name);}
#define ENTRYSTRING_(NAME, name)
#define ENTRYDSTRING(NAME, name) if(param->is_##name##_present) {if(name) free(name); name = strdup(param->name); printf_log(LOG_INFO, "Applying %s=%s\n", #NAME, param->name);}
#define ENTRYADDR(NAME, name) if(param->is_##name##_present) {name = param->name; printf_log(LOG_INFO, "Applying %s=%zd\n", #NAME, param->name);}
#define ENTRYULONG(NAME, name) if(param->is_##name##_present) {name = param->name; printf_log(LOG_INFO, "Applying %s=%lld\n", #NAME, param->name);}
SUPER()
#undef ENTRYBOOL
#undef CENTRYBOOL
#undef ENTRYINT
#undef ENTRYINTPOS
#undef ENTRYSTRING
#undef ENTRYSTRING_
#undef ENTRYDSTRING
#undef ENTRYADDR
#undef ENTRYULONG
// now handle the manuel entry (the one with ending underscore)
if(new_cycle_log==1)
new_cycle_log = 16;
if(new_cycle_log!=cycle_log) {
freeCycleLog(my_context);
cycle_log = new_cycle_log;
initCycleLog(my_context);
}
if(param->is_ld_library_path_present) AppendList(&my_context->box86_ld_lib, param->ld_library_path, 1);
if(param->is_box86_path_present) AppendList(&my_context->box86_path, param->box86_path, 1);
if(param->is_trace_file_present) {
if(ftrace_has_pid) {
// open a new ftrace...
fclose(ftrace);
}
openFTrace(param->trace_file);
}
if(param->is_emulated_libs_present) {
AppendList(&my_context->box86_emulated_libs, param->emulated_libs, 0);
printf_log(LOG_INFO, "Applying %s=%s\n", "BOX86_EMULATED_LIBS", param->emulated_libs);
}
if(param->is_bash_present && (FileIsX86ELF(param->bash) || FileIsX64ELF(param->bash))) {
if(my_context->bashpath)
free(my_context->bashpath);
my_context->bashpath = strdup(param->bash);
printf_log(LOG_INFO, "Applying %s=%s\n", "BOX86_BASH", param->bash);
}
if(param->is_box64_present && FileExist(param->box64, IS_FILE)) {
if(my_context->box64path) {
free(my_context->box64path);
}
my_context->box64path = strdup(param->box64);
printf_log(LOG_INFO, "Applying %s=%s\n", "BOX86_BOX64", param->box64);
}
if(param->is_ld_preload_present) {
if(preload) {
printf_log(LOG_INFO, "Applying %s=%s\n", "BOX86_LD_PRELOAD", param->ld_preload);
PrependList(preload, param->ld_preload, 1);
} else {
printf_log(LOG_INFO, "Cannot Apply %s=%s\n", "BOX86_LD_PRELOAD", param->ld_preload);
}
}
#ifdef HAVE_TRACE
int old_x86trace = my_context->x86trace;
if(param->is_trace_present) {
char*p = param->trace;
if (strcmp(p, "0")) {
my_context->x86trace = 1;
box86_trace = p;
}
printf_log(LOG_INFO, "Applying %s=%s", "BOX86_TRACE", param->trace);
}
if(param->is_trace_init_present) {
char* p = param->trace_init;
if (strcmp(p, "0")) {
my_context->x86trace = 1;
trace_init = p;
}
printf_log(LOG_INFO, "Applying %s=%s", "BOX86_TRACE_INIT", param->trace_init);
}
if(my_context->x86trace && !old_x86trace) {
printf_log(LOG_INFO, "Initializing Zydis lib\n");
if(InitX86Trace(my_context)) {
printf_log(LOG_INFO, "Zydis init failed, no x86 trace activated\n");
my_context->x86trace = 0;
}
}
if(param->is_trace_init_present)
setupTraceInit();
if(param->is_trace_present)
setupTrace();
#endif
#ifdef DYNAREC
if(param->is_box86_nodynarec_present) {
uintptr_t no_start = 0, no_end = 0;
char* p;
no_start = strtoul(param->box86_nodynarec, &p, 0);
if(p!=param->box86_nodynarec) {
char* p2;
no_end = strtoul(p, &p2, 0);
if(p2!=p && no_end>no_start) {
box86_nodynarec_start = no_start;
box86_nodynarec_end = no_end;
printf_log(LOG_INFO, "Appling BOX86_NODYNAREC=%p-%p\n", (void*)box86_nodynarec_start, (void*)box86_nodynarec_end);
}
}
}
if(param->is_box86_dynarec_forward_present) {
int forward = 0;
if(sscanf(param->box86_dynarec_forward, "%d", &forward)==1) {
box86_dynarec_forward = forward;
printf_log(LOG_INFO, "Appling BOX86_DYNAREC_FORWARD=%d\n", box86_dynarec_forward);
}
}
if(!olddynarec && box86_dynarec)
GatherDynarecExtensions();
#endif
if(box86_log==3) {
box86_log = 2;
box86_dump = 1;
}
}
+123 -5
View File
@@ -68,6 +68,7 @@
#() dFG
#() lFv
#() lFi
#() lFu
#() lFl
#() lFp
#() lFG
@@ -278,6 +279,7 @@
#() vFEpV
#() vFiii
#() vFiiu
#() vFiif
#() vFiip
#() vFiII
#() vFiui
@@ -286,6 +288,7 @@
#() vFiUU
#() vFiff
#() vFidd
#() vFill
#() vFilp
#() vFipi
#() vFipu
@@ -314,6 +317,9 @@
#() vFfpp
#() vFddd
#() vFdpp
#() vFlip
#() vFllp
#() vFlpp
#() vFLpL
#() vFpii
#() vFpiI
@@ -325,14 +331,17 @@
#() vFpui
#() vFpuI
#() vFpuu
#() vFpuU
#() vFpup
#() vFpUi
#() vFpUu
#() vFpUU
#() vFpUp
#() vFpUP
#() vFpff
#() vFpdd
#() vFpll
#() vFplp
#() vFpLi
#() vFpLL
#() vFpLp
@@ -587,21 +596,27 @@
#() vFEpPp
#() vFiiii
#() vFiiip
#() vFiill
#() vFiipp
#() vFiipV
#() vFiIII
#() vFiuiu
#() vFiuip
#() vFiuuu
#() vFiuup
#() vFiulp
#() vFiupu
#() vFiupV
#() vFiUUU
#() vFifff
#() vFiddd
#() vFilil
#() vFilip
#() vFilpu
#() vFilpp
#() vFipii
#() vFipup
#() vFipll
#() vFippi
#() vFippu
#() vFippp
@@ -668,16 +683,19 @@
#() vFpuuV
#() vFpudd
#() vFpupp
#() vFpupP
#() vFpUui
#() vFpUuu
#() vFpUup
#() vFpUUi
#() vFpUUu
#() vFpUUp
#() vFpUpp
#() vFpfff
#() vFpdii
#() vFpddi
#() vFpddd
#() vFplpp
#() vFpLLL
#() vFppii
#() vFppiu
@@ -807,6 +825,7 @@
#() iFpLpL
#() iFppii
#() iFppiu
#() iFppiU
#() iFppiL
#() iFppip
#() iFppIL
@@ -859,6 +878,7 @@
#() uFpppi
#() uFpppu
#() uFpppp
#() uFpppV
#() UFpipp
#() UFppii
#() UFppip
@@ -903,12 +923,14 @@
#() pFiipi
#() pFiipp
#() pFiIIi
#() pFillu
#() pFipii
#() pFipip
#() pFipup
#() pFippi
#() pFippu
#() pFuiii
#() pFuuii
#() pFuuuu
#() pFulli
#() pFullu
@@ -962,10 +984,15 @@
#() vFEppiV
#() vFEppup
#() vFEpppp
#() vFEpPpp
#() vFiiiii
#() vFiiiiu
#() vFiiuii
#() vFiiuup
#() vFiillu
#() vFiilll
#() vFiipii
#() vFiipll
#() vFiIIII
#() vFiuiip
#() vFiuipi
@@ -976,6 +1003,8 @@
#() vFiffff
#() vFidddd
#() vFilill
#() vFilipi
#() vFilipl
#() vFipipu
#() vFipipp
#() vFipupi
@@ -985,6 +1014,7 @@
#() vFuiiiu
#() vFuiiip
#() vFuiifi
#() vFuiill
#() vFuiIII
#() vFuiuii
#() vFuiuiu
@@ -1037,6 +1067,8 @@
#() vFpiipp
#() vFpiIiI
#() vFpiIII
#() vFpiUUp
#() vFpilpp
#() vFpipii
#() vFpipiu
#() vFpuiip
@@ -1097,6 +1129,7 @@
#() iFEpipi
#() iFEpipp
#() iFEpipV
#() iFEpupU
#() iFEpupp
#() iFEpupV
#() iFEpUup
@@ -1139,6 +1172,7 @@
#() iFpiIip
#() iFpiuwp
#() iFpiupu
#() iFpiUUU
#() iFpipii
#() iFpipiL
#() iFpipip
@@ -1162,6 +1196,7 @@
#() iFpupup
#() iFpuppu
#() iFpuppp
#() iFpUiUi
#() iFplluu
#() iFpLlpp
#() iFpLLpp
@@ -1202,6 +1237,7 @@
#() uFEpppp
#() uFiuuuu
#() uFipipp
#() uFipLpp
#() uFuiiiu
#() uFpCCCC
#() uFpWuip
@@ -1299,13 +1335,20 @@
#() vFEppppp
#() vFiiiiii
#() vFiiiuil
#() vFiiilpi
#() vFiiuiil
#() vFiiuilp
#() vFiiuulp
#() vFiililp
#() vFiiplli
#() vFiiplll
#() vFiuippp
#() vFiffiff
#() vFiddidd
#() vFililll
#() vFilipli
#() vFiliplu
#() vFipiplp
#() vFipllli
#() vFuiiiii
#() vFuiiiil
@@ -1319,6 +1362,7 @@
#() vFuiuiuu
#() vFuiuuip
#() vFuiuuuu
#() vFuiuulp
#() vFuiupii
#() vFuiupiu
#() vFuiUUUU
@@ -1386,6 +1430,7 @@
#() vFppippi
#() vFppippp
#() vFppuuuu
#() vFppuUUU
#() vFppupii
#() vFppuppp
#() vFppdidd
@@ -1420,6 +1465,7 @@
#() iFEpuppp
#() iFEpUPpp
#() iFEpLppp
#() iFEpppip
#() iFEppppp
#() iFiiiiii
#() iFiiiiip
@@ -1564,8 +1610,12 @@
#() vFEpppppp
#() vFiiiiiip
#() vFiiiiuup
#() vFiiuilil
#() vFiiffffp
#() vFiipllli
#() vFiuulipi
#() vFilipliu
#() vFilulipi
#() vFuiiiiii
#() vFuiiiuip
#() vFuiiiuup
@@ -1605,6 +1655,7 @@
#() vFulipulp
#() vFulpiill
#() vFlipuiip
#() vFlliiiip
#() vFpiiiipp
#() vFpiiliip
#() vFpiipCpp
@@ -1768,6 +1819,7 @@
#() vFEippippp
#() vFEuuuuppp
#() vFEppipppp
#() vFEpppippp
#() vFEpppuipV
#() vFEpppppuu
#() vFEppppppp
@@ -1778,6 +1830,7 @@
#() vFuiiiiuup
#() vFuiuiiiii
#() vFuiuiiiip
#() vFuiuiuuuu
#() vFuiulplpp
#() vFuipuliuf
#() vFuuiiiiii
@@ -1791,6 +1844,7 @@
#() vFuuuipipp
#() vFuuuuuuuu
#() vFuuuuufff
#() vFuuufffff
#() vFulllplip
#() vFffffffff
#() vFlipuiuip
@@ -1815,6 +1869,7 @@
#() vFpppppppp
#() iFEipupupi
#() iFEpippppp
#() iFEpuiippp
#() iFEpuuiipp
#() iFEpuuuipp
#() iFEpuuLppp
@@ -1850,6 +1905,7 @@
#() uFEpppuppp
#() uFEppppppp
#() uFuipppppp
#() uFulpppppp
#() uFpupuuuCp
#() uFppuuuupp
#() uFppuuuppi
@@ -1885,10 +1941,14 @@
#() vFEpiiiiipp
#() vFEpippippp
#() vFEpippippV
#() vFEpuuuippp
#() vFEppiipppp
#() vFEpppiippp
#() vFEppppippp
#() vFiiiiiiiii
#() vFiiiiiiill
#() vFiiiiillli
#() vFiiilllilp
#() vFuiiiiiiii
#() vFuiiiiiuip
#() vFuiiiiiuup
@@ -1974,7 +2034,10 @@
#() vFEiippppppp
#() vFEpippppppp
#() vFEpppiipppp
#() vFiiiiiiiiii
#() vFiiiiiiiiiu
#() vFiiiiiiiiui
#() vFiiillliiip
#() vFippppppppp
#() vFuiiiiiiiii
#() vFuiiiiiiill
@@ -2009,7 +2072,7 @@
#() iFEppppppipp
#() iFiiiiiiiiip
#() iFpiipiiipip
#() iFpuipuppppp
#() iFpippddiidd
#() iFpuupiuiipp
#() iFpddpippppp
#() iFppipiippii
@@ -2030,6 +2093,8 @@
#() pFppuiipuuii
#() pFpppppppppp
#() vFEpiiiupupup
#() vFiiiiillliip
#() vFiiiiilllilp
#() vFiippppppppp
#() vFuiiiiiiiiip
#() vFuiiiiiiiuip
@@ -2055,6 +2120,7 @@
#() vFppipppuiiii
#() vFppipppppppp
#() vFppppppppppp
#() iFEpuipuppppp
#() iFEpuuiiuippu
#() iFEpuuuuuiipp
#() iFEpppipppppp
@@ -2134,6 +2200,7 @@
#() pFEppCuuWWwwCCup
#() pFEppuuuWWWWWWWW
#() pFpuupuupwwwwWWC
#() vFuiiiiiuiiiiilll
#() vFuuiiiiuuiiiiiii
#() vFfffffffffffffff
#() vFppipppppppppppp
@@ -2146,7 +2213,9 @@
#() vFpppppppppppppppp
#() iFpppppppppppppppp
#() pFppipipipipipipip
#() vFuuuiiiiiuiiiiilll
#() vFppiiiiddddiiiiiuu
#() vFpppuppiipppuUUUpi
#() iFppipipppppppppppp
#() iFpppippppppppppppp
#() pFppippipipipipipip
@@ -2203,9 +2272,7 @@
#() UFsvvs -> UFss
#() iFEpvpp -> iFEppp
#() iFEpvpV -> iFEppV
#() iFEpvvpV -> iFEppV
#() pFpsvvvvs -> pFpss
#() iFEpuvvppp -> iFEpuppp
#defined(NOALIGN) iFpvpV -> iFppV
#!defined(NOALIGN) iFEivpV -> iFEipV
wrappedalure:
@@ -2232,6 +2299,7 @@ wrappedcairo:
- cairo_scaled_font_set_user_data
- cairo_set_user_data
- cairo_surface_set_user_data
wrappedcairogobject:
wrappedcap:
wrappedcrashhandler:
wrappedcrypto:
@@ -2359,6 +2427,8 @@ wrappedgconf2:
- uFpppppp:
- gconf_client_notify_add
wrappedgcrypt:
- uFpppV:
- gcry_sexp_build
wrappedgdk3:
- vFpp:
- gdk_init
@@ -2614,6 +2684,8 @@ wrappedgobject2:
- g_param_spec_get_default_value
- g_type_class_peek_parent
- g_value_reset
- vFpp:
- g_closure_set_marshal
- iFpp:
- g_param_type_register_static
- pFpi:
@@ -2623,6 +2695,8 @@ wrappedgobject2:
- vFiip:
- g_type_add_interface_static
- g_value_register_transform_func
- vFppp:
- g_closure_add_finalize_notifier
- vFppV:
- g_object_get
- g_object_set
@@ -3017,7 +3091,7 @@ wrappedlibc:
- iFipppp:
- getopt_long
- getopt_long_only
- iFpvvpV:
- iFpiipV:
- iFpiLpp:
- iFpippp:
- iFpuppp:
@@ -3033,7 +3107,7 @@ wrappedlibc:
- pFpLiiiI:
- pFpppppp:
- iFpippppp:
- iFpuvvppp:
- iFpuiippp:
- iFpLiLppp:
wrappedlibcairogobject:
wrappedlibcrypt:
@@ -3069,6 +3143,7 @@ wrappedlibgl:
- glDebugMessageCallback
- glDebugMessageCallbackAMD
- glDebugMessageCallbackARB
- glDebugMessageCallbackKHR
- vFipp:
- glProgramCallbackMESA
wrappedlibglu:
@@ -3077,6 +3152,23 @@ wrappedlibglu:
- gluQuadricCallback
- gluTessCallback
wrappedlibharfbuzz:
wrappedlibibus:
- vFpippp:
- ibus_bus_current_input_context_async
- ibus_bus_get_global_engine_async
- ibus_bus_list_active_engines_async
- ibus_bus_list_engines_async
- ibus_input_context_get_engine_async
- vFppippp:
- ibus_bus_create_input_context_async
- ibus_bus_set_global_engine_async
- ibus_config_get_values_async
- vFpppippp:
- ibus_config_get_value_async
- vFpuuuippp:
- ibus_input_context_process_key_event_async
- vFppppippp:
- ibus_config_set_value_async
wrappedlibice:
wrappedlibjpeg:
- iFv:
@@ -3086,6 +3178,9 @@ wrappedlibjpeg:
- jpeg_start_decompress
- pFp:
- jpeg_std_error
- vFpp:
- jpeg_stdio_dest
- jpeg_stdio_src
- iFpi:
- jpeg_read_header
- vFpiL:
@@ -3109,6 +3204,9 @@ wrappedlibjpeg62:
- jpeg_std_error
- vFpi:
- jpeg_start_compress
- vFpp:
- jpeg_stdio_dest
- jpeg_stdio_src
- iFpi:
- jpeg_read_header
- jpeg_resync_to_restart
@@ -3179,6 +3277,7 @@ wrappedlibm:
- cbrtl
- erfcl
- erfl
- floorl
- ldexpl
- lgammal
- logl
@@ -3509,6 +3608,7 @@ wrappedlibxcb:
- xcb_unmap_window
- xFpp:
- xcb_free_cursor
- xcb_no_operation
- xFpCC:
- xcb_get_keyboard_mapping
- xFpup:
@@ -3537,6 +3637,8 @@ wrappedlibxcb:
- xcb_change_window_attributes
- xcb_change_window_attributes_checked
- xcb_query_text_extents
- iFpppip:
- xcb_take_socket
- xFpCuup:
- xcb_send_event
- xFpCppp:
@@ -3558,6 +3660,7 @@ wrappedlibxcb:
- xcb_grab_keyboard
- xFpCuuWW:
- xcb_create_pixmap
- xcb_create_pixmap_checked
- xFpCuuup:
- xcb_poly_line
- xcb_poly_line_checked
@@ -3781,6 +3884,7 @@ wrappedlibxft:
wrappedlibxi:
wrappedlibxmu:
wrappedlibxpm:
wrappedlibxpresent:
wrappedlibxrandr:
wrappedlibxrender:
wrappedlibxss:
@@ -4332,6 +4436,7 @@ wrappedtbbmallocproxy:
- _ZnamRKSt9nothrow_t
- _ZnwmRKSt9nothrow_t
wrappedtcmallocminimal:
- pFp:
- iFpL:
- munmap
- pFpLiiii:
@@ -4421,9 +4526,12 @@ wrappedvulkan:
- vkDestroyFramebuffer
- vkDestroyImage
- vkDestroyImageView
- vkDestroyOpticalFlowSessionNV
- vkDestroyPipeline
- vkDestroyPipelineCache
- vkDestroyPipelineLayout
- vkDestroyPrivateDataSlot
- vkDestroyPrivateDataSlotEXT
- vkDestroyQueryPool
- vkDestroyRenderPass
- vkDestroySampler
@@ -4452,6 +4560,12 @@ wrappedvulkan:
- vkGetPhysicalDeviceSurfaceCapabilities2KHR
- iFPpp:
- vkCreateInstance
- vFpPpp:
- vkGetDeviceImageSparseMemoryRequirements
- vkGetDeviceImageSparseMemoryRequirementsKHR
- iFpupU:
- vkQueueSubmit2
- vkQueueSubmit2KHR
- iFpUup:
- vkGetDisplayPlaneCapabilitiesKHR
- iFpUpP:
@@ -4477,8 +4591,11 @@ wrappedvulkan:
- vkCreateHeadlessSurfaceEXT
- vkCreateImage
- vkCreateImageView
- vkCreateOpticalFlowSessionNV
- vkCreatePipelineCache
- vkCreatePipelineLayout
- vkCreatePrivateDataSlot
- vkCreatePrivateDataSlotEXT
- vkCreateQueryPool
- vkCreateRenderPass
- vkCreateRenderPass2
@@ -4492,6 +4609,7 @@ wrappedvulkan:
- vkCreateValidationCacheEXT
- vkCreateXcbSurfaceKHR
- vkCreateXlibSurfaceKHR
- vkGetPhysicalDeviceOpticalFlowImageFormatsNV
- vkRegisterDeviceEventEXT
- vFpupup:
- vkUpdateDescriptorSets
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
*******************************************************************/
#ifndef __wrappedcairogobjectDEFS_H_
#define __wrappedcairogobjectDEFS_H_
#endif // __wrappedcairogobjectDEFS_H_
@@ -0,0 +1,17 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
*******************************************************************/
#ifndef __wrappedcairogobjectTYPES_H_
#define __wrappedcairogobjectTYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
#define SUPER() ADDED_FUNCTIONS()
#endif // __wrappedcairogobjectTYPES_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
*******************************************************************/
#ifndef __wrappedcairogobjectUNDEFS_H_
#define __wrappedcairogobjectUNDEFS_H_
#endif // __wrappedcairogobjectUNDEFS_H_
+3 -1
View File
@@ -11,7 +11,9 @@
#define ADDED_FUNCTIONS()
#endif
typedef uint32_t (*uFpppV_t)(void*, void*, void*, ...);
#define SUPER() ADDED_FUNCTIONS()
#define SUPER() ADDED_FUNCTIONS() \
GO(gcry_sexp_build, uFpppV_t)
#endif // __wrappedgcryptTYPES_H_
@@ -12,10 +12,12 @@
#endif
typedef void* (*pFp_t)(void*);
typedef void (*vFpp_t)(void*, void*);
typedef int32_t (*iFpp_t)(void*, void*);
typedef void* (*pFpi_t)(void*, int32_t);
typedef void* (*pFpp_t)(void*, void*);
typedef void (*vFiip_t)(int32_t, int32_t, void*);
typedef void (*vFppp_t)(void*, void*, void*);
typedef void (*vFppV_t)(void*, void*, ...);
typedef int32_t (*iFppp_t)(void*, void*, void*);
typedef void* (*pFipV_t)(int32_t, void*, ...);
@@ -39,11 +41,13 @@ typedef uint32_t (*uFpiippppiup_t)(void*, int32_t, int32_t, void*, void*, void*,
GO(g_param_spec_get_default_value, pFp_t) \
GO(g_type_class_peek_parent, pFp_t) \
GO(g_value_reset, pFp_t) \
GO(g_closure_set_marshal, vFpp_t) \
GO(g_param_type_register_static, iFpp_t) \
GO(g_value_init, pFpi_t) \
GO(g_value_array_sort, pFpp_t) \
GO(g_type_add_interface_static, vFiip_t) \
GO(g_value_register_transform_func, vFiip_t) \
GO(g_closure_add_finalize_notifier, vFppp_t) \
GO(g_object_get, vFppV_t) \
GO(g_object_set, vFppV_t) \
GO(g_boxed_type_register_static, iFppp_t) \
+2 -2
View File
@@ -98,7 +98,7 @@ typedef int32_t (*iFiLLLL_t)(int32_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t
typedef int32_t (*iFipipu_t)(int32_t, void*, int32_t, void*, uint32_t);
typedef int32_t (*iFipuup_t)(int32_t, void*, uint32_t, uint32_t, void*);
typedef int32_t (*iFipppp_t)(int32_t, void*, void*, void*, void*);
typedef int32_t (*iFpvvpV_t)(void*, void, void, void*, ...);
typedef int32_t (*iFpiipV_t)(void*, int32_t, int32_t, void*, ...);
typedef int32_t (*iFpiLpp_t)(void*, int32_t, uintptr_t, void*, void*);
typedef int32_t (*iFpippp_t)(void*, int32_t, void*, void*, void*);
typedef int32_t (*iFpuppp_t)(void*, uint32_t, void*, void*, void*);
@@ -114,7 +114,7 @@ typedef void* (*pFpLiiii_t)(void*, uintptr_t, int32_t, int32_t, int32_t, int32_t
typedef void* (*pFpLiiiI_t)(void*, uintptr_t, int32_t, int32_t, int32_t, int64_t);
typedef void* (*pFpppppp_t)(void*, void*, void*, void*, void*, void*);
typedef int32_t (*iFpippppp_t)(void*, int32_t, void*, void*, void*, void*, void*);
typedef int32_t (*iFpuvvppp_t)(void*, uint32_t, void, void, void*, void*, void*);
typedef int32_t (*iFpuiippp_t)(void*, uint32_t, int32_t, int32_t, void*, void*, void*);
typedef int32_t (*iFpLiLppp_t)(void*, uintptr_t, int32_t, uintptr_t, void*, void*, void*);
#define SUPER() ADDED_FUNCTIONS() \
@@ -23,6 +23,7 @@ typedef void (*vFipp_t)(int32_t, void*, void*);
GO(glDebugMessageCallback, vFpp_t) \
GO(glDebugMessageCallbackAMD, vFpp_t) \
GO(glDebugMessageCallbackARB, vFpp_t) \
GO(glDebugMessageCallbackKHR, vFpp_t) \
GO(glProgramCallbackMESA, vFipp_t)
#endif // __wrappedlibglTYPES_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
*******************************************************************/
#ifndef __wrappedlibibusDEFS_H_
#define __wrappedlibibusDEFS_H_
#endif // __wrappedlibibusDEFS_H_
@@ -0,0 +1,33 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.0.0.10) *
*******************************************************************/
#ifndef __wrappedlibibusTYPES_H_
#define __wrappedlibibusTYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef void (*vFpippp_t)(void*, int32_t, void*, void*, void*);
typedef void (*vFppippp_t)(void*, void*, int32_t, void*, void*, void*);
typedef void (*vFpppippp_t)(void*, void*, void*, int32_t, void*, void*, void*);
typedef void (*vFpuuuippp_t)(void*, uint32_t, uint32_t, uint32_t, int32_t, void*, void*, void*);
typedef void (*vFppppippp_t)(void*, void*, void*, void*, int32_t, void*, void*, void*);
#define SUPER() ADDED_FUNCTIONS() \
GO(ibus_bus_current_input_context_async, vFpippp_t) \
GO(ibus_bus_get_global_engine_async, vFpippp_t) \
GO(ibus_bus_list_active_engines_async, vFpippp_t) \
GO(ibus_bus_list_engines_async, vFpippp_t) \
GO(ibus_input_context_get_engine_async, vFpippp_t) \
GO(ibus_bus_create_input_context_async, vFppippp_t) \
GO(ibus_bus_set_global_engine_async, vFppippp_t) \
GO(ibus_config_get_values_async, vFppippp_t) \
GO(ibus_config_get_value_async, vFpppippp_t) \
GO(ibus_input_context_process_key_event_async, vFpuuuippp_t) \
GO(ibus_config_set_value_async, vFppppippp_t)
#endif // __wrappedlibibusTYPES_H_
Loaded 100 of 235 files, more files were not shown because too many files have changed in this diff. Show more