582 Commits
Author SHA1 Message Date
ptitSeb 3c98cbccbe Bumped to v0.1.8 2020-12-16 07:58:23 +01:00
ptitSeb 3a5c6751e2 Many fixes to Double->Int x87 opcodes ([DYNAREC] too) 2020-12-15 15:53:38 +01:00
ptitSeb 002d3d7b9b This also fixes 66 D9 and 66 DD opcodes 2020-12-15 15:52:53 +01:00
ptitSeb e57a66da04 [DYNAREC] Fixed AAD opcode 2020-12-15 15:51:13 +01:00
ptitSeb b1ecad2d49 Fixed 66 D9 and 66 DD opcodes 2020-12-15 15:50:18 +01:00
ptitSeb 658a107f60 Better log for FE xx and FF xx Illegal Instructions on interpretor 2020-12-15 15:49:39 +01:00
ptitSeb 7b419ce5f1 Fix a callback for pulse audio (help #268, seems to be working now) 2020-12-15 15:40:58 +01:00
ptitSeb 367df08989 Fix Zoom hack for libturbojpeg.so (for #268) 2020-12-15 07:59:04 +01:00
ptitSeb 2004006a9d Added Zoom detection and hack to first try to use system libturbojpeg.so if loaded (still for #268) 2020-12-14 21:45:57 +01:00
ptitSeb bed0f24f2b Wrapped libturbojpeg.so.0 with a small set of functions (should help #268) 2020-12-14 20:48:56 +01:00
ptitSeb 7995dfc70a Fixed a potential SIGBUS on DF /7 FISTP opcode 2020-12-14 14:12:43 +01:00
ptitSeb b29d569f6b Reworked libpulse wrappers (should be more stable and little tad faster) 2020-12-14 12:22:39 +01:00
ptitSeb 3c166c438a [DYNAREC] Added BOX86_DYNAREC_SAFEMMAP (can be usefull to speedup Wine progs, but may also introduce crash) 2020-12-13 20:25:55 +01:00
ptitSeb 03dac0ef6a [DYNAREC] Use a table read that is not thread safe in linker (I don't think thread safe is a must-have in this case) 2020-12-13 19:26:31 +01:00
ptitSeb 27cb5219ae [DYNAREC] Various simplifications 2020-12-13 19:24:27 +01:00
ptitSeb 97a7459f5d [DYNAREC] Small optims 2020-12-13 16:12:17 +01:00
ptitSeb 1eac337e59 [DYNAREC] Don't flush dynarec_log 2020-12-13 16:11:59 +01:00
ptitSeb 1613358927 [DYNAREC] Fixed a type is FS: Cache handling (should give back some speed on Wine stuff) 2020-12-13 15:38:32 +01:00
ptitSeb 2f0da26f14 [DYNAREC] Presize dblists 2020-12-13 14:21:05 +01:00
ptitSeb 45fa32cb9d [DYNAREC] Small fixes for cancelled dynablock 2020-12-13 14:19:56 +01:00
ptitSeb 9e9f2a37be [DYNAREC] Precalc exact instsize array size 2020-12-13 14:19:04 +01:00
ptitSeb 7b37bb6825 [DYNAREC] simplify this structure 2020-12-13 14:18:36 +01:00
ptitSeb 081378a178 Added empty wrapped libnsl.so 2020-12-13 10:05:28 +01:00
ptitSeb ff72343429 [DYNAREC] Removed a debug leftover 2020-12-13 10:04:57 +01:00
ptitSeb b0b8a2ca1c Fixed a warning 2020-12-13 09:09:35 +01:00
ptitSeb 55be6835b8 Removed a debug leftover (should help #227 and box-compatibility-list/#46) 2020-12-13 08:38:43 +01:00
ptitSeb c465e1de21 [VULKAN] fixed SDL2 wrapping of SDL_Vulkan_GetVkGetInstanceProcAddr 2020-12-12 19:50:04 +01:00
ptitSeb 0f255de201 Made box86context_t lighter for easier debugging (also reorganised member order) 2020-12-12 19:50:04 +01:00
ptitSeb deb04610b5 Revert commit 31a108b685, previous method seems better 2020-12-12 19:25:53 +01:00
ptitSeb a9887fe471 Fixed an old type on Bridge handling 2020-12-12 17:09:35 +01:00
ptitSeb 4b3c5a7f6f [DYNAREC] Reworked Dynablock memory manager 2020-12-12 15:24:05 +01:00
ptitSeb 0058d3563d Added 66 F0 0F B1 opcode 2020-12-12 10:18:13 +01:00
ptitSeb 52a4808f2c Added a few more function to wrapped libfontconfig 2020-12-12 10:09:17 +01:00
ptitSeb 7a0874165f Added 1 wrapped function to libfontconfig 2020-12-12 09:37:44 +01:00
ptitSeb 7c7acd134b Small wrapped libmpg123 and pulse change 2020-12-11 22:27:43 +01:00
ptitSeb ddd4874baa [DYNAREC] Some small optim on support function for the Dynarec 2020-12-11 21:04:11 +01:00
ptitSeb 23f91b1a0d [DYNAREC] All Interpretor to switch back to Dynarec on more opcodes 2020-12-11 20:47:23 +01:00
ptitSeb b8c32d580b [DYNAREC] If a block wasn't created because executable memory was not allocated, delete the whole dynablocks to try again later 2020-12-11 20:35:39 +01:00
ptitSeb c0e67004d5 [DYNAREC] Reworked the dynarec signal handling, to improve its performances 2020-12-11 20:25:24 +01:00
ptitSeb 38a557b7e9 [DYNAREC] Don't try to create 0 sized Map block 2020-12-11 17:28:32 +01:00
ptitSeb 7d6d5d673d [DYNAREC] added 64 A2 opcode 2020-12-11 17:27:23 +01:00
ptitSeb 2cf067f004 [DYNAREC] Don't try to a free a 0 sized of NULL pos Map 2020-12-11 17:27:08 +01:00
ptitSeb 92d9bc525f [DYNAREC] Try to avoid some deadlock with dynarec that could happens in some specific cases involving signals 2020-12-11 16:43:25 +01:00
ptitSeb dca91b1efc added 64 A0 opcode ([DYNAREC] too) 2020-12-11 16:32:14 +01:00
ptitSeb 6bf1ea7539 [DYNAREC] Remove some old code behind ifdefs 2020-12-11 14:23:18 +01:00
ptitSeb 670b13595b Improved the PltRelocator detection of elfloader 2020-12-10 17:14:17 +01:00
ptitSeb dcbb8b29de Added some X11 wrapped functions 2020-12-10 17:12:40 +01:00
ptitSeb 7284c817b2 And more libxcb* wrapped functions 2020-12-10 17:05:54 +01:00
ptitSeb b16912132f Added some xcb_xrandr wrapped functions 2020-12-10 15:44:53 +01:00
ptitSeb 9805ad7f3a Initialize context as soon as possible in library (should help #265 and #266) 2020-12-10 15:11:26 +01:00
ptitSeb 4e7e0f6aab Added a few libdrm wrapped function 2020-12-10 13:56:24 +01:00
ptitSeb c905ebfdd2 Added wrapped libSDL2_ttf-2.0.so.0 (copy if the sdl1 version) 2020-12-10 13:51:31 +01:00
ptitSeb b5c787938c Fixed commented code, in case it gets uncommented someday 2020-12-10 13:38:59 +01:00
ptitSeb 69ca5351b4 Added a bunch of wrapped xcb* functions 2020-12-10 12:35:52 +01:00
ptitSeb 3f42372603 Added liblcms2 wrapped lib (partial wrapping, just enough for wine) 2020-12-09 15:54:33 +01:00
ptitSeb 595028e9ec Reworked Exit, to avoid segfault and lockup and end of execution 2020-12-09 11:25:14 +01:00
ptitSeb 7358a049ef Huge refactoring (again), completly removed old Callback mecanism (working to have only 1 x86emu_t structure per thread, almost there) 2020-12-08 22:38:51 +01:00
ptitSeb 792aeda72e Be more smart to when to apply PltRelacator or not (fix SuperHexagon's libGLEW loading) 2020-12-08 21:44:21 +01:00
ptitSeb 53bf2d277b Added wrapped libldap_r and liblber 2020-12-08 08:10:02 +01:00
ptitSeb 0cbc55ba24 Fix potential build error on old system (at least with old headers) 2020-12-08 07:56:18 +01:00
ptitSeb 7b0d228972 Added a few XTandr wrapped functions 2020-12-08 07:54:40 +01:00
ptitSeb 8ac0b66836 Improved Segment offset Cache, and enable GS: caching (some speed boost on Linux apps) 2020-12-07 13:56:29 +01:00
ptitSeb 2756b1b9dd [DYNAREC] fixed some warning and a typo from last commit 2020-12-06 22:31:15 +01:00
ptitSeb e3f44bae26 [DYNAREC] Huge refactor to simplify Dynablock handling 2020-12-06 21:52:27 +01:00
ptitSeb 1963589186 Mooore Thread Cancel slots 2020-12-06 21:14:38 +01:00
ptitSeb a5c9675b84 [DYNAREC] Removed Mark mecanism (it needs mutex to run properly, so it's too heavy) 2020-12-06 15:13:40 +01:00
ptitSeb 76747d5c38 [DYNAREC] Immprove log for SMC debugging option 2020-12-06 15:12:36 +01:00
ptitSeb 59bfeb9fb2 [DYNAREC] This barrier optimization seems to break Mono on Linux, so reverting it for now 2020-12-06 13:15:09 +01:00
ptitSeb c40669b429 [DYNAREC] Optimized AddMark function to not redo what is already done 2020-12-05 23:22:09 +01:00
ptitSeb d83cdbfeeb Fixed a potential segfault 2020-12-05 23:21:29 +01:00
ptitSeb d8773e96d6 Not sure if awesomium_process needs or not emulated libpng12. Commenting for now 2020-12-05 20:59:24 +01:00
ptitSeb 78571698c2 Some improvements in wrapped libpng handling 2020-12-05 19:43:52 +01:00
ptitSeb 77282f1ff1 Added one more wrapped function to libglib2 2020-12-05 17:07:57 +01:00
ptitSeb 953fcb7f1b Fixed handling of TLS object with a 0 offset (help Garry's Mod, probably a few other too) 2020-12-05 16:59:08 +01:00
ptitSeb 1905e4a7f6 Better handling of libtcmalloc_minimum.so.4 2020-12-05 16:15:35 +01:00
ptitSeb 31e6ae0705 Improved the BOX86_NOBANNER behaviour 2020-12-05 12:49:17 +01:00
ptitSeb 31a108b685 Change method used for Thread Cancel registeration 2020-12-04 21:47:39 +01:00
ptitSeb b122c68b16 Improved a bit XImage handling 2020-12-04 21:47:04 +01:00
ptitSeb 0efae1fdf5 Added BOX86_NOGTK to disable use of wrapped gtk libs (can be used with Steam) 2020-12-04 19:52:10 +01:00
ptitSeb 0850180861 Fixed and improved wrapped libdbus-1 2020-12-04 19:49:25 +01:00
ptitSeb 528478b379 Improved a bit wrapped libusb-1 2020-12-04 17:55:30 +01:00
ptitSeb 65302010db Small remork on cancel tread registration mecanism (should fix memory leaks) 2020-12-03 12:01:07 +01:00
ptitSeb 6b32440347 Small fix (mostly cosmetic) in a pthread wrapped function signature 2020-12-03 12:00:32 +01:00
ptitSeb 5a0b6c419e [DYNAREC] Fixed some memory leak 2020-12-03 11:59:43 +01:00
ptitSeb 94c5d0205b fixed some warning 2020-12-03 11:58:49 +01:00
ptitSeb 0f2998a672 More libxml2 wrapping improvment for wine 2020-12-02 21:39:27 +01:00
ptitSeb 1ba7936ef7 Improve wrapping of libxml2 (especially for wine msxml3.dll.so) 2020-12-02 21:16:19 +01:00
ptitSeb 5192aacb22 [RPI] Added runtime hack to get TokiTori2+ running on Pi 2020-12-01 15:13:22 +01:00
ptitSeb ac2adcaf52 A bit more logs when function name is not found 2020-12-01 15:01:12 +01:00
ptitSeb 1b3e707f62 Added SDL_LogGetOutputFunction to wrapped libsdl2 and refactored remaining callback functions 2020-12-01 08:59:01 +01:00
ptitSeb 925fc67c66 Fixed a typo in wrapped libxml2 2020-12-01 08:33:47 +01:00
ptitSeb 54ce6deb1c Wrapped libxslt (should help #259) 2020-11-30 20:02:57 +01:00
ptitSeb 754859d28a Wrapped libxml2 (should help #259) 2020-11-30 18:42:09 +01:00
ptitSeb 269bc9e289 [DYNAREC] Disable one of the new optim, it breaks some installer 2020-11-29 17:26:54 +01:00
ptitSeb 35c768c040 [DYNAREC] Fixed an issue with an optimisation that was too agressive 2020-11-29 13:51:11 +01:00
ptitSeb ff45cfed83 [DYNAREC] Various fixes on some dynarec optimisation mecanism 2020-11-28 16:07:04 +01:00
ptitSeb 38c5c1c17a [DYNAREC] Added 64 FF /2 CALL FS:Ed opcode 2020-11-28 15:32:22 +01:00
ptitSeb 423b301596 Added syscal 356 (and code to emulate it if not present) 2020-11-28 12:26:40 +01:00
ptitSeb 000c11f9ea [PANDORA] Added basic implementation of renameat2 2020-11-28 12:17:12 +01:00
ptitSeb cea4a02ad9 Fixed RPATH handling when a list of path was set 2020-11-28 11:10:01 +01:00
ptitSeb 4e9bc39381 [DYNAREC] Some rework on dynablock management 2020-11-27 17:40:16 +01:00
ptitSeb ad084da13d Start a new dev. cycle with v0.1.7 2020-11-27 10:18:13 +01:00
ptitSeb 27e5262f1d Bumped to v0.1.6 2020-11-26 09:43:33 +01:00
ptitSeb 363464092e [DYNAREC] Added 66 60/61 16bits PUSHA/POPA opcodes 2020-11-25 12:04:47 +01:00
ptitSeb b2cab70427 [DYNAREC] Improved 16bits immediate PUSH opcodes 2020-11-25 12:04:46 +01:00
ptitSeb 44d5301244 [DYNAREC] Improved 16bits PUSH/POP opcodes 2020-11-25 12:04:46 +01:00
ptitSeb 8e4f4feb3c Updated CHANGELOG 2020-11-25 12:04:46 +01:00
ptitSeb e9f6f8824c [DYNAREC] Fixed a potential SIGBUS with int64->double loading 2020-11-24 12:04:03 +01:00
ptitSeb be6f9870d0 Added 64 01/03/11/2B opcodes 2020-11-23 18:41:20 +01:00
ptitSeb bb086223c7 Update README.md 2020-11-23 13:33:36 +01:00
ptitSeb be6a3bff3f Fixed 2 wrapped functions signature in libappindicator (help Steam) 2020-11-22 20:42:49 +01:00
ptitSeb adfc5fda2e Fixed a SEGBUS on RK339 build 2020-11-22 20:31:33 +01:00
ptitSeb d833f136a0 Enable the 'GOG Linux install hack' also for RK3399 platforms 2020-11-22 18:41:37 +01:00
ptitSeb 1703e9d1b7 Refined CMakeList a bit 2020-11-22 18:41:05 +01:00
ptitSeb 011b9f93e4 [DYNAREC] Fixed 66 0F EA/EE opcodes (should fix #253 this time) 2020-11-22 17:30:30 +01:00
ptitSeb e449a4e247 Launch natively program if elf is not recognised as an i386, or not an elf 2020-11-22 14:08:11 +01:00
ptitSeb fe7f0ff842 Fixed potential BUSERROR with LOCK CMPXCHG8B opcode on interpretor 2020-11-22 13:52:44 +01:00
ptitSeb 2033e5764d Fixed potential segfault when using BOX86_LOG=2 2020-11-22 13:05:28 +01:00
ptitSeb 55175263ac [DYNAREC] Added 0F BA /5 and /7 opcodes 2020-11-22 10:52:40 +01:00
ptitSeb c484221cd6 Remove the 'suspicious segment' left over debug code 2020-11-22 10:21:55 +01:00
ptitSeb e9862cb30d [DYNAREC] Fix potential issue when multiple similar thread are launched at the same time (will help #253) 2020-11-21 20:32:52 +01:00
ptitSeb 0c7b99cbc6 [DYNAREC] Changed how opcodes 66 0F 38 08/09/0A are coded (this fixes the md5 error in #253) 2020-11-21 18:36:55 +01:00
ptitSeb 824f39e4db [DYNAREC] Potential fix for 66 0F 38 1C/1D/1E when Gx==Ex and Gx is not cached yet (help #253, but still some issues) 2020-11-21 15:31:27 +01:00
ptitSeb 66a5ce1e52 [DYNAREC] Fixed 66 0F 38 1C/1D/1E opcode (for #253, still not ok, how many opcodes are borked?) 2020-11-21 15:18:22 +01:00
ptitSeb f39637a652 [DYNAREC] Fixed 66 0F EE opcode (for #253, but still not enough) 2020-11-21 15:10:03 +01:00
ptitSeb eaf7d0a277 [DYNAREC] Fixed 66 0F 38 08/09/0A opcode (should help #253 a bit) 2020-11-21 14:54:25 +01:00
ptitSeb b61bb908a2 Improve handling of signals with threads or functions call 2020-11-21 11:06:16 +01:00
ptitSeb 2e891b807c [DYNAREC] Added 66 0F 38 08/09/0A opcodes (for #253 again) 2020-11-20 21:44:47 +01:00
ptitSeb f0b236df88 [DYNAREC] Added 66 0F 38 1C/1D/1E opcodes (still for #253) 2020-11-20 21:18:42 +01:00
ptitSeb 08904dbe0d [DYNAREC] Added 66 0F E4/E5/EA/EE opcodes (should help #253) 2020-11-20 21:04:45 +01:00
ptitSeb c9c4e226af Added 0F DA PMINUB and 0F DE PMAXUB opcodes ([DYNAREC] too) 2020-11-18 21:21:42 +01:00
ptitSeb ab3dc70145 Added 2 clipboard function to gtk2 wrapped lib 2020-11-18 20:50:06 +01:00
ptitSeb 4d8c841f3f [DYNAREC] Fix potential BUSERROR of F3 0F 2C and F3 0F 2D opcode, and fixed a typo on F3 0F E6 opcode 2020-11-18 20:44:38 +01:00
ptitSeb a8b247cde9 More improvments and fixes to signal handler 2020-11-18 19:29:52 +01:00
ptitSeb 416e161285 Added F2 0F D0 ADDSUBPS Gx, Ex opcode 2020-11-18 15:28:21 +01:00
ptitSeb cc8d1f9bf2 Better handling of signals 2020-11-18 09:58:55 +01:00
ptitSeb ae95f1b0e5 One more wrapped func tion with callback to gtk2 2020-11-17 10:35:29 +01:00
ptitSeb c10441bec4 Added g_timeout_* wrapped functions to libglib2 2020-11-17 10:27:43 +01:00
ptitSeb 6ab334fc34 Fixed a nasty typo in wrapped libgobject2 2020-11-17 10:27:20 +01:00
ptitSeb 10e849ce60 Fixed a warning in generated wrapper.c 2020-11-17 10:03:35 +01:00
ptitSeb c2206f5452 Aligned most of GValue handling in gtk libs 2020-11-17 09:41:18 +01:00
ptitSeb 3b66cd3cee Merge branch 'master' of https://github.com/ptitSeb/box86 2020-11-16 22:20:11 +01:00
ptitSeb 731a083bb7 Merge pull request #251 from daitj/makemkvtest
added few more wrapper for libcrypto (for #250)
2020-11-16 22:18:25 +01:00
Binay Devkota d35c6ab864 added more wrapper function for #250 2020-11-16 22:51:28 +02:00
Binay Devkota e9cade872c fixed previous commit as i am blind 2020-11-16 20:42:46 +02:00
Binay Devkota b2a8146851 added missing wrapped function for libcrypto #250 2020-11-16 20:15:53 +02:00
ptitSeb 6fd3d6c452 Improved handling of 'marshal' function in gobject2 2020-11-16 19:06:25 +01:00
ptitSeb bc3e72a87d Added a few more wrapped function to libcrypto (for #250) 2020-11-16 17:28:18 +01:00
ptitSeb e50e050aa9 Added some AES_* wrapped funciton to libcrypto (for #250) 2020-11-16 16:45:36 +01:00
ptitSeb c1a75607fa Fixed 'Alternate' autobridge on Interpretor 2020-11-16 14:57:37 +01:00
ptitSeb b203cd2af3 Added system 242 and 241 (for #250) 2020-11-16 14:39:39 +01:00
ptitSeb 84063f026f Added gtk_recent_filter_* wrapped function to gtk2 2020-11-16 14:39:12 +01:00
ptitSeb 3ec1ce25d7 [DYNAREC] Remove a leftover of debug trace 2020-11-16 14:35:54 +01:00
ptitSeb 0e70c543ee Added 'Aternate' solution for Gtk Classes functions beeing called in x86 code 2020-11-16 14:19:16 +01:00
ptitSeb e4d522a8d2 Refactored Gtk Class wrapping code 2020-11-16 10:25:32 +01:00
ptitSeb 272ecbd8ff More gtk class wrapping 2020-11-16 09:44:01 +01:00
ptitSeb 369fa03f9b Better handling of gtk signals 2020-11-15 18:28:25 +01:00
ptitSeb 1675ea3ba2 Added 2 functions wrapped libX11 2020-11-15 17:12:43 +01:00
ptitSeb 5b7a1bb9e6 Added phtread_spin handling 2020-11-15 17:07:07 +01:00
ptitSeb ace3effa2d Improved GCallback handling and fixed g_action_group_add_actions 2020-11-15 17:04:07 +01:00
ptitSeb bd0a14b3ce Added g_list_find_custom wrapped function to libglib2 2020-11-15 16:21:55 +01:00
ptitSeb 29a82f83c5 Added g_queue_find_custom to wrapped libglib2 2020-11-15 16:13:17 +01:00
ptitSeb f7232f09de Fixed a warning 2020-11-15 16:12:47 +01:00
ptitSeb f3eeae9edd Implemented gtk_builder_connect_signals to wrapped gtk2 2020-11-15 15:29:44 +01:00
ptitSeb 874468ca07 Added gtk_cell_layout_set_cell_data_func to gtk2 wrapped lib 2020-11-15 13:49:59 +01:00
ptitSeb 7a972af610 Fixed potential issue with gobject2 signal handler 2020-11-15 12:57:37 +01:00
ptitSeb 4ed42c38c9 Added wrapping of GtkLabel class to gtk2/3 libs 2020-11-15 12:55:31 +01:00
ptitSeb 6a73719a6b One more wrapped function to gtk2 2020-11-15 12:29:58 +01:00
ptitSeb 6efcfc6b93 Added 2 more g_list_ function to wrapped libglib2 2020-11-15 12:28:38 +01:00
ptitSeb 25f30c220e Added gtk_viewport_* wrapped function to gtk2 2020-11-15 12:24:42 +01:00
ptitSeb 2e9665f10e One more glib2 wrapped function 2020-11-15 12:22:23 +01:00
ptitSeb 197881b430 Fixed g_build_path wrapped function 2020-11-15 12:20:37 +01:00
ptitSeb 96fe98d71f Added gtk_cell_renderer_* wrapped function to gtk2 2020-11-15 11:54:35 +01:00
ptitSeb d1ecd4c933 Added g_build_path wrapped function to libglib2 2020-11-15 11:44:15 +01:00
ptitSeb fad25caa08 Added g_content_type_* function to wrapped libgio2 2020-11-15 11:34:25 +01:00
ptitSeb 98c481e045 Added gtk_tree_store wrapped functions to gtk2 lib 2020-11-15 11:29:48 +01:00
ptitSeb 6082e655e6 Added g_slist_sort and g_slist_sort_with_data to wrapped libglib2 2020-11-15 11:11:44 +01:00
ptitSeb 6a97367242 Made GetNativeFnc smarter, and should find more native funcs now 2020-11-15 11:05:07 +01:00
ptitSeb bbcfffdab9 Added gtk_container_foreach and fixed gtk_binding_entry_add_signal when n is 0 in wrapped gtk2 2020-11-15 10:28:22 +01:00
ptitSeb 2dfb6c1012 Added g_regex function to wrapped libglib2 2020-11-15 10:11:12 +01:00
ptitSeb 82317343aa Added GtkAction wrapped functions 2020-11-15 09:58:55 +01:00
ptitSeb 0ea0d0ec98 Better handling of custom gtk class, plus a bunch of gtk wrapeed functions 2020-11-15 09:48:10 +01:00
ptitSeb 33aa27c590 Added GtkAction Class handling (gtk2 and gtk3, hopefully it's the same) 2020-11-14 16:17:04 +01:00
ptitSeb c31f990183 Added F3 0F 12 MOVSLDUP Ex, Gx opcode ([DYNAREC] too) 2020-11-14 15:11:52 +01:00
ptitSeb 791956bee0 More wrapped function to gtk2 lib 2020-11-14 15:03:57 +01:00
ptitSeb 6cebf4f6fd Added more wrapped functions to gtk2 lib 2020-11-14 14:46:02 +01:00
ptitSeb 1782136e02 Added F3 0F 16 MOVSHDUP Ex, Gx opcode ([DYNAREC] too) 2020-11-14 14:30:44 +01:00
ptitSeb 2f381192dd Added some queue wrapped function to libglib2 2020-11-14 13:30:51 +01:00
ptitSeb dac2009cab Added the random functions to wrapped libglib2 2020-11-14 12:39:17 +01:00
ptitSeb d592af694f Added some more wrapped functions to libglib2 2020-11-14 12:18:56 +01:00
ptitSeb e5ea3f9e49 Added g_set_print_handler and g_set_printerr_handler to wrapped libglib2 2020-11-14 11:55:01 +01:00
ptitSeb f0af865401 Fix potential crash on exit for app using Pulse (fixes Iconoclash crash on exit) 2020-11-14 11:37:30 +01:00
ptitSeb 1e20a9effe Improved and simplifiex SDL2_mixer wrapped library 2020-11-13 22:33:34 +01:00
ptitSeb ce968f7756 Added some precision on 32bits build over 64bits OS 2020-11-12 17:43:03 +01:00
ptitSeb 00aaf316ef Added RK3399 target and compilation guide (plus some restructuration in CMake project 2020-11-11 18:08:16 +01:00
ptitSeb 3ad9a0ca73 [DYNAREC] Added ability to track exact x86 address in dynablocks for signal handling 2020-11-11 14:08:53 +01:00
ptitSeb 14a2d24fba [DYNAREC] Better way to prevent difference in emited dynablock between pass2 and pass3 2020-11-10 19:13:07 +01:00
ptitSeb e374886fcf AddedF0 90..97 opcode, simply ignoring F0 LOCK prefix ([DYNREC] too) 2020-11-09 15:09:43 +01:00
ptitSeb e25b373f00 Fixed gtk_menu_item_set_use_underline wrapped function signature 2020-11-09 12:06:57 +01:00
ptitSeb 6fbd270d24 [DYNAREC] cosmetic change 2020-11-08 13:40:40 +01:00
ptitSeb 6adb55a9c4 [DYNAREC] Try to fix the randow issue were a block have a different emited size between pass2 and pass3 2020-11-08 13:40:14 +01:00
ptitSeb 16aa5cac04 Fixed a warning with wrapped posix_spawnp 2020-11-08 13:39:06 +01:00
ptitSeb dca0009df5 [DYNAREC] Fix 66 0F 16 MOVHPD opcode and improved 66 0F C6 SHUFPD 2020-11-08 13:32:28 +01:00
ptitSeb 1cae441cbc More glib2 wrapped functions 2020-11-07 11:27:28 +01:00
ptitSeb 8b21d8f74a [DYNAREC] Added some dump of block when incosistancy between pass2 and pass3 is detected 2020-11-07 11:26:40 +01:00
ptitSeb ff141e30ee Added handling of environ instead of envv for box86 called with spawnp 2020-11-07 11:25:54 +01:00
ptitSeb 2c970a1b8d Added wrapped posix_spawnp function 2020-11-07 11:25:12 +01:00
ptitSeb b433f8194e Improved a bit the fork wrapped function 2020-11-06 17:47:53 +01:00
ptitSeb 7b2f5e5de0 Improved some BOX86_LOG=2 traces 2020-11-06 17:47:26 +01:00
ptitSeb 3d1400e347 Added preliminary gtk3/gdk3 wrapped lib (based on gtk2/gdk2 wrapping) 2020-11-06 14:08:10 +01:00
ptitSeb 8b5d68f79b Use std=gnu11 to avoid some warning when using clang 2020-11-05 14:01:32 +01:00
ptitSeb ded4b461b4 Some more check to help build on some Linux on Android env. 2020-11-05 12:48:44 +01:00
ptitSeb 13a7be57f2 Check some define to help build on some Linux on Android env. 2020-11-05 12:21:55 +01:00
ptitSeb e8fdcd5c06 Added a bunch of gtk wrapped functions 2020-11-05 11:34:11 +01:00
ptitSeb b8e263d7e6 Removed a warning in wrapped SDL_mixer 2020-11-05 11:33:50 +01:00
ptitSeb b76d17e7b9 Update ChangeLog 2020-11-04 13:15:57 +01:00
ptitSeb ce3151b256 Fixed some (XX)printf alignement issue when formating have %+ or %- command 2020-11-02 16:19:39 +01:00
ptitSeb dd0c3ac51e [VULKAN] More work on vulkan wrapper 2020-11-02 13:32:38 +01:00
ptitSeb f06c5897db Merge pull request #245 from linkmauve/patch-1
Fix install target after previous change
2020-11-02 12:51:14 +01:00
linkmauve 7dac72f796 Fix install target after previous change
#244 broke the install target because system/box86.conf should
now be taken from the build directory, sorry for that.
2020-11-02 12:10:29 +01:00
ptitSeb e5a55114b7 Merge pull request #239 from SpacingBat3/master
PKGBUILDs for Arch Linux.
2020-11-02 12:02:57 +01:00
ptitSeb a66d0b3d39 Merge pull request #244 from linkmauve/fix-binfmt-path
Generate binfmt so it points to the correct path
2020-11-02 12:00:29 +01:00
Emmanuel Gil Peyrot b01ad69ba1 Generate binfmt so it points to the correct path
CMake’s templating language is suitable for this kind of generation, as
it knows about all of the variables that have been set at configure-
time.
2020-11-02 10:52:25 +00:00
ptitSeb bbe183e8d4 Do not try to run winedbg 2020-11-01 23:29:20 +01:00
ptitSeb f6c9e5079a Small improvement on BOX86_LOG=2 2020-11-01 23:28:54 +01:00
ptitSeb 0b8408d50a [VULKAN] Fixed vkGetPhysicalDeviceImageFormatProperties signature 2020-11-01 22:42:20 +01:00
ptitSeb 51682eac11 [VULKAN] Fixed vkalignStruct/vkunalignStruct (and now Sascha-willems samples start working) 2020-11-01 21:34:23 +01:00
ptitSeb aea38c682c [VULKAN] More vulka wrapping work 2020-11-01 21:12:56 +01:00
ptitSeb 6edbe97290 Added the last function not wrapped in SDL1_mixer, and redid the wrapping of the callback (for #243) 2020-11-01 20:11:23 +01:00
ptitSeb 304eaab4d2 [VULKAN] Fixed a warning 2020-11-01 17:11:53 +01:00
ptitSeb f4e5839931 [VULKAN] Morework on wrapped functions 2020-11-01 15:35:53 +01:00
ptitSeb 4bac9ea9d5 [VULKAN] More work on vulkan wrapper 2020-11-01 10:04:30 +01:00
ptitSeb 64c9b21849 [VULKAN] Alignment of many structures. Now a simple TriangleDrawing windows App works 2020-10-31 22:58:58 +01:00
SpacingBat3 34828b66a2 Added a PKGBUILDs for other platforms. 2020-10-31 17:35:06 +01:00
SpacingBat3 957ba00723 Added a PKGBUILD for other raspberries.
Added a unified PKGBUILD to install box86 on all RPi-based machines (that are fully supported by box86) and did some changes to README.md.
2020-10-31 17:32:45 +01:00
SpacingBat3 d548ee48c1 Added a RPI4B PKGBUILD.
It is possible now to install the `box86` using the PKBUILD providen in the repository.
2020-10-31 16:57:09 +01:00
ptitSeb d0e93a22a2 Better vulkan log 2020-10-31 09:55:49 +01:00
ptitSeb fe6c1e260b Added one more vulkan extension 2020-10-31 09:55:33 +01:00
ptitSeb 1e5add91d3 Fixed many vulkan wrapped function (and now vulkaninfo works) 2020-10-30 22:12:55 +01:00
ptitSeb f4c7329c30 Forgotten in previous commit 2020-10-30 22:12:11 +01:00
ptitSeb b1742ccb8e Added some minimum wrapped libwayland-client 2020-10-30 22:11:37 +01:00
ptitSeb 870a0d8361 [VULKAN] Fixed library not found even if present 2020-10-30 17:52:44 +01:00
ptitSeb 1f0adf92d4 Added 64 8E MOV Seg, FS:Ed opcode (for #241) 2020-10-30 16:15:45 +01:00
ptitSeb 18ce562698 Wrapping of vulkan (untested yet) 2020-10-30 16:08:46 +01:00
ptitSeb 77af926336 Added 64 8C MOV FS:Ed, Seg opcode (for #241) 2020-10-30 10:44:32 +01:00
ptitSeb 33f2269896 [DYNAREC] removes some compile warning 2020-10-30 10:43:52 +01:00
ptitSeb c477e14a04 [DYNAREC] Minor chenges to some 67 xx opcodes 2020-10-30 10:10:36 +01:00
ptitSeb 373494094a [DYNAREC] Forgot that file on previous commit 2020-10-30 10:08:46 +01:00
ptitSeb 72ca666007 [DYNAREC] Added 65 80/82 opcodes 2020-10-30 10:07:47 +01:00
ptitSeb 5be299b897 [DYNAREC] Cosmetic change 2020-10-30 10:06:55 +01:00
ptitSeb 49afd5077b [DYNAREC] Fixed some function that needs flags before CALL (fixed some ESP not properly preserved on some Windows programs) 2020-10-30 10:05:47 +01:00
ptitSeb e7336de8a7 Change COMPILE.md for Pi4: make -j4 is enough 2020-10-30 10:03:10 +01:00
ptitSeb 5b0f4f5b94 Start a new developpement cycle 2020-10-30 10:02:17 +01:00
ptitSeb 0edc037441 Bumped version to v0.1.4 2020-10-24 15:34:34 +02:00
ptitSeb d4a7f7e658 Simplified glib2 wrapped lib 2020-10-24 12:38:28 +02:00
ptitSeb fcf9668e8b Fixed wrapped g_variant_get function 2020-10-24 12:36:17 +02:00
ptitSeb 76e53e0869 Fixed execvp wrapped function to use PATH / BOX86_PATH to look for binary if needed 2020-10-24 10:47:59 +02:00
ptitSeb 74764253b4 Fixed pango_attribute_init wrapped function 2020-10-24 00:12:35 +02:00
ptitSeb c029c6c152 [DYNAREC] Avoid potential SIGBUS on 66 0F 13MOVLPD and 66 0F 16/17 MOVHPD opcodes 2020-10-24 00:11:44 +02:00
ptitSeb bb4b0d5f92 [DYNAREC] Avoid potential SIGBUS on F3 0F E6 CVTDQ2PD opcode 2020-10-24 00:10:04 +02:00
ptitSeb a355cf941b [DYNAREC] cosmetic changes on dynarec_arm_dd.c 2020-10-24 00:07:32 +02:00
ptitSeb e7c5ef1cca Added some wrapped function to lib pango and pangoft2 2020-10-23 20:03:07 +02:00
ptitSeb 09d0f7a3cb Fixed GVariant creation on wrapped glib2 2020-10-23 20:02:28 +02:00
ptitSeb 3e7dd07b4c Added a libpangoft2-1.0.so as wrapped too 2020-10-23 20:02:02 +02:00
ptitSeb c536eed349 [DYNAREC] Changed a bit how comon dynablock is selected 2020-10-23 20:00:29 +02:00
ptitSeb 93948021e6 Added DE D0..D7 FCOMP ([DYNAREC] too) 2020-10-23 19:59:40 +02:00
ptitSeb 77317f87c0 Simplify SDL2 Event Handler 2020-10-23 19:58:37 +02:00
ptitSeb b091ea9c6d Fixed wrapped lib appindicator 2020-10-23 14:36:56 +02:00
ptitSeb 208493da88 It seems mpg123 use 64bits off_t 2020-10-23 13:04:00 +02:00
ptitSeb 7015745c4f Silence a warning, and don't create a fake /sys/devices/system/cpu/cpuX/topology/core_id file if it exist 2020-10-22 23:50:59 +02:00
ptitSeb 41a5c72d46 [PANDORA] put all define at the same place (for #233) 2020-10-22 23:48:04 +02:00
ptitSeb 2b428641fb [PANDORA] forgot to close the ifdef (for #233) 2020-10-22 23:43:00 +02:00
ptitSeb 4ebb1e60db [PANDORA] Fix potential build issue (for #233) 2020-10-22 23:31:56 +02:00
ptitSeb 5e4c1feed1 [DYNAREC] Fixed the Free of Dynablock that weren't always sane (fixes RGPMaker 2000, among aother things) 2020-10-22 19:24:11 +02:00
ptitSeb d13e1da1a7 [DYNAREC] Added undocummented BOX86_DYNAREC_SMC to detect special case of SMC (slow things down, so use wizely) 2020-10-22 19:24:11 +02:00
ptitSeb 9f57cff43b [README] Fixed address of 86box github project (still for #232) 2020-10-22 17:40:56 +02:00
ptitSeb b9d9776d5c Added 86box precision on README, plus PILab Discord channel link (to mitigate #232) 2020-10-22 16:52:02 +02:00
ptitSeb b57ab8470d [DYNAREC] Some more small optims to some of the LOCK opcodes 2020-10-21 19:08:29 +02:00
ptitSeb fe402d2faa [DYNAREC] Use posix_memalign instead of mmap to for Dynarec block memory 2020-10-21 18:58:50 +02:00
ptitSeb 3d38210752 Improved (once more) signal handling 2020-10-21 17:52:42 +02:00
ptitSeb 6c4b047b58 Changed slightly the win prereserve mecanism 2020-10-20 11:00:22 +02:00
ptitSeb e861d3415a Changed, once again, the loading position of box86 2020-10-20 10:59:55 +02:00
ptitSeb cb251fe88b [DYNAREC] Fixed F0 0F B0 LOCK CMPXCHG Eb, Gb opcode (help KaM Remake) 2020-10-19 21:28:11 +02:00
ptitSeb b1e594f4d7 More work on signal handling 2020-10-19 11:04:45 +02:00
ptitSeb f9505f3c9f Improved a bit wrappedlibc 2020-10-19 11:03:02 +02:00
ptitSeb 52ee2bb769 A bit more logs when using BOX86_LOG=2 2020-10-19 11:01:45 +02:00
ptitSeb f0471fac14 Merge pull request #231 from icecream95/nine-2
Create a fake IDirect3D9 object instead of changing the vtable
2020-10-19 09:57:26 +02:00
Icecream95 7baac98959 Create a fake Direct3D9 object instead of changing the vtable
This means both x86 and ARM code can have the right function pointers
at the same time, allowing a hack in Gallium Nine to be removed.
2020-10-19 20:02:49 +13:00
ptitSeb 9119443c2a [DYNAREC] Go back to X_PEND (as it's more optimized) on end of block (now PvZ still works, thanks to previous commit) 2020-10-17 17:29:38 +02:00
ptitSeb c9c33929f0 [DYNAREC] Fixed (and optimized a bit) some Math emiter 2020-10-17 17:27:16 +02:00
ptitSeb 60717d38d4 Added wrapped libcups with a few functions 2020-10-17 15:21:27 +02:00
ptitSeb 858757f8d1 Merge pull request #230 from mogwa1/master
Fix presumable typo in wrappedlibncurses files
2020-10-17 09:38:22 +02:00
Bart De Vries f15a22a3cb Fix presumable typo in wrappedlibncurses files
A call to vmprintw is made, which is a non-existent function.
Presumably, vwprintw is meant to be called.
2020-10-17 09:34:24 +02:00
ptitSeb f6022de7d3 Don't try to alloc elf section that have so read/write/execute flags 2020-10-16 13:19:17 +02:00
ptitSeb 8214301231 Added handling of /sys/devices/system/cpu/cpuX/topology/core_id file 2020-10-16 13:17:59 +02:00
ptitSeb a4745098c5 Don't inject PLTResolver if it's not needed (should help #195) 2020-10-15 11:04:00 +02:00
ptitSeb 647b06a615 Fixed an issue with box86 shutdown 2020-10-15 10:51:49 +02:00
ptitSeb a7cbafee07 Added libssl.so.1.1 as a alt name for wrapped libssl 2020-10-14 21:18:32 +02:00
ptitSeb ee0eb2345c Added libcrytpo.so.1.1 as a alt name for wrapped libcrypto 2020-10-14 21:16:50 +02:00
ptitSeb d37c42761d Don't try to use XSAVE/XRSTR yet on signal handling 2020-10-14 20:06:05 +02:00
ptitSeb d4984fd0ee New attemps at improving Signal Handling 2020-10-14 17:43:08 +02:00
ptitSeb c770ea1859 Added an option to disable the loading of pulse audio libs 2020-10-14 09:29:59 +02:00
ptitSeb 4d1307e223 Improve signal handling, again (to help windows exception managers) 2020-10-12 22:16:23 +02:00
ptitSeb e9308c11ba [DYNAREC] Added 67 64 xx opcode (copy of 64 67 xx, need to factorise all this) 2020-10-12 21:50:48 +02:00
ptitSeb 5206ec0fcb Fixed 1 wrapped function signature in libXext 2020-10-12 21:50:12 +02:00
ptitSeb c65671a6f9 Added more libXext wrapped functions (for #226) 2020-10-12 10:40:33 +02:00
ptitSeb ec99203dc6 Better log for FF illegzal opcode 2020-10-12 10:22:05 +02:00
ptitSeb 1cdde047ff Added more ncurses wrapped function (for #215) 2020-10-12 08:35:30 +02:00
ptitSeb 2375d70782 [DYNAREC] Fixed a typo in 8D LEA Gd, Ed opcode 2020-10-11 22:10:44 +02:00
ptitSeb 5b0c395293 Added a even more wrapped libcrypto functions 2020-10-11 20:47:36 +02:00
ptitSeb ea0c1abb0b Added a few more wrapped libcrypto functions 2020-10-11 20:13:37 +02:00
ptitSeb cc841812ce Added 1 wrapped function to libcrypto 2020-10-11 19:07:48 +02:00
ptitSeb 5104bce7bb [DYNAREC] Added (fake) F2/F3 EB opcode 2020-10-11 18:28:45 +02:00
ptitSeb 357ce483a8 [DYNAREC] Added a workaround for some SMC trick using PUSH Id followed by RET (help RPGMaker RunTime) 2020-10-11 18:21:17 +02:00
ptitSeb 1a40b4b984 [DYNAREC] Added D9 F6/F7 FDECSTP/FINCSTP opcode 2020-10-11 15:30:02 +02:00
ptitSeb cdd0e542f1 Added (faked) XACQURE/XRELEASE prefix 2020-10-11 14:21:20 +02:00
ptitSeb a9d87a938d Added (fake?) 63 ARPL Ed, Gd opcode 2020-10-10 18:30:22 +02:00
ptitSeb 549ff980a3 [DYNAREC] Added FPREM1 opcode 2020-10-10 16:33:46 +02:00
ptitSeb 545af93972 [DYNAREC] Added FBSTSW opcode 2020-10-10 16:33:10 +02:00
ptitSeb 72b9ed9f54 Even more libjpeg.so.62 improvements 2020-10-10 15:01:27 +02:00
ptitSeb 536c7dd04b Big improvement in libjpeg.so.62 handling 2020-10-10 13:46:04 +02:00
ptitSeb 274d5d1e75 Also trap SIGILL now, like SIGSEGV and SIGBUS 2020-10-10 10:42:47 +02:00
ptitSeb 7b478e42c0 Improved libjpeg.so.8 and libjpeg.so.62 handling 2020-10-10 10:31:27 +02:00
ptitSeb d0ac1e61d4 Added libjpeg.so.62 as for wrapped libjpeg 2020-10-09 20:13:58 +02:00
ptitSeb 31d73927a3 [README] Added a Steam paragraph (for #223) 2020-10-09 17:38:45 +02:00
ptitSeb 7713bd042a Added wcsnlen wrapped function to libc 2020-10-08 12:00:16 +02:00
ptitSeb 664dab76e3 Fixed improved signal handler. It seems to work a bit now 2020-10-07 21:38:38 +02:00
ptitSeb 6e2c33866d Add DB E1 FDISI8087_NOP as NOP ([DYNAREC] too) 2020-10-07 20:03:43 +02:00
ptitSeb 7b6dd6765e Rermoved a forgotten debug trace 2020-10-07 19:57:50 +02:00
ptitSeb d55d2d0303 [DYNAREC] Added D5 Ib AAM and D6 Ib AAD opcodes 2020-10-07 19:37:40 +02:00
ptitSeb 4df7bec913 Some fixes to new signal handling functions 2020-10-07 19:15:44 +02:00
ptitSeb 4ddab1b691 Made fork to reset the main hread emu if needed 2020-10-07 19:14:54 +02:00
ptitSeb b0c0e96fca [DYNAREC] Added D6 SALC opcode 2020-10-07 19:12:34 +02:00
ptitSeb aeee2fc391 Try to better handle Signals when signal handler change any context value 2020-10-07 12:07:52 +02:00
ptitSeb 4f28cb5617 Added wrapped funciton logl to libm (help KeeperRL) 2020-10-07 11:42:46 +02:00
ptitSeb a442a841f2 Added wrapped function curl_free to libcurl (help KeeperRL) 2020-10-07 11:42:10 +02:00
ptitSeb 9201170ab8 [DYNAREC] Fixed and optimized F3 0F E6 CVTDQ2PD opcode 2020-10-06 23:12:32 +02:00
ptitSeb 4f06cfa0da [DYNAREC] Added F3 0F E6 CVTDQ2PD Gx, Ex opcode 2020-10-06 16:19:25 +02:00
ptitSeb fe03daa01f [DYNAREC] Cosmetic change in one of the emmiter 2020-10-06 16:18:57 +02:00
ptitSeb b64c4f6043 Better handling of path with space (for #220, but seriously, space in folder name are evil) 2020-10-06 13:04:07 +02:00
ptitSeb 5884c78b56 Use CMAKE_SOURCE_DIR instead of CMAKE_HOME_DIRECTORY as recommended in cmake documentation 2020-10-06 11:59:33 +02:00
ptitSeb b01b7373ac [DYNAREC] Added workaround for unaligned LOCK XADD Ed, Gd 2020-10-06 11:53:28 +02:00
ptitSeb 3cc9482a08 [DYNAREC] Added a workaround for unaligned LOCK SUB Ed, Id/Ib 2020-10-06 11:12:16 +02:00
ptitSeb 83c6b01fae Added a NOGIT option to build from sources that are not a git clone (should help #220) 2020-10-06 10:59:20 +02:00
ptitSeb 1f169bc67e [DYNAREC] Added a workaround for unaligned LOCK ADD Ed, Id/Ib and also fix potential issues when an opcode have internal jump 2020-10-06 08:05:40 +02:00
ptitSeb ea25675264 Merge pull request #221 from Botspot/patch-1
Optimize compilation & full install commands
2020-10-06 07:59:29 +02:00
Botspot c302cd680c Optimize compilation & full install commands 2020-10-05 18:28:43 -05:00
ptitSeb ebf46d0cfd Added a few more symbols and dependancies to gtk wrapped libs (should help #193) 2020-10-05 22:38:28 +02:00
ptitSeb 2c9b504688 Improve dlsym mecanism (should help #193) 2020-10-05 21:13:45 +02:00
ptitSeb 41d3de565c Added 2 symbols in wrapped libgtk-x11 2020-10-05 20:15:25 +02:00
ptitSeb 88430d845d Fixed an issue with a log of wrapped dlopen 2020-10-05 20:15:24 +02:00
ptitSeb c6e5e5d27e Added wrapped libxcb-present (partial) 2020-10-05 15:20:26 +02:00
ptitSeb cd673028b7 Added wrapped libxcb-dri2 and libxcb-dri3 (partial) 2020-10-05 14:29:56 +02:00
ptitSeb 2cafe12e4f Default to BOX86_LOG=NONE (use BOX86_LOG=1 to get previous behaviour) 2020-10-05 11:54:55 +02:00
ptitSeb febbaca66b Added BOX86_NOBANNER env. var. plus default to printing box86 version and build number at start 2020-10-05 11:53:46 +02:00
ptitSeb e410ca748a Merge pull request #219 from icecream95/nine
Wrap Gallium Nine
2020-10-05 10:02:15 +02:00
ptitSeb 524c04296e Fixed FXSR opcodes (should help #218) 2020-10-05 09:52:06 +02:00
Icecream95 ef360bf93e Add a final NULL to environment variables
Fixes Wine crashes with certain numbers of environment variables present.
2020-10-05 14:44:50 +13:00
Icecream95 bd4f7a4783 Update generated functions 2020-10-05 14:44:50 +13:00
Icecream95 3c2c242225 Add wrapping for d3d9 2020-10-05 14:44:50 +13:00
Icecream95 a8e657c86e Add some headers for d3d9 wrapping 2020-10-05 14:44:50 +13:00
Icecream95 70e103af49 Wrap some more libxcb functions 2020-10-05 14:44:50 +13:00
ptitSeb 006f7a79b4 Added C4 LES Gd, Ed opcode 2020-10-04 22:08:02 +02:00
ptitSeb c7a4dbe84b Fixed __res_state that is wrapped function and not a data in libc 2020-10-04 18:29:27 +02:00
ptitSeb 31c0c52d7f Added a few more wrapped function to libdbus 2020-10-04 17:28:07 +02:00
ptitSeb a4590d3771 Fix for commit 85dd704f86 2020-10-04 16:58:32 +02:00
ptitSeb 02b5e39c39 Improved signal handling 2020-10-04 16:23:11 +02:00
ptitSeb 85dd704f86 Don't protect executable memory until it's actually executed 2020-10-04 16:22:55 +02:00
ptitSeb b4d4efd40c Added 2 more wrapped functions to libdbus 2020-10-04 16:18:13 +02:00
ptitSeb 8745b0f31a Small changes in thread handling ([DYNAREC] Pre-compute first dynarec of thread function before creating a thread) 2020-10-04 10:59:36 +02:00
ptitSeb 3787b3bbfc Minor changein trace handling 2020-10-04 10:58:42 +02:00
ptitSeb 765e1b1231 [DYNAREC] Changed __builtin___clear_cache with __clear_cache 2020-10-04 10:58:09 +02:00
ptitSeb 2a2e2bf957 Improved a bit SIGSEGV/SIGBUS log message 2020-10-04 10:57:32 +02:00
ptitSeb c93913732b Added C5 LDS Gd, Ed opcode (not sure it's correct) 2020-10-04 10:54:11 +02:00
ptitSeb f5bbc99d7d Change how LD2D works, to avoid potential BusError 2020-10-03 21:42:54 +02:00
ptitSeb 27ce42b9b0 Added g_log_set_default_handler to wrapped glib2 lib 2020-10-03 09:10:43 +02:00
ptitSeb 008d51aeec Added in6addr_loopback data to wrapped libc 2020-10-03 09:10:06 +02:00
ptitSeb 8d0d264c0f Add some data to wrapped ncurses libs (should help #215) 2020-10-03 08:06:47 +02:00
ptitSeb 28717352b4 Improved detail when using BOX86_DLSYM_ERROR=1 2020-10-02 15:52:28 +02:00
ptitSeb f9e492dfdc Added FXSR in the CPU ID flags 2020-10-02 15:51:48 +02:00
ptitSeb a8e029f0e0 [DYNAREC] Added DF C0..C7 FFREEP opcode 2020-10-01 10:13:46 +02:00
ptitSeb f5be4503c5 Added DF C0..C7 FREEP opcode 2020-10-01 10:13:19 +02:00
ptitSeb cd1d3f5026 Added tputs wrapped function to libtsinfo.so.5 and libtsinfo.so.6 (for #211) 2020-10-01 09:38:46 +02:00
ptitSeb 4f55733bdd Added msgctl wrapped function to libc 2020-09-30 18:14:38 +02:00
ptitSeb 81819d04e8 Added msgsnd and msgrcv wrapped function to libc 2020-09-30 17:57:55 +02:00
ptitSeb 4d4adea6eb Added msgget wrapped function to libc 2020-09-30 17:36:08 +02:00
ptitSeb ca981fbc8e [DYNAREC] Added 66 0F 38 01/02/03/05 opcodes 2020-09-30 17:25:12 +02:00
ptitSeb b4c64abd1e Added 66 0F 38 03 PHADDSW opcode 2020-09-30 17:24:18 +02:00
ptitSeb a8787330d8 [DYNAREC] Added F2 0F F0 LDDQU opcode 2020-09-30 17:20:18 +02:00
ptitSeb 7725234b69 Added F2 0F F0 LDDQ opcode 2020-09-30 17:19:50 +02:00
ptitSeb 062d897fb1 Added 66 0F 38 05 PHSUBW opcode 2020-09-30 16:50:59 +02:00
ptitSeb e1ed95a638 Added a few more xcb wrapped functions 2020-09-30 16:35:08 +02:00
ptitSeb 7ffa5d076c Changed a bit FF /6 opcode to avoid potential issues with Ed with ESP 2020-09-30 16:32:51 +02:00
ptitSeb 1ae0ae630a Fixed some typo on some segments opcode ([DYNAREC] too) 2020-09-30 11:05:11 +02:00
ptitSeb d3e8daa9b5 Removed workaround that disabled SSSE3 for Steam, it's not needed anymore 2020-09-30 10:20:19 +02:00
ptitSeb 5f8be26b73 Added xcb_setup_roots_length wrapped function to libxcb (for #193) 2020-09-30 08:24:21 +02:00
ptitSeb 0eb575b472 Fixed some wrapped libXRandr functions 2020-09-28 15:03:47 +02:00
ptitSeb 1888d905a4 Try to handle SIGBUS like SIGSEGV 2020-09-28 15:03:18 +02:00
ptitSeb 3bc4dc8450 Fixed handling of file not found at start 2020-09-28 10:21:12 +02:00
ptitSeb 78719df8d4 Try to implement sigset wrapped function (for #211) 2020-09-27 15:03:17 +02:00
ptitSeb d3616b335f Improved wrapped ncurses / tsinfo symbols (for #209 and #211) 2020-09-27 14:38:40 +02:00
ptitSeb e72cd086b4 Better handling of /proc/PID/xxx in wrapped files open function (for #202) 2020-09-27 14:14:31 +02:00
ptitSeb c82e67c39a Added 66 0F 38 08/09/0A PSIGN(B/W/D) opcode 2020-09-27 14:02:38 +02:00
ptitSeb 9885cf6f10 [DYNAREC] Assorted fix and optim for some SSE2/SSSE3 opcodes 2020-09-27 13:42:26 +02:00
ptitSeb d923b5bc0f [DYNAREC] better log for unimplemented opcode 2020-09-27 09:39:25 +02:00
ptitSeb 611d2fcaff Assorted interpretor fixes for some SSE2 opcodes 2020-09-27 09:38:58 +02:00
ptitSeb 9b2b312719 Merge branch 'master' of https://github.com/ptitSeb/box86 2020-09-26 19:18:49 +02:00
ptitSeb f84161dafc Merge pull request #210 from rajdakin/printerFix
Fixed some instructions printer
2020-09-26 19:16:14 +02:00
rajdakin 8546a0d0bd [PRINTER] Fixed some instructions printer 2020-09-26 18:43:02 +02:00
ptitSeb 09f5873806 Fixed 66 0F E8 PSUBSB opcode 2020-09-26 13:49:14 +02:00
ptitSeb 18dc905a8c [DYNAREC] Various small optimisations, mainly SSE oriented 2020-09-26 11:48:19 +02:00
ptitSeb 30d64a0aa5 Small fix on 66 0F 67 PACKSSDW opcode 2020-09-26 10:24:46 +02:00
ptitSeb 8359c9e19f [DYNAREC] Added D9 /6 FNSTENV opcode 2020-09-26 10:23:48 +02:00
ptitSeb 571f0c0564 Small optim on D9 /6 FNSTENV opcode 2020-09-26 10:23:21 +02:00
ptitSeb 736a9ef442 Fixed 66 0F 67 PACKUSWB when EX and GX are the same 2020-09-25 13:49:43 +02:00
ptitSeb aee94b0e14 A bit more work on cpow(f) wrapped function 2020-09-25 12:08:54 +02:00
ptitSeb 4cfed0d394 [DYNAREC] Fixed 66 0F 38 04 PMADDUBSW opcode 2020-09-25 10:51:11 +02:00
ptitSeb c714d5d881 Fixed 0F 38 00 PSHUFB to use MM regs instead of XMM 2020-09-25 10:35:34 +02:00
ptitSeb 1c2d07ee56 [DYNAREC] Change implementation for 66 0F 6E MOVD Gx, Ex opcode 2020-09-25 08:25:06 +02:00
ptitSeb 96f7f3d88f Change implementation for 66 0F 3A 0F PALIGNR opcode 2020-09-25 08:24:17 +02:00
ptitSeb c743577369 Added 0F C3 MOVNTI opcode ([DYNAREC] too) 2020-09-25 08:21:28 +02:00
ptitSeb e5ea60fe88 Added more complex functions to wrapped libm 2020-09-24 21:39:05 +02:00
ptitSeb 330d93f335 Fixed wrapped libm function taht return float complex, plus added a few complex functions 2020-09-24 19:42:10 +02:00
ptitSeb f4936144d0 0F 38 01/02 PHADD(W/D) opcode 2020-09-24 19:41:33 +02:00
ptitSeb bbaa5dde92 Refactored gigantic Run function to create Run660F and try speedup build a bit 2020-09-24 17:45:37 +02:00
ptitSeb e6b46151ec Added (66) 0F 38 1C/1D/1E PABS(B/W/D) opcode 2020-09-24 17:23:12 +02:00
ptitSeb 655a8de652 Added 66 0F 7C HADDPD opcode 2020-09-24 16:53:44 +02:00
ptitSeb 771d69f38b [DYNAREC] Some (S)SSE2/3 opcodes fixes 2020-09-24 16:35:14 +02:00
ptitSeb 2a46dbf149 A bit more (S)SSE3 opcodes fixes 2020-09-24 16:34:49 +02:00
ptitSeb 95a0535462 Try to fix 0F 38 0B PMULHRSW opcode 2020-09-24 16:34:10 +02:00
ptitSeb 041758fead Fixed (66) 0F 38 04 PMULHRSW opcode 2020-09-24 11:59:20 +02:00
ptitSeb d6bb723c6a [DYNAREC] Added 0F E0 PAVGB Gm, Em opcode 2020-09-24 11:58:43 +02:00
ptitSeb 95f97e1c9f [DYNAREC] Added (66) 0F 38 0B PMULHRSW opcodes 2020-09-24 10:56:42 +02:00
ptitSeb b029292dd2 Added 0F 38 0B PMULHRSW Gm, Em opcode 2020-09-24 10:56:15 +02:00
ptitSeb 82ba663c24 [DYNAREC] Fixed 0F 38 00 opcode 2020-09-24 10:17:46 +02:00
ptitSeb fabd5b9d32 Added 0F 38 00 PSHUFB opcode ([DYNAREC] too) 2020-09-24 08:39:28 +02:00
ptitSeb 58736b707d [DYNAREC] Added workaround for unaligned LOCK CMPXCHG and LOCK CMPXCHG8B (fixes Unity Games and Steam) 2020-09-23 22:10:06 +02:00
ptitSeb 9219384650 [DYNAREC] Changed the method used on ARM to simulate LOCK prefix 2020-09-23 20:22:44 +02:00
ptitSeb 14a904cfa9 Added all 64 67 opcodes to 67 64 ... 2020-09-23 10:24:17 +02:00
ptitSeb e73f7a9c10 Added 67 64 FF /6 PUSH FS:Ew16 opcode 2020-09-23 07:50:24 +02:00
ptitSeb 09acd36c08 [DYNAREC] Make end of block need a X_ALL, but end because recursive loop need X_PEND (helps PvZ) 2020-09-22 18:11:19 +02:00
ptitSeb 69a6f44b8b Refined .gitignore for TwisterOS 2020-09-22 18:11:08 +02:00
ptitSeb 3ee8fd4ec6 [DYNAREC] Try to optimize runtime speed a bit 2020-09-22 12:21:55 +02:00
ptitSeb 4f6c0b45f8 [DYNAREC] Avoid deleting block that are not supposed to be volatile 2020-09-22 11:38:50 +02:00
ptitSeb 06a756a5eb [DYNAREC] Small optimization for 64 A1 and 64 A3 opcodes 2020-09-22 11:17:01 +02:00
ptitSeb b312df3b53 Bugfixe on Interpretor for some 64, 65, 66 and 67 prefixed opcodes 2020-09-22 11:16:18 +02:00
ptitSeb 8e4b2a90a4 [DYNAREC] Fixed 64 67 8F POP FS:Ew16 opcode 2020-09-21 23:03:23 +02:00
ptitSeb 85b3091b8a [DYNAREC] Added 64 67 A1 MOV EAX, FS:Ow opcode 2020-09-21 18:16:58 +02:00
ptitSeb 3838fc3d22 [DYNAREC] Added 64 67 8F POP FS:Ew16 opcode 2020-09-21 18:14:45 +02:00
ptitSeb 0f4722d580 Improved (f)open(64) wrapped function a bit more 2020-09-21 15:37:53 +02:00
ptitSeb 4241258158 Added a workaround for steam requieremnt checker 2020-09-21 15:37:23 +02:00
ptitSeb 13c446c918 Wrapped libappindicator (seems to fix Steam starting issues) 2020-09-21 06:17:08 -05:00
ptitSeb 9255026b84 [DYNAREC] Fix build 2020-09-21 11:56:32 +02:00
ptitSeb 119eb57a38 Added an option to Launch GDB when a Segfault occur (JIT Debugging) 2020-09-21 09:41:20 +02:00
ptitSeb 731f379bed Fixed a bug in FindDynablockDynablocklist(...) function, making message on segfault with dynarec more precise 2020-09-20 21:43:00 +02:00
ptitSeb bedcf304e1 Added 65 EB and 65 E9 opcode (also [DYNAREC]) 2020-09-20 16:50:33 +02:00
ptitSeb a4655484cb Added 64 EB and 64 E9 opcode (also [DYNAREC]) 2020-09-20 16:44:40 +02:00
ptitSeb babc5aba4f Added a few more wrapped functions to libc (for #204) 2020-09-20 09:45:55 +02:00
ptitSeb 763a6f8b02 Added syscall handling for syscall 11: execve (for #203) 2020-09-20 08:15:03 +02:00
ptitSeb b08960d4b9 Fixed some rounding issues with x87 interpretor (thx @pale) 2020-09-19 22:12:56 +02:00
ptitSeb 2c6e91622f Try to handle NULL argv and NULL envp in execv(e) wrapped function (still for #203) 2020-09-19 18:12:09 +02:00
ptitSeb 4679977612 Small optims on x87 interpretor 2020-09-19 18:03:18 +02:00
ptitSeb 0e387904b0 More work on execv(e) wrapped functions (still for #203) 2020-09-19 15:01:53 +02:00
ptitSeb f4238621a6 Handling of /proc/self/exe in execv(p) function (for #203) 2020-09-19 14:23:27 +02:00
ptitSeb 2fa19e8cae Handling of /proc/self/exe in (f)open(64) (for #202) 2020-09-19 14:13:41 +02:00
ptitSeb ab644d0638 Made same hacks for fopen64 as for fopen 2020-09-19 12:48:58 +02:00
ptitSeb 8d1db88e1a [DYNAREC] Free of dynablock log level is now DEBUG instead of INFO 2020-09-18 18:00:58 +02:00
ptitSeb 12215ac5dd Removed FLOAT build (was not compatible with Dynarec anyway) 2020-09-18 17:52:28 +02:00
ptitSeb 97d0b386ba Added more mpg123 wrapped functions 2020-09-16 08:33:47 +02:00
ptitSeb f8526be667 Reworked FPREM, FPREM1 and FXTRACT opcodes 2020-09-15 14:47:44 +02:00
ptitSeb 22624f6a29 Added g_pattern_spec_* wrapped functions to glib2.0 2020-09-15 10:39:31 +02:00
ptitSeb e70584e7fc Added some wrapped function to mpg123 2020-09-15 10:35:43 +02:00
ptitSeb ebd2346f3e Added some GLib2 wrapped functions 2020-09-15 10:08:38 +02:00
ptitSeb 03ce553620 Added 66 0F 38 0B PMULHRSW Gx, Ex opcode 2020-09-15 08:45:46 +02:00
ptitSeb 9418a37846 Added (F2) EB opcode 2020-09-14 08:01:23 +02:00
ptitSeb 4f186dec68 g_variant_new_va use va_list* and not just va_list... 2020-09-13 20:57:41 +02:00
ptitSeb 5867fd9912 Added D6 SACL opcode 2020-09-12 18:46:27 +02:00
ptitSeb cd327cfc5a Fixed a message when detecting Steam thta was obsolete 2020-09-11 15:06:21 +02:00
ptitSeb a3f95871b2 Fix loading of elf that have no header sections at all 2020-09-11 15:05:57 +02:00
ptitSeb 53021b770b Added 66 0F DA PMINUB Gx, Ex opcode ([DYNAREC] too) 2020-09-10 16:47:38 +02:00
ptitSeb 7f93731d0c [DYNAREC] Added 66 0F 50 MOVMSKPD Gd, Ex opcode 2020-09-10 16:30:44 +02:00
ptitSeb 570f82d7f8 Improved trace with pid when using fork 2020-09-10 11:27:59 +02:00
ptitSeb 2c8a069f47 Improved LOCK opcodes and locking on dynarec dumper 2020-09-09 20:19:19 +02:00
ptitSeb bbf23be1f3 Merge pull request #201 from rajdakin/NEONprinter_fix
Forgot to add those files
2020-09-08 23:15:56 +02:00
rajdakin accca4e700 [PRINTER] Also fixed VRSHL, VQSHL and VQRSHL 2020-09-08 23:11:40 +02:00
rajdakin ecc8ebef6a [PRINTER] Forgot to add those files 2020-09-08 19:04:35 +02:00
ptitSeb 6c8a807c8c Merge pull request #200 from rajdakin/NEONprinter_fix
Various printer fixes
2020-09-08 18:59:22 +02:00
rajdakin dfb2d5eaaa [PRINTER] Fixed the VMOV.<dt> R, D[imm] instruction printer 2020-09-08 18:52:12 +02:00
rajdakin 71c7ec6fed [PRINTER] Fixed a class of var. size opcodes printer 2020-09-08 18:30:35 +02:00
ptitSeb 55d216f024 [DYNAREC] Thoses fixes to 8bits and 16bits opcodes should have been pushed yesterday already 2020-09-08 08:35:30 +02:00
ptitSeb 5e22febd54 Fixed 0F BA /6 BTS opcode (thx @hmilyyang) 2020-09-08 08:34:21 +02:00
ptitSeb 436d871ea9 Reorganized a bit FreeBox86Context function 2020-09-08 08:33:20 +02:00
ptitSeb 02099912c5 [DYNAREC] Fixed (66) 0F D7 PMOVMSKB for good this time 2020-09-07 19:51:48 +02:00
ptitSeb 601aedb25a More improved to env. var. and other misc. attributes 2020-09-07 10:49:36 +02:00
ptitSeb c65aa3d507 Improvment to Env Var handling 2020-09-07 10:24:27 +02:00
ptitSeb 9b02837d5a Another small improvement to wrapped X11 2020-09-07 10:24:06 +02:00
ptitSeb dbbff7b833 Some fixes to some wrapped X11 function callbacks 2020-09-07 08:10:04 +02:00
ptitSeb e306db4d0c Added F2 25 opcode 2020-09-07 07:29:17 +02:00
ptitSeb 985266fc77 Small cosmetic change to one xcb wrapped function 2020-09-07 07:29:03 +02:00
ptitSeb a3f771cc7c Added a bunch of X11 / Xext / FontConfig wrapped functions 2020-09-06 17:05:09 +02:00
ptitSeb 71a1bea9c7 A few more xcb wrapped functions 2020-09-06 14:26:49 +02:00
ptitSeb 565543fbba Added a few more xcb wrapped functions 2020-09-06 12:20:19 +02:00
ptitSeb 9193194596 Less alarming error message on default log level when loading libraries 2020-09-06 11:03:54 +02:00
ptitSeb 83ea28ded7 Made BOX86_LOG=2 a bit less chatty 2020-09-06 10:55:35 +02:00
ptitSeb 1a69782f51 Added more libSSL/libcrypto wrapped functions 2020-09-05 21:10:48 +02:00
ptitSeb 394ea0f3d3 Added more xcb* wrapped functions 2020-09-05 16:09:27 +02:00
ptitSeb 0241bbdbc0 Added xcb_connect to wrapped libxcb 2020-09-05 14:51:14 +02:00
ptitSeb 5e00739776 Added more pulseaudio wrapped functions 2020-09-05 13:22:21 +02:00
ptitSeb 5d214ac965 Added some more libasound wrapped functions 2020-09-05 12:11:32 +02:00
ptitSeb d35ae51fbb Oops, fixed libxrandr and libxcb-randr private mixup 2020-09-05 11:19:29 +02:00
ptitSeb 717f319dc7 Fixed CPUID command 0 Max basic command supported 2020-09-05 11:18:56 +02:00
ptitSeb fbd2f52da2 Added a few xcb_*_id to xcb-* wrapped libs 2020-09-05 10:57:08 +02:00
ptitSeb 853d89ca9c Added (stub) mcount to wrapped libc 2020-09-05 10:56:44 +02:00
ptitSeb 9c9e3cef29 Added getentropy to wrapped libc 2020-09-05 10:46:46 +02:00
ptitSeb 2237afceff Some fixes to the new empty xcb-* wrapped libs 2020-09-05 10:34:10 +02:00
ptitSeb 180d036fd4 Added some empty xcb-* wrapped lib 2020-09-04 23:57:12 +02:00
ptitSeb 7248ee7ed2 Update README.md 2020-09-04 23:56:57 +02:00
ptitSeb d1e7944ad2 Fix shrd16/shld16 opcode (thx to @hmilyyang) 2020-09-03 13:28:04 +02:00
ptitSeb 2f53752e05 Added a workaround for Unreal, to avoid segfault when launching it whithout leading './' 2020-09-03 10:41:13 +02:00
ptitSeb 3c0de68a00 Fixes to PMOVMSKB opcode ([DYNREC] too, avoiding a segfault) 2020-09-02 14:09:32 +02:00
ptitSeb ef22236f35 [DYNAREC] Another attempt to fix 66 0F D7 PMOVMSKB opcode 2020-09-02 10:19:42 +02:00
ptitSeb 563fc27eae [DYNAREC] Try to fix 66 0F D7 PMOVMSKB opcode 2020-09-02 08:48:59 +02:00
ptitSeb d453e120c8 Added F2 0F 80..8F (BND) Jxx opcodes 2020-09-01 22:29:08 +02:00
ptitSeb 57bd72f147 [DYNAREC] Added 66 0F F1/F2/F3 PSLL(W/D/Q) opcodes 2020-09-01 18:42:23 +02:00
ptitSeb 298c62e00b [DYNAREC] 66 0F D7 PMOVMSKB Gd, Ex opcode 2020-09-01 18:41:31 +02:00
ptitSeb 3d4abfeba2 [DYNAREC] Fix(?) 0F D7 PMOVMSKB Gd, Em opcode 2020-09-01 18:40:43 +02:00
ptitSeb b412118a79 [DYNAREC] Added 66 0F D3 PSRLQ Gx, Ex opcode 2020-09-01 18:05:42 +02:00
ptitSeb c2b5c32a14 Added CB FAR RET opcode 2020-08-31 10:45:11 +02:00
ptitSeb 06cd0a518f Added 64 67 8F POP FS:Ew16 opcode 2020-08-29 21:21:58 +02:00
ptitSeb 947dcc3f3d Added 0F 1A NOP / BNDLDX (ignored) opcode 2020-08-28 17:04:26 +02:00
ptitSeb fa5eb23cae Added 0F 1B NOP / BNDSTX (ignored) opcode 2020-08-28 10:55:45 +02:00
ptitSeb c43895b602 Update CHANGELOG.md 2020-08-27 22:07:18 +02:00
ptitSeb 18cb2a2047 [DYNAREC] Added 64 67 89 MOV Gd, FS:Ew16 opcode 2020-08-26 18:07:18 +02:00
ptitSeb 91637c7b11 [DYNAREC] Added 66 9C PUSHF and 66 9D POPF opcodes 2020-08-26 17:50:24 +02:00
ptitSeb 7b70e987ba [DYNAREC] Added 64 67 FF /6 PUSH FS:Ew16 2020-08-26 16:56:26 +02:00
ptitSeb 74dfef3424 [DYNAREC] Added 64 67 8B MOV Gd, FS:Ew16 and 64 67 A3 MOV FS:Ow, EAX opcodes 2020-08-26 16:26:28 +02:00
ptitSeb 65255edec5 [DYNAREC] Added 66 F8 CLC and 66 F9 STC opcodes 2020-08-26 15:11:29 +02:00
ptitSeb 5b00412ba0 [DYNAREC] Added D7 XLAT opcode 2020-08-26 15:05:51 +02:00
ptitSeb ef43e3f8a0 [DYNAREC] Added 0F EA PMINPS Gm, Em opcode 2020-08-26 14:24:29 +02:00
ptitSeb 3fa06d865a [DYNAREC] Added 66 99 CWD opcode 2020-08-26 14:01:15 +02:00
ptitSeb 96f2f12dec [DYNAREC] Added 66 EE PMAXW Gm, Em opcode 2020-08-26 13:43:06 +02:00
ptitSeb 972079532c [DYNAREC] Added 0F 74 PCMPEQB opcode 2020-08-26 13:11:02 +02:00
ptitSeb 996d4efa32 [DYNAREC] Added PADDUSW opcode 2020-08-25 13:55:45 +02:00
ptitSeb 4704bfb7e6 Added 66 0F DD PADDUSW opcode 2020-08-24 17:58:33 +02:00
ptitSeb 5d3b237854 [DYNAREC] Don't delete volatile dynablock (just invalidate) when memory block loose it's eXecutable flag 2020-08-24 14:00:17 +02:00
ptitSeb dca290b3f0 [DYNAREC] Fixed potential bus error on 0F 13 MOVLPS and 0F 17 MOVHPS opcodes 2020-08-23 15:55:44 +02:00
ptitSeb a84473036d [DYNAREC] End of block now provoque an X_PEND flags instead of X_ALL, also, removed the hl_linux workaround (and made C3 RET also needing an X_PEND flags) 2020-08-23 15:17:48 +02:00
ptitSeb 1b3cb7abb5 Merge pull request #191 from rajdakin/ubfx_fix
[DYNAREC] Fixed the UBFX and others instructions
2020-08-23 14:05:44 +02:00
rajdakin 7dd99ae13e [DYNAREC] Fixed the UBFX and others instructions 2020-08-23 13:54:16 +02:00
ptitSeb 7af511b01a Added 66 0F E4 PMULHUW Gx, Ex opcode 2020-08-23 11:41:58 +02:00
ptitSeb bb3dc2d889 Added 66 0F BA /7 BTC Ew, Ib 2020-08-22 11:05:57 +02:00
ptitSeb 76268c41bc Added 66 0F BA /5 BTS Ew, Ib 2020-08-22 10:24:54 +02:00
ptitSeb b6963ba7c6 Added 66 0F C8..CF BSWAP Reg16 opcode 2020-08-22 04:21:20 +02:00
ptitSeb bd3ff8f828 [DYNAREC] Add a temporary workaround to have HalfLife 2 Engine running correctly 2020-08-20 13:47:30 +02:00
ptitSeb 385326f3a8 [DYNAREC] Fixed RETN with N on 2 bytes (should help #188) 2020-08-19 15:21:07 +02:00
ptitSeb d896fd9106 Merge pull request #186 from shahidali55/patch-1
Removed backslash which was breaking ccmake
2020-08-18 10:06:28 +02:00
shahidali55 9c18afee35 Removed backslash which was breaking ccmake 2020-08-18 13:23:58 +05:30
ptitSeb f0b87c8312 Try to fix the gtk_display workaround when using gtk-1.2 instead of gtk-2.0 2020-08-17 20:24:10 +02:00
ptitSeb 297b7d548a [DYNAREC] Added a few GS: and FS opcodes 2020-08-17 17:07:49 +02:00
ptitSeb 7c406e8f8a [DYNAREC] Fixed CF flag for SHL32c emiter (fixed Sega Rally with Dynarec) 2020-08-16 20:55:23 +02:00
ptitSeb f458d8dc39 [DYNAREC] Optimized a bit BT Ed, Ib opcode 2020-08-16 20:54:47 +02:00
ptitSeb 66ed78cf4d [TRACE][DYNAREC] Small cosmetic changes to block that generate trace 2020-08-16 20:53:56 +02:00
ptitSeb f6205182b9 [TRACE] Fix trace that was disabled at first signal handling 2020-08-16 20:53:11 +02:00
ptitSeb a661016824 Avoid a BUSERROR on FISTP Ed, ST0 (help Sega Rally with Interpretor) 2020-08-16 20:52:28 +02:00
ptitSeb 448afcea7a [DYNAREC] Don't optimize flags on C3 RET opcode, some app count on it (help PlantsVsZombies and GOG Setup under wine, maybe more, #183) 2020-08-16 12:17:58 +02:00
ptitSeb 23881ad861 [DYNAREC] Avoid potential BUSERROR on FIST(P)64 2020-08-16 12:16:40 +02:00
ptitSeb 9d41f49741 {DYNAREC] Fixed a crash that can occur on multithreaded apps (fix regression on NFS2SE) 2020-08-16 10:58:00 +02:00
ptitSeb b302ebfbb5 [DYNAREC] Added F2/F3 9C PUSHF 2020-08-16 09:35:40 +02:00
ptitSeb 88d428f03c Added F2/F3 9C PUSHF opcode 2020-08-16 09:25:58 +02:00
ptitSeb 7396b30615 Fixed some '67' opcodes 2020-08-15 19:27:14 +02:00
ptitSeb 6fe1cc9ed7 [DYNAREC] Fixed 66 0F 5B CVTPS2DQ opcode 2020-08-15 19:25:52 +02:00
ptitSeb 7622959657 Generate git_head.h (and so build build_info.c) only when something else needs to be built 2020-08-15 17:44:34 +02:00
ptitSeb 6f94fdf133 [DYNAREC] Changed PUSHAD to have ESP always up-to-date 2020-08-15 14:49:18 +02:00
ptitSeb b348ce3660 Fixed git_head.h no generated at every build (it's build 2 times now with Dynrarec) 2020-08-15 14:23:37 +02:00
ptitSeb f8638fef92 Added 0F 01 /4 SMSW (dummy) opcode 2020-08-15 14:22:56 +02:00
ptitSeb 9e895da7ed Added wrapped gnutls_check_version function 2020-08-15 13:00:37 +02:00
ptitSeb cb659fef0d Added 66 0F B7 MOVZX Gw, Ew ([DYNAREC] too) 2020-08-15 12:53:13 +02:00
ptitSeb 1a9042c8d1 [DYNAREC] Simplified and optimized Dynablocklist Hash 2 Direct handling 2020-08-15 12:33:10 +02:00
ptitSeb aac8cb9775 [DYNAREC] Optimized dynablock handling 2020-08-15 12:31:37 +02:00
ptitSeb 99962a68b6 [DYNAREC] Removed dynablocks from elfheader, only using global one now 2020-08-15 10:56:39 +02:00
ptitSeb 8ce6d7f369 [DYNAREC] The 'volatile' dynablocks are now 4096 bytes of size, like a page (instead of 65536) 2020-08-15 09:48:59 +02:00
ptitSeb 3bc5a586fa Started v0.1.3 dev. cycle 2020-08-15 09:47:49 +02:00
273 changed files with 34579 additions and 7522 deletions

No files matched your search

+1
View File
@@ -3,3 +3,4 @@ build*/
.vscode
.gdb_history
src/git_head.h
backup/
+44
View File
@@ -1,3 +1,47 @@
v0.1.8
======
* Fixes on some float to int x87 convertions opcodes
* Reworked all callback mecanisms
* Added libturbojpeg wrapping (and a hack for zoom to force using native one)
* Added BOX86_SAFEMMAP env. var.
* Reworked dynarec memory manager
* Added a few opcodes
* Improve elfloader to not force PltResolver all the time (fixing SuperHexagon and maybe other)
* Reworked Exet and Cancel Thread mecanism
* Added wrapped libldap_r and liblber library (used by wine)
* Reworked Dynarec block handling, and remove the "AddMark" mecanism that wasn't efficient enough
* Added TokiTori 2+ detection and runtime patch on PI
* Fixes on elfloader with TLS object
v0.1.6
======
* Changes in Dynarec to make flags optimizations before CALL and RET opcode less aggressive
* Added Vulkan wrapper
* Improved wrapping of SDL_mixer/ SDL2_mixer lib
* Improved wrapping of some gtk structures
* Added a quick and dirty wrapping of Gtk3 (based on current gtk2)
* Improved the signal handling, should be more stable now (the signal handler from syscall still need some works)
* Added RK3399 profile, and some hints to build the 32bits box86 on 64bits OS
* Fixed some wrapped printf formating not handled correctly
* Fixed some buserror with the new LOCK mecanism handling
* A few more Dynarec opcodes added
* If winedbg is tried to be launched, exit without launching it (it doesn't work anyway)
v0.1.4
======
* Change in Dynarec memory handling, to simplify it (and hopefully optimized it)
* Even more opcodes added.
* And some more Dynarec opcodes.
* Fixed some issue were PltResolver was injected but should not
* Fixed many Dynarec and non dynarec opcodes
* Improved Signal handling
* Added a few more wrapped lib (like curl)
* Gallium9 is wrapped (thx @icecream95)
* Fixed and simplied many wrapped functions (especialy the one were a callback is involved)
* Fixed Dynarec "freeing" a Dynablock somthime corrupting the heap (happens in case of JIT mainly)
* Optimized the way LOCK prefix work when using Dynarec on ARM
* Printer of ARM opcode (for dumping Dynarec blocks) improvement (thx @rajdakin)
v0.1.2
======
* The Dynarec now handle JIT code
+111 -74
View File
@@ -1,25 +1,26 @@
cmake_minimum_required(VERSION 2.6)
project(box86)
enable_testing()
enable_language(C)
cmake_minimum_required(VERSION 3.0)
option(PANDORA "Set to ON if targeting an OpenPandora device" ${PANDORA})
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(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
option(GAMESHELL "Set to ON if targeting a GameShell device" ${GAMESHELL})
option(ODROID "Set to ON if targeting an ODroid device" ${ODROID})
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box86" ${NO_LOADAADR})
option(NOGETCLOCK "Set to ON to avoid using clock_gettime with CLOCK_MONOTONIC_COARSE for RDTSC opcode (use gltimeofday instead)" ${NOGETCLOCK})
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR RK3399)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
endif()
option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" ${LD80BITS})
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
option(USE_FLOAT "Set to ON to use only float, no double, in all x87 Emulation" ${USE_FLOAT})
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box86" ${NO_LOADAADR})
option(ARM_DYNAREC "Set to ON to use ARM Dynamic Recompilation (WIP, don't use yet)" ${ARM_DYNAREC})
option(NOGETCLOCK "Set to ON to avoid using clock_gettime with CLOCK_MONOTONIC_COARSE for RDTSC opcode (use gltimeofday instead)" ${NOGETCLOCK})
if(${CMAKE_VERSION} VERSION_LESS "3.12.2")
find_package(PythonInterp 3)
@@ -37,6 +38,16 @@ else()
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE} CACHE INTERNAL "The Python3 executable" FORCE)
endif()
if(RK3399)
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)
endif()
project(box86 C ASM)
enable_testing()
set(default_build_type "RelwithDebInfo")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
@@ -44,69 +55,63 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
# Pandora
if(PANDORA)
add_definitions(-DPANDORA)
#add_definitions(-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize -fsingle-precision-constant -ffast-math)
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
# Gameshell
if(GAMESHELL)
add_definitions(-DGAMEHELL)
add_definitions(-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(PYRA)
add_definitions(-DPYRA)
add_definitions(-mcpu=cortex-a15 -mfpu=neon -mfloat-abi=hard -marm)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a15 -mfpu=neon -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(RPI2)
add_definitions(-DRPI)
add_definitions(-DRPI2)
add_definitions(-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(RPI3)
add_definitions(-DRPI)
add_definitions(-DRPI3)
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")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(RPI4)
add_definitions(-DRPI)
add_definitions(-DRPI3)
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")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(ODROID)
add_definitions(-DODROID)
add_definitions(-mcpu=cortex-a9 -mfpu=neon-vfpv4 -mfloat-abi=hard -marm)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a9 -mfpu=neon-vfpv4 -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(RK3399)
add_definitions(-DRK3399)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto")
endif()
set(BOX86_ELF_ADDRESS "0x02800000")
if(NOGIT)
add_definitions(-DNOGIT)
endif()
if(BOX86LIB)
set(BOX86 box86)
elseif(HAVE_TRACE)
set(BOX86 box86t)
else()
set(BOX86 box86)
endif()
set(BOX86_ELF_ADDRESS "0x62800000")
if(LD80BITS)
add_definitions(-DHAVE_LD80BITS)
@@ -120,10 +125,6 @@ if(HAVE_TRACE)
add_definitions(-DHAVE_TRACE)
endif()
if(USE_FLOAT)
add_definitions(-DUSE_FLOAT)
endif()
if(ARM_DYNAREC)
add_definitions(-DDYNAREC)
add_definitions(-DARM)
@@ -145,11 +146,11 @@ if(BOX86LIB)
message(FATAL_ERROR "BOX86_ROOT not set when build as lib")
endif()
else()
set(BOX86_ROOT ${CMAKE_HOME_DIRECTORY})
set(BOX86_ROOT ${CMAKE_SOURCE_DIR})
endif()
add_definitions(-std=gnu99 -funwind-tables -fvisibility=hidden)
add_definitions(-std=gnu11 -funwind-tables -fvisibility=hidden)
if(USE_CCACHE)
find_program(CCACHE_FOUND ccache)
@@ -165,15 +166,13 @@ include_directories(
"${BOX86_ROOT}/src/wrapped/generated"
)
add_custom_command(
OUTPUT "${BOX86_ROOT}/src/git_head.h"
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\"\>${BOX86_ROOT}/src/git_head.h"
DEPEND "${BOX86_ROOT}/src/build_info.c"
VERBATIM
)
# git_head.h is a generated file
set_source_files_properties(
"${BOX86_ROOT}/src/git_head.h"
PROPERTIES GENERATED TRUE
HEADER_FILE_ONLY TRUE)
set(ELFLOADER_SRC
"${BOX86_ROOT}/src/git_head.h"
"${BOX86_ROOT}/src/main.c"
"${BOX86_ROOT}/src/box86context.c"
"${BOX86_ROOT}/src/build_info.c"
@@ -193,6 +192,7 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/emu/x86emu.c"
"${BOX86_ROOT}/src/emu/x86run.c"
"${BOX86_ROOT}/src/emu/x86run66.c"
"${BOX86_ROOT}/src/emu/x86run660f.c"
"${BOX86_ROOT}/src/emu/x86run_private.c"
"${BOX86_ROOT}/src/emu/x86syscall.c"
"${BOX86_ROOT}/src/emu/x86primop.c"
@@ -210,6 +210,7 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/libtools/sdl2rwops.c"
"${BOX86_ROOT}/src/libtools/signals.c"
"${BOX86_ROOT}/src/libtools/threads.c"
"${BOX86_ROOT}/src/libtools/vkalign.c"
"${BOX86_ROOT}/src/dynarec/dynarec.c"
"${BOX86_ROOT}/src/wrapped/generated/wrapper.c"
)
@@ -231,6 +232,7 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedsdl2.c"
"${BOX86_ROOT}/src/wrapped/wrappedsdl2mixer.c"
"${BOX86_ROOT}/src/wrapped/wrappedsdl2image.c"
"${BOX86_ROOT}/src/wrapped/wrappedsdl2ttf.c"
"${BOX86_ROOT}/src/wrapped/wrappedsmpeg.c"
"${BOX86_ROOT}/src/wrapped/wrappedsmpeg2.c"
"${BOX86_ROOT}/src/wrapped/wrappedvorbisfile.c"
@@ -252,6 +254,16 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedlibxdmcp.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibx11xcb.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcb.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbxfixes.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbshape.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbshm.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbrandr.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbimage.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbkeysyms.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbxtest.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbdri2.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbdri3.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbpresent.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxtst.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxt.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcomposite.c"
@@ -261,6 +273,8 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedopenal.c"
"${BOX86_ROOT}/src/wrapped/wrappedalut.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibjpeg.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibjpeg62.c"
"${BOX86_ROOT}/src/wrapped/wrappedturbojpeg.c"
"${BOX86_ROOT}/src/wrapped/wrappedcurl.c"
"${BOX86_ROOT}/src/wrapped/wrappedudev0.c"
"${BOX86_ROOT}/src/wrapped/wrappedudev1.c"
@@ -289,6 +303,8 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedlibtinfo6.c"
"${BOX86_ROOT}/src/wrapped/wrappedgtkx112.c"
"${BOX86_ROOT}/src/wrapped/wrappedgdkx112.c"
"${BOX86_ROOT}/src/wrapped/wrappedgtk3.c"
"${BOX86_ROOT}/src/wrapped/wrappedgdk3.c"
"${BOX86_ROOT}/src/wrapped/wrappedgdkpixbuf2.c"
"${BOX86_ROOT}/src/wrapped/wrappedgio2.c"
"${BOX86_ROOT}/src/wrapped/wrappedgmodule2.c"
@@ -298,6 +314,7 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedgstinterfaces010.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenugtk.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenuglib.c"
"${BOX86_ROOT}/src/wrapped/wrappedappindicator.c"
"${BOX86_ROOT}/src/wrapped/wrappedatk.c"
"${BOX86_ROOT}/src/wrapped/wrappedpangoft2.c"
"${BOX86_ROOT}/src/wrapped/wrappedpangocairo.c"
@@ -310,10 +327,20 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedtcmallocminimal.c"
"${BOX86_ROOT}/src/wrapped/wrappedmpg123.c"
"${BOX86_ROOT}/src/wrapped/wrappedgnutls.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibcups.c"
"${BOX86_ROOT}/src/wrapped/wrappedd3dadapter9.c"
"${BOX86_ROOT}/src/wrapped/wrappedvulkan.c"
"${BOX86_ROOT}/src/wrapped/wrappedwaylandclient.c"
"${BOX86_ROOT}/src/wrapped/wrappedxml2.c"
"${BOX86_ROOT}/src/wrapped/wrappedxslt.c"
"${BOX86_ROOT}/src/wrapped/wrappedldapr.c"
"${BOX86_ROOT}/src/wrapped/wrappedlber.c"
"${BOX86_ROOT}/src/wrapped/wrappedlcms2.c"
"${BOX86_ROOT}/src/wrapped/wrappednsl.c"
"${BOX86_ROOT}/src/wrapped/wrappedldlinux.c"
)
set(WRAPPEDS_HEAD "")
set(WRAPPEDS_HEAD "${BOX86_ROOT}/src/wrapped/wrappedd3dadapter9_gen.h")
foreach(A ${WRAPPEDS})
string(REPLACE ".c" "_private.h" B ${A})
set(WRAPPEDS_HEAD ${WRAPPEDS_HEAD} ${B})
@@ -324,7 +351,7 @@ set(WRAPPER "${BOX86_ROOT}/src/wrapped/generated/wrapper.c" "${BOX86_ROOT}/src/w
add_custom_command(
OUTPUT "${BOX86_ROOT}/src/wrapped/generated/functions_list.txt"
COMMAND "${PYTHON_EXECUTABLE}" "${BOX86_ROOT}/rebuild_wrappers.py" "${BOX86_ROOT}" "PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "USE_FLOAT" "--" ${WRAPPEDS_HEAD}
COMMAND "${PYTHON_EXECUTABLE}" "${BOX86_ROOT}/rebuild_wrappers.py" "${BOX86_ROOT}" "PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "--" ${WRAPPEDS_HEAD}
MAIN_DEPENDENCY "${BOX86_ROOT}/rebuild_wrappers.py"
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
BYPRODUCTS ${WRAPPER}
@@ -341,9 +368,6 @@ add_custom_command(
add_custom_target(WRAPPERS DEPENDS "${BOX86_ROOT}/src/wrapped/generated/functions_list.txt")
add_custom_target(PRINTER DEPENDS "${BOX86_ROOT}/src/dynarec/last_run.txt")
#this is to force build_info.c to be rebuilt all the time
set_source_files_properties("${BOX86_ROOT}/src/build_info.c" PROPERTIES OBJECT_OUTPUTS "dummy.c")
if(ARM_DYNAREC)
set(DYNAREC_SRC
"${BOX86_ROOT}/src/dynarec/dynablock.c"
@@ -356,6 +380,7 @@ if(ARM_DYNAREC)
"${BOX86_ROOT}/src/dynarec/arm_epilog.S"
"${BOX86_ROOT}/src/dynarec/arm_linker.S"
"${BOX86_ROOT}/src/dynarec/arm_table.S"
"${BOX86_ROOT}/src/dynarec/arm_lock_helper.S"
)
set(DYNAREC_PASS
@@ -409,37 +434,48 @@ if(ARM_DYNAREC)
$<TARGET_OBJECTS:arm_pass2>
$<TARGET_OBJECTS:arm_pass3>
)
endif()
# creates git_head.h
if(ARM_DYNAREC)
add_custom_command(
OUTPUT "${BOX86_ROOT}/src/git_head.h"
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX86_ROOT}/src/git_head.h\""
DEPENDS dynarec ${ELFLOADER_SRC} ${WRAPPEDS}
VERBATIM)
else()
add_custom_command(
OUTPUT "${BOX86_ROOT}/src/git_head.h"
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX86_ROOT}/src/git_head.h\""
DEPENDS ${ELFLOADER_SRC} ${WRAPPEDS}
VERBATIM)
endif()
if(BOX86LIB)
#build a static or dynamic lib...
if(BOX86DYNAMIC)
add_library(box86 SHARED ${ELFLOADER_SRC} ${WRAPPEDS})
add_library(box86 SHARED ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head.h")
else()
add_library(box86 OBJECT ${ELFLOADER_SRC} ${WRAPPEDS})
add_library(${BOX86} OBJECT ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head.h")
endif()
if(ARM_DYNAREC)
target_link_libraries(box86 dynarec m dl rt pthread)
target_link_libraries(${BOX86} dynarec m dl rt pthread)
endif()
if(${CMAKE_VERSION} VERSION_LESS "3.13")
set_target_properties(box86 PROPERTIES LINK_FLAGS -rdynamic)
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS -rdynamic)
else()
target_link_options(box86 PUBLIC -rdynamic)
target_link_options(${BOX86} PUBLIC -rdynamic)
endif()
add_dependencies(box86 WRAPPERS)
add_dependencies(box86 PRINTER)
add_dependencies(${BOX86} WRAPPERS)
add_dependencies(${BOX86} PRINTER)
add_custom_target(buildinfo ${BOX86}
DEPENDS dynarec ${BOX86} )
else(BOX86LIB)
if(USE_FLOAT)
set(BOX86 box86f)
elseif(HAVE_TRACE)
set(BOX86 box86t)
else()
set(BOX86 box86)
endif()
add_executable(${BOX86} ${ELFLOADER_SRC} ${WRAPPEDS})
add_executable(${BOX86} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head.h")
add_dependencies(${BOX86} WRAPPERS)
add_dependencies(${BOX86} PRINTER)
target_link_libraries(${BOX86} m dl rt pthread)
@@ -466,7 +502,8 @@ string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
if(NOT _x86 AND NOT _x86_64)
install(TARGETS ${BOX86}
RUNTIME DESTINATION bin)
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.conf DESTINATION /etc/binfmt.d/)
configure_file(system/box86.conf.cmake system/box86.conf)
install(FILES ${CMAKE_BINARY_DIR}/system/box86.conf DESTINATION /etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION /usr/lib/i386-linux-gnu/)
+18 -1
View File
@@ -16,7 +16,14 @@ Compiling
_a build for model 2, 3 and 4 can be done. Model 1 and 0 cannot (at least not with Dynarec, as they lack NEON support)_
`mkdir build; cd build; cmake .. -DRPI4=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
```
git clone https://github.com/ptitSeb/box86
cd box86
mkdir build; cd build; cmake .. -DRPI4=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
sudo systemctl restart systemd-binfmt
```
_For Pi4. Change to RPI2 or RPI3 for other models._
@@ -24,6 +31,12 @@ Compiling
`mkdir build; cd build; cmake .. -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
#### for RK3399
`mkdir build; cd build; cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
As most RK3399 device run AARCH64 OS, you'll need an `armhf` multiarch env, and an armhf gcc: use `sudo apt install gcc-arm-linux-gnueabihf` to install it.
#### for Other ARM Linux
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
@@ -54,6 +67,10 @@ To have a trace enabled build (warning, it will be slower), add `-DHAVE_TRACE=1`
The Dynarec is only avaiable on ARM Cpu. Notes also that VFPv3 and NEON are required for the Dynarec. Activate it by using `-DARM_DYNAREC=1`. Also, be sure to use `-marm` in compilation flags (because many compileur use Thumb as default, and the dynarec will not work in this mode).
*not building from a git clone*
If you are not building from a git clone (for example downloading a release sources Zipped from github), you need to activate `-DNOGIT=1` from cmake to be able to build (normal process include git sha1 of HEAD in the version that box86 print).
----
Testing
+24 -2
View File
@@ -5,7 +5,7 @@ Linux Userspace x86 Emulator with a twist
Box86 lets you run x86 Linux programs (such as games) on non-x86 Linux, like ARM (host system needs to be 32bit little-endian).
You *NEED* a 32-bit subsystem to run and build Box86. Box86 is useless on 64-bit only systems. Also, you *NEED* a 32-bit toolchain to build Box86. A toolchain that only support 64-bit will not compile Box86, and you'll get errors (typically on aarch64, you get "-marm" not recognized).
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 support 64-bit will not compile Box86, and you'll get errors (typically on aarch64, you get "-marm" not recognized, and you'll need a multiarch or chroot environnement).
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use, and performance can be surprisingly high in some cases.
@@ -32,6 +32,16 @@ Compatibility list is there: https://github.com/ptitSeb/box86-compatibility-list
Logo and Icon made by @grayduck, thanks!
Note that this project is not to be mystaken with [86box](https://github.com/86Box/86Box), a nice "Full system" emulator specialized in early (to fairly recent) PC hardware.
----
Discord
----
If you want to discuss about box86 on Discord, there is a frendly server there: [PI Lab Discord](https://discord.gg/Fh8sjmu)
----
Compiling
@@ -73,7 +83,18 @@ A note 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 he new "protected memory" mechanism implemented it is 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 Mono games work and can require a high OpenGL profile, but the speed, for the ones running, should be correct 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.
----
A note about Steam
----
Linux Steam can run now with box86. But it's still a bit unstable., and not everything works. First is steam crashes after the Sign in, you may need to add libappindicator. On debian it's `sudo apt install libappindicator1`.
Once open, Steam will only work on "Small mode" and in "Big Picture", not in the regular "Browser mode". So go in the "View" menu and witch to Small view (or Compact view?), else the list will stay empty (this is because some steam component used in the browser view are only 64bits now).
Final word, to avoid the "libc.so.6 is absent" message, you can use `STEAMOS=1` and `STEAM_RUNTIME=1` export.
(Steam for Windows install fine but doesn't work yet)
Some steam games (most of Source engine one, like "Portal" or "Half-Life 2") use libtcmalloc. Box86 will detect it's use and will try to LD_PRELOAD it, for better compatibility. While it should work without, it is better to add it to your system if you intend to play those game (something like `sudo apt install libtcmalloc-minimal4` on debian familly)
----
@@ -81,6 +102,7 @@ A note about Wine
----
Wine is now partly supported. Wine integreted program all runs, annd some windows program and games now run fine. Don't forget most Windows games use Direct3D, that may require a complete OpenGL driver and as high profile as possible (and gl4es with ES2 backend have issue with Wine for now). Also, vulkan is not wrapped on box86, so vk3d is not usable yet, even if supported by the hardware.
A not if you plan to use box86 with wine on Raspberry PI 3 or earlier: those model use a default OS that have a kernle with a 2/2 Split (meaning 2G of space for user program, and 2G of space for Kernel). This is not compatible with wine, that need to access memory > 2Gb address. So you'll need to reconfigure your kernel for a 3G/1G split. Use your favorite search engine to find tutos on how to do that.
----
+26 -1
View File
@@ -3,7 +3,7 @@ Usage
There are many environment variable to control Box86 behaviour.
##### BOX86_LOG
#### BOX86_LOG
Controls the Verbose level of the log
* 0
* NONE : No message (except some fatal error)
@@ -14,6 +14,11 @@ Controls the Verbose level of the log
* 3
* DUMP : All DEBUG plus DUMP of all ELF Info
#### BOX86_NOBANNER
Control Box86 printing it's version and build
* 0 : Enabled the printing
* 1 : Diable the printing
#### BOX86_LD_LIBRARY_PATH
Controls the folder scanned to look for x86 libs. Default is current folder and `lib` in current folder.
Also `/usr/lib/i386-linux-gnu` and `/lib/i386-linux-gnu` are added if they exists
@@ -103,6 +108,10 @@ Set level of DynaRec log
* 0 : Disable Dynarec Linker (use that on debug, with dynarec log >= 2, to have detail on wich block get executed)
* 1 : Enable Dynarec Linker (default)
#### BOX86_DYNAREC_SAFEMMAP
* 0 : Default. Some mmp/mmap64 are consider unsafe (depending of flags mainly)
* 1 : Consider all mmap/mmap64 safe to use linker (potential speedup, but potential crash for apps using JIT/Dynarec)
#### BOX86_DYNAREC_TRACE
* 0 : Disable trace for generated code (default)
* 1 : Enable trace for generated code (like regular Trace, this will slow down a lot and generate huge logs)
@@ -126,7 +135,23 @@ Allow box86 to continue even if a lib is missing
* 0 : default, stop if a lib cannot be loaded
* 1 : continue even if a needed lib cannot be loaded. Unadvised, this will, in most cases, crash later on.
#### BOX86_NOPULSE
Disable the load of pulseaudio libs
* 0 : default, load pulseaudio libs if present
* 1 : disable the load of pulse audio libs (libpulse and libpulse-simple), both native and x86 version
#### BOX86_NOGTK
Disable the load of wrapped gtk libs
* 0 : default, load wrapped gtk libs if present
* 1 : disable the load of wrapped gtk libs (can be used with Steam, along with STEAM_RUNTIME=1 to use i386 versio of gtk)
#### BOX86_FIX_64BIT_INODES
* 0 : Don't fix 64bit inodes (default)
* 1 : Fix 64bit inodes. Helps when running on filesystems with 64bit inodes, the program uses API functions which don't support it and the program doesn't use inodes information.
#### 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.
When in gdb, you need to find the correct thread yourself (the one with `my_box86signalhandler` in is stack)
then probably need to `finish` 1 or 2 functions (inside `usleep(..)`) and then you'll be in `my_box86signalhandler`,
just before the printf of the Segfault message. Then simply `set waiting=0` to exit the infinite loop.
+38
View File
@@ -0,0 +1,38 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier
pkgname=box86-arm-git
pkgver=r2798.0edc0374
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}")
conflicts=("${pkgname%-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-git}/build"
make DESTDIR="${pkgdir}/" install
}
+38
View File
@@ -0,0 +1,38 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier
pkgname=box86-gameshell-git
pkgver=r2798.0edc0374
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}")
conflicts=("${pkgname%-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DGAMESHELL=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-git}/build"
make DESTDIR="${pkgdir}/" install
}
+38
View File
@@ -0,0 +1,38 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier
pkgname=box86-odroid-git
pkgver=r2798.0edc0374
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}")
conflicts=("${pkgname%-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-git}/build"
make DESTDIR="${pkgdir}/" install
}
+38
View File
@@ -0,0 +1,38 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier
pkgname=box86-pandora-git
pkgver=r2798.0edc0374
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}")
conflicts=("${pkgname%-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DPANDORA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-git}/build"
make DESTDIR="${pkgdir}/" install
}
+38
View File
@@ -0,0 +1,38 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier
pkgname=box86-pyra-git
pkgver=r2798.0edc0374
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}")
conflicts=("${pkgname%-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DPYRA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-git}/build"
make DESTDIR="${pkgdir}/" install
}
+52
View File
@@ -0,0 +1,52 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier
pkgname=box86-rpi-git
pkgver=r2798.0edc0374
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}")
conflicts=("${pkgname%-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
_pimodel=`tr -d '\0' < /sys/firmware/devicetree/base/model`
pkgver() {
cd "$srcdir/${pkgname%-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-git}"
# Check for Pi version number
if [[ ${_pimodel} ~= "Raspberry Pi 4" ]]; then
_piversion=4
elif [[ ${_pimodel} ~= "Raspberry Pi 3" ]]; then
_piversion=3
elif [[ ${_pimodel} ~= "Raspberry Pi 2" ]]; then
_piversion=2
else
# Your RPI is not supported or this device is not a pi, cancel build then
echo -e "\033[01m\033[01;31m==> ERROR:\033[00;01m Your device is not supported! This script is for RPi model 4/3/2 (1/0 not supported).\033[00m"
exit 1
fi
echo -e "\033[01m\033[01;34m==> INFO:\033[00;01m Your detected Pi verion number is: \033[01;31m${_piversion}\033[01m.\033[00m"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRPI${_piversion}=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-git}/build"
make DESTDIR="${pkgdir}/" install
}
+37
View File
@@ -0,0 +1,37 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier
pkgname=box86-x86-git
pkgver=r2798.0edc0374
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('i386')
url="https://github.com/ptitSeb/box86"
license=('MIT')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}")
conflicts=("${pkgname%-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-git}/build"
make DESTDIR="${pkgdir}/" install
}
+21
View File
@@ -0,0 +1,21 @@
# The directory containing all PKGBUILDs for BOX86
## FAQ
### 1. How to use it?
Just download the `PKGBUILD-<your-platform>` (no need to download the whole repository), go to directory where you downloaded and type:
```sh
mv ./PKGBUILD-<your-platform> ./PKGBUILD
cd ..
makepkg -si
```
This will copy the PKGBUILD for your platform (where you type your platform name instead of `<your-platform>`), build it and install the PKGBUILD on 32-bit Archlinux ARM.
In the future, I might try to do an unified PKGBUILD for all platforms that will recognize your platform automatically.
### 2. What platforms are currently supported.
All specified in [COMPILE.md](../COMPILE.md).
### 3. Any advantages with that sollution?
This might give you some advantages like those:
- automatic updates (with some AUR frontends like [`pamac-aur`](https://aur.archlinux.org/packages/pamac-aur/) or [`yay`](https://aur.archlinux.org/packages/yay));
- easily uninstall with `pacman -R` when no needed (no need other scripts nor Makefile to do this);
- your `box86` installation is recognized as a package (where it wasn't when installing with `make install`).
+5 -5
View File
@@ -575,11 +575,11 @@ def main(root, ver, __debug_forceAllDebugging=False):
append("int rot = (opcode >> " + str(variables["r"]) + ") & 3;\nchar tmprot[8] = {0};\n")
append("if (rot) {\nsprintf(tmprot, \" ror %d\", rot * 8);\n}\n")
if variables["sb"][0] != -1:
append("int lsb = (opcode >> " + str(variables["sb"][0]) + ") & 0xF;\n")
append("int lsb = (opcode >> " + str(variables["sb"][0]) + ") & 0x1F;\n")
if variables["sb"][1] != -1:
append("int msb = (opcode >> " + str(variables["sb"][1]) + ") & 0xF;\n")
append("int msb = (opcode >> " + str(variables["sb"][1]) + ") & 0x1F;\n")
if variables["sb"][2] != -1:
append("int widthm1 = (opcode >> " + str(variables["sb"][2]) + ") & 0xF;\n")
append("int widthm1 = (opcode >> " + str(variables["sb"][2]) + ") & 0x1F;\n")
if variables["reglist16"] != -1:
append("int reglist = (opcode >> " + str(variables["reglist16"]) + ") & 0xFFFF;\n")
if imms != []:
@@ -1105,7 +1105,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
l = len(imms) == 2
if l:
append("uint8_t l = (opcode >> " + str(imms[1][1]) + ") & 0x1;\n")
append("uint8_t l = (opcode >> " + str(imms[1][0]) + ") & 0x1;\n")
immssz = 6
append("uint8_t imm6 = (opcode >> " + str(imms[0][0]) + ") & 0x3F;\n")
@@ -1774,7 +1774,7 @@ const char* print_shift(int shift, int comma) {
return ret;
}
#define print_modified_imm_ARM(imm12) (((imm12 & 0xFF) >> (imm12 >> 8)) | ((imm12 & 0xFF) << (32 - (imm12 >> 8))))
#define print_modified_imm_ARM(imm12) (((imm12 & 0xFF) >> (2*(imm12 >> 8))) | ((imm12 & 0xFF) << (32 - 2*(imm12 >> 8))))
const char* print_register_list(int list, int size) {
int last = -2;
+127 -65
View File
@@ -3,7 +3,7 @@
import os
import sys
values = ['E', 'e', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S']
values = ['E', 'e', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', '2', 'P', 'G']
def splitchar(s):
try:
ret = [len(s), values.index(s[0])]
@@ -230,6 +230,11 @@ typedef union ui64_s {
uint32_t d[2];
} ui64_t;
typedef struct _2uint_struct_s {
uint32_t a;
uint32_t b;
} _2uint_struct_t;
extern void* my__IO_2_1_stderr_;
extern void* my__IO_2_1_stdin_ ;
extern void* my__IO_2_1_stdout_;
@@ -247,11 +252,35 @@ static void* io_convert(void* v)
return v;
}
#ifdef USE_FLOAT
#define ST0val ST0.f
#else
typedef struct my_GValue_s
{
int g_type;
union {
int v_int;
int64_t v_int64;
uint64_t v_uint64;
float v_float;
double v_double;
void* v_pointer;
} data[2];
} my_GValue_t;
static void alignGValue(my_GValue_t* v, void* value)
{
v->g_type = *(int*)value;
memcpy(v->data, value+4, 2*sizeof(double));
}
static void unalignGValue(void* value, my_GValue_t* v)
{
*(int*)value = v->g_type;
memcpy(value+4, v->data, 2*sizeof(double));
}
void* VulkanFromx86(void* src, void** save);
void VulkanTox86(void* src, void* save);
#define ST0val ST0.d
#endif
int of_convert(int);
""",
"wrapper.h": """/*****************************************************************
@@ -260,6 +289,7 @@ int of_convert(int);
#ifndef __WRAPPER_H_
#define __WRAPPER_H_
#include <stdint.h>
#include <string.h>
typedef struct x86emu_s x86emu_t;
@@ -279,7 +309,9 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
// O = libc O_ flags bitfield
// S = _IO_2_1_stdXXX_ pointer (or FILE*)
// Q = ...
// S8 = struct, 8 bytes
// 2 = struct of 2 uint
// P = Vulkan struture pointer
// G = a single GValue pointer
"""
}
@@ -315,8 +347,8 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
# First part: typedefs
for v in gbl["()"]:
# E e v c w i I C W u U f d D K l L p V O S
types = ["x86emu_t*", "x86emu_t**", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*"]
# E e v c w i I C W u U f d D K l L p V O S 2 P G
types = ["x86emu_t*", "x86emu_t**", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "_2uint_struct_t", "void*", "void*"]
if len(values) != len(types):
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
@@ -325,8 +357,8 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
for k in gbl_idxs:
file.write("\n#if " + k + "\n")
for v in gbl[k]:
# E e v c w i I C W u U f d D K l L p V O S
types = ["x86emu_t*", "x86emu_t**", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*"]
# E e v c w i I C W u U f d D K l L p V O S 2 P G
types = ["x86emu_t*", "x86emu_t**", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "_2uint_struct_t", "void*", "void*"]
if len(values) != len(types):
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
@@ -335,8 +367,72 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
file.write("#endif\n")
file.write("\n")
# Next part: function definitions
# Helper variables
arg = [
"emu, ", # E
"&emu, ", # e
"", # v
"*(int8_t*)(R_ESP + {p}), ", # c
"*(int16_t*)(R_ESP + {p}), ", # w
"*(int32_t*)(R_ESP + {p}), ", # i
"*(int64_t*)(R_ESP + {p}), ", # I
"*(uint8_t*)(R_ESP + {p}), ", # C
"*(uint16_t*)(R_ESP + {p}), ", # W
"*(uint32_t*)(R_ESP + {p}), ", # u
"*(uint64_t*)(R_ESP + {p}), ", # U
"*(float*)(R_ESP + {p}), ", # f
"*(double*)(R_ESP + {p}), ", # d
"*(long double*)(R_ESP + {p}), ", # D
"FromLD((void*)(R_ESP + {p})), ", # K
"*(intptr_t*)(R_ESP + {p}), ", # l
"*(uintptr_t*)(R_ESP + {p}), ", # L
"*(void**)(R_ESP + {p}), ", # p
"(void*)(R_ESP + {p}), ", # V
"of_convert(*(int32_t*)(R_ESP + {p})), ", # O
"io_convert(*(void**)(R_ESP + {p})), ", # S
"(_2uint_struct_t){{*(uintptr_t*)(R_ESP + {p}),*(uintptr_t*)(R_ESP + {p} + 4)}}, ", #2
"arg{p}, ", # P
"&arg{p}, ", # G
]
# E e v c w i I C W u U f d D K l L p V O S 2 P G
deltas = [0, 0, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 8, 12, 12, 4, 4, 4, 0, 4, 4, 8, 4, 4]
vals = [
"\n#error Invalid return type: emulator\n", # E
"\n#error Invalid return type: &emulator\n", # e
"fn({0});", # v
"R_EAX=fn({0});", # c
"R_EAX=fn({0});", # w
"R_EAX=fn({0});", # i
"ui64_t r; r.i=fn({0}); R_EAX=r.d[0]; R_EDX=r.d[1];", # I
"R_EAX=(unsigned char)fn({0});", # C
"R_EAX=(unsigned short)fn({0});", # W
"R_EAX=(uint32_t)fn({0});", # u
"ui64_t r; r.u=(uint64_t)fn({0}); R_EAX=r.d[0]; R_EDX=r.d[1];", # U
"float fl=fn({0}); fpu_do_push(emu); ST0val = fl;", # f
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # d
"long double ld=fn({0}); fpu_do_push(emu); ST0val = ld;", # D
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # K
"R_EAX=(intptr_t)fn({0});", # l
"R_EAX=(uintptr_t)fn({0});", # L
"R_EAX=(uintptr_t)fn({0});", # p
"\n#error Invalid return type: va_list\n", # V
"\n#error Invalid return type: at_flags\n", # O
"\n#error Invalid return type: _io_file*\n", # S
"\n#error Invalid return type: _2uint_struct\n", # 2
"\n#error Invalid return type: Vulkan Struct\n", # P
"\n#error Invalid return type: GValue Pointer\n", # G
]
# Asserts
if len(values) != len(arg):
raise NotImplementedError("len(values) = {lenval} != len(arg) = {lenarg}".format(lenval=len(values), lenarg=len(arg)))
if len(values) != len(deltas):
raise NotImplementedError("len(values) = {lenval} != len(deltas) = {lendeltas}".format(lenval=len(values), lendeltas=len(deltas)))
if len(values) != len(vals):
raise NotImplementedError("len(values) = {lenval} != len(vals) = {lenvals}".format(lenval=len(values), lenvals=len(vals)))
# Helper functions to write the function definitions
def function_args(args, d=4):
if len(args) == 0:
@@ -349,65 +445,31 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
elif args[0] == "1":
return "1, " + function_args(args[1:], d)
arg = [
"emu, ", # E
"&emu, ", # e
"", # v
"*(int8_t*)(R_ESP + {p}), ", # c
"*(int16_t*)(R_ESP + {p}), ", # w
"*(int32_t*)(R_ESP + {p}), ", # i
"*(int64_t*)(R_ESP + {p}), ", # I
"*(uint8_t*)(R_ESP + {p}), ", # C
"*(uint16_t*)(R_ESP + {p}), ", # W
"*(uint32_t*)(R_ESP + {p}), ", # u
"*(uint64_t*)(R_ESP + {p}), ", # U
"*(float*)(R_ESP + {p}), ", # f
"*(double*)(R_ESP + {p}), ", # d
"*(long double*)(R_ESP + {p}), ", # D
"FromLD((void*)(R_ESP + {p})), ", # K
"*(intptr_t*)(R_ESP + {p}), ", # l
"*(uintptr_t*)(R_ESP + {p}), ", # L
"*(void**)(R_ESP + {p}), ", # p
"(void*)(R_ESP + {p}), ", # V
"of_convert(*(int32_t*)(R_ESP + {p})), ", # O
"io_convert(*(void**)(R_ESP + {p})), ", # S
]
# E e v c w i I C W u U f d D K l L p V O S
deltas = [0, 0, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 8, 12, 12, 4, 4, 4, 0, 4, 4]
if len(values) != len(arg):
raise NotImplementedError("len(values) = {lenval} != len(arg) = {lenarg}".format(lenval=len(values), lenarg=len(arg)))
if len(values) != len(deltas):
raise NotImplementedError("len(values) = {lenval} != len(deltas) = {lendeltas}".format(lenval=len(values), lendeltas=len(deltas)))
return arg[values.index(args[0])].format(p=d) + function_args(args[1:], d + deltas[values.index(args[0])])
def function_writer(f, N, W, rettype, args):
f.write("void {0}(x86emu_t *emu, uintptr_t fcn) {2} {1} fn = ({1})fcn; ".format(N, W, "{"))
vals = [
"\n#error Invalid return type: emulator\n", # E
"\n#error Invalid return type: &emulator\n", # e
"fn({0});", # v
"R_EAX=fn({0});", # c
"R_EAX=fn({0});", # w
"R_EAX=fn({0});", # i
"ui64_t r; r.i=fn({0}); R_EAX=r.d[0]; R_EDX=r.d[1];", # I
"R_EAX=(unsigned char)fn({0});", # C
"R_EAX=(unsigned short)fn({0});", # W
"R_EAX=(uint32_t)fn({0});", # u
"ui64_t r; r.u=(uint64_t)fn({0}); R_EAX=r.d[0]; R_EDX=r.d[1];", # U
"float fl=fn({0}); fpu_do_push(emu); ST0val = fl;", # f
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # d
"long double ld=fn({0}); fpu_do_push(emu); ST0val = ld;", # D
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # K
"R_EAX=(intptr_t)fn({0});", # l
"R_EAX=(uintptr_t)fn({0});", # L
"R_EAX=(uintptr_t)fn({0});", # p
"\n#error Invalid return type: va_list\n", # V
"\n#error Invalid return type: at_flags\n", # O
"\n#error Invalid return type: _io_file*\n", # S
]
if len(values) != len(vals):
raise NotImplementedError("len(values) = {lenval} != len(vals) = {lenvals}".format(lenval=len(values), lenvals=len(vals)))
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " }\n")
if any(cc in 'PG' for cc in args):
# Vulkan struct or GValue pointer, need to unwrap functions at the end
delta = 4
for c in args:
if c == 'P':
f.write("void* save{d}=NULL; void *arg{d} = VulkanFromx86(*(void**)(R_ESP + {d}), &save{d}); ".format(d=delta))
if c == 'G':
f.write("my_GValue_t arg{d}; alignGValue(&arg{d}, *(void**)(R_ESP + {d})); ".format(d=delta))
delta = delta + deltas[values.index(c)]
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " ")
delta = 4
for c in args:
if c == 'P':
f.write("VulkanTox86(arg{d}, save{d}); ".format(d=delta))
if c == 'G':
f.write("unalignGValue(*(void**)(R_ESP + {d}), &arg{d}); ".format(d=delta))
delta = delta + deltas[values.index(c)]
f.write("}\n")
else:
# Generic function
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " }\n")
for v in gbl["()"]:
function_writer(file, v, v + "_t", v[0], v[2:])
+1
View File
@@ -13,6 +13,7 @@ if( NOT TEST_REFERENCE )
endif( NOT TEST_REFERENCE )
set(ENV{BOX86_LOG} 0)
set(ENV{BOX86_NOBANNER} 1)
if( EXISTS ${CMAKE_SOURCE_DIR}/x86lib )
# we are inside box86 folder
set(ENV{LD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/x86lib)
+317 -152
View File
@@ -22,170 +22,303 @@
#ifdef DYNAREC
#include <sys/mman.h>
#include "dynablock.h"
#include "khash.h"
#define MMAPSIZE (4*1024*1024) // allocate 4Mo sized blocks
#define MMAPBLOCK 256 // minimum size of a block
#define MMAPSIZE (256*1024) // allocate 256kb sized blocks
// init inside dynablocks.c
KHASH_MAP_INIT_INT(dynablocks, dynablock_t*)
typedef union mark_s {
struct {
unsigned int fill:1;
unsigned int size:31;
};
uint32_t x32;
} mark_t;
typedef struct blockmark_s {
mark_t prev;
mark_t next;
} blockmark_t;
typedef struct mmaplist_s {
void* block;
uint8_t map[MMAPSIZE/(8*MMAPBLOCK)]; // map of allocated sub-block
void* block;
int maxfree;
kh_dynablocks_t* dblist;
} mmaplist_t;
// get first subblock free in map, stating at start. return -1 if no block, else first subblock free, filling size (in subblock unit)
static int getFirstBlock(mmaplist_t *map, int start, int maxsize, int* size)
// get first subblock free in block, stating at start (from block). return NULL if no block, else first subblock free (mark included), filling size
static void* getFirstBlock(void* block, int maxsize, int* size)
{
#define ISFREE(A) (((map->map[(A)>>3]>>((A)&7))&1)?0:1)
if(start<0) start = 0;
while(start<MMAPSIZE/(8*MMAPBLOCK)) { // still a chance...
if(ISFREE(start)) {
// free, now get size...
int end = start+1;
while(end<MMAPSIZE/(8*MMAPBLOCK)) {
if(!ISFREE(end) || (end-start==maxsize)) {
if(size) *size = end-start;
return start;
}
++end;
}
if(size) *size = end-start;
return start;
// get start of block
blockmark_t *m = (blockmark_t*)block;
while(m->next.x32) { // while there is a subblock
if(!m->next.fill && m->next.size>=maxsize+sizeof(blockmark_t)) {
*size = m->next.size;
return m;
}
++start;
m = (blockmark_t*)((uintptr_t)m + m->next.size);
}
return -1;
return NULL;
}
static void allocBlock(mmaplist_t *map, int start, int size)
static int getMaxFreeBlock(void* block)
{
for(int i=0; i<size; ++i) {
map->map[start/8]|=(1<<(start&7));
++start;
// get start of block
blockmark_t *m = (blockmark_t*)((uintptr_t)block+MMAPSIZE-sizeof(blockmark_t)); // styart with the end
int maxsize = 0;
while(m->prev.x32) { // while there is a subblock
if(!m->prev.fill && m->prev.size>maxsize) {
maxsize = m->prev.size;
if((uintptr_t)block+maxsize>(uintptr_t)m)
return maxsize; // no block large enough left...
}
m = (blockmark_t*)((uintptr_t)m - m->prev.size);
}
return maxsize;
}
static void freeBlock(mmaplist_t *map, int start, int size)
static void* allocBlock(void* block, void *sub, int size)
{
for(int i=0; i<size; ++i) {
map->map[start/8]&=~(1<<(start&7));
++start;
blockmark_t *s = (blockmark_t*)sub;
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
s->next.fill = 1;
s->next.size = size+sizeof(blockmark_t);
blockmark_t *m = (blockmark_t*)((uintptr_t)s + s->next.size); // this is new n
m->prev.fill = 1;
m->prev.size = s->next.size;
if(n!=m) {
// new mark
m->prev.fill = 1;
m->prev.size = s->next.size;
m->next.fill = 0;
m->next.size = (uintptr_t)n - (uintptr_t)m;
n->prev.fill = 0;
n->prev.size = m->next.size;
}
return (void*)((uintptr_t)sub + sizeof(blockmark_t));
}
static void freeBlock(void *block, void* sub, int size)
{
blockmark_t *m = (blockmark_t*)block;
blockmark_t *s = (blockmark_t*)sub;
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
if(block!=sub)
m = (blockmark_t*)((uintptr_t)s - s->prev.size);
s->next.fill = 0;
n->prev.fill = 0;
// check if merge with previous
if (s->prev.x32 && !s->prev.fill) {
// remove s...
m->next.size += s->next.size;
n->prev.size = m->next.size;
s = m;
}
// check if merge with next
if(n->next.x32 && !n->next.fill) {
blockmark_t *n2 = (blockmark_t*)((uintptr_t)n + n->next.size);
//remove n
s->next.size += n->next.size;
n2->prev.size = s->next.size;
}
}
uintptr_t AllocDynarecMap(int size, int nolinker)
uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
{
if(size>MMAPSIZE) {
void* p = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(p==MAP_FAILED) {
dynarec_log(LOG_DEBUG, "Cannot create dynamic map of %d bytes\n", size);
return 0;
}
return (uintptr_t)p;
}
pthread_mutex_lock(&my_context->mutex_mmap);
int bsize = (size+MMAPBLOCK-1)/MMAPBLOCK;
// look for free space
void* sub = NULL;
for(int i=0; i<my_context->mmapsize; ++i) {
int rsize = 0;
int start = 0;
do {
start = getFirstBlock(my_context->mmaplist+i, start, bsize, &rsize);
if(start!=-1 && rsize>=bsize) {
allocBlock(my_context->mmaplist+i, start, bsize);
uintptr_t ret = (uintptr_t)my_context->mmaplist[i].block + start*MMAPBLOCK;
pthread_mutex_unlock(&my_context->mutex_mmap);
if(my_context->mmaplist[i].maxfree>=size) {
int rsize = 0;
sub = getFirstBlock(my_context->mmaplist[i].block, size, &rsize);
if(sub) {
uintptr_t ret = (uintptr_t)allocBlock(my_context->mmaplist[i].block, sub, size);
if(rsize==my_context->mmaplist[i].maxfree)
my_context->mmaplist[i].maxfree = getMaxFreeBlock(my_context->mmaplist[i].block);
kh_dynablocks_t *blocks = my_context->mmaplist[i].dblist;
if(!blocks) {
blocks = my_context->mmaplist[i].dblist = kh_init(dynablocks);
kh_resize(dynablocks, blocks, 64);
}
khint_t k;
int r;
k = kh_put(dynablocks, blocks, (uintptr_t)db, &r);
kh_value(blocks, k) = db;
return ret;
}
if(start!=-1)
start += rsize;
} while (start!=-1);
}
}
// no luck, add a new one !
return 0;
}
uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
{
int i = my_context->mmapsize++; // yeah, useful post incrementation
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%d\n", my_context->mmapsize);
my_context->mmaplist = (mmaplist_t*)realloc(my_context->mmaplist, my_context->mmapsize*sizeof(mmaplist_t));
void* p = mmap(NULL, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(p==MAP_FAILED) {
dynarec_log(LOG_DEBUG, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, i);
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);
--my_context->mmapsize;
pthread_mutex_unlock(&my_context->mutex_mmap);
return 0;
}
mprotect(p, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
my_context->mmaplist[i].block = p;
memset(my_context->mmaplist[i].map, 0, sizeof(my_context->mmaplist[i].map));
allocBlock(my_context->mmaplist+i, 0, bsize);
pthread_mutex_unlock(&my_context->mutex_mmap);
return (uintptr_t)p;
// setup marks
blockmark_t* m = (blockmark_t*)p;
m->prev.x32 = 0;
m->next.fill = 0;
m->next.size = MMAPSIZE-sizeof(blockmark_t);
m = (blockmark_t*)(p+MMAPSIZE-sizeof(blockmark_t));
m->next.x32 = 0;
m->prev.fill = 0;
m->prev.size = MMAPSIZE-sizeof(blockmark_t);
// alloc 1st block
uintptr_t sub = (uintptr_t)allocBlock(my_context->mmaplist[i].block, p, size);
my_context->mmaplist[i].maxfree = getMaxFreeBlock(my_context->mmaplist[i].block);
kh_dynablocks_t *blocks = my_context->mmaplist[i].dblist = kh_init(dynablocks);
kh_resize(dynablocks, blocks, 64);
khint_t k;
int ret;
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
kh_value(blocks, k) = db;
return sub;
}
void FreeDynarecMap(uintptr_t addr, uint32_t size)
void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
{
if(size>MMAPSIZE) {
munmap((void*)addr, size);
if(!addr || !size)
return;
}
pthread_mutex_lock(&my_context->mutex_mmap);
int bsize = (size+MMAPBLOCK-1)/MMAPBLOCK;
// look for free space
for(int i=0; i<my_context->mmapsize; ++i) {
if(addr>=(uintptr_t)my_context->mmaplist[i].block && ((uintptr_t)my_context->mmaplist[i].block+MMAPSIZE)>=addr+size) {
int start = (addr - (uintptr_t)my_context->mmaplist[i].block) / MMAPBLOCK;
freeBlock(my_context->mmaplist+i, start, bsize);
pthread_mutex_unlock(&my_context->mutex_mmap);
if ((addr>(uintptr_t)my_context->mmaplist[i].block)
&& (addr<((uintptr_t)my_context->mmaplist[i].block+MMAPSIZE))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
freeBlock(my_context->mmaplist[i].block, sub, size);
my_context->mmaplist[i].maxfree = getMaxFreeBlock(my_context->mmaplist[i].block);
kh_dynablocks_t *blocks = my_context->mmaplist[i].dblist;
if(blocks) {
khint_t k = kh_get(dynablocks, blocks, (uintptr_t)db);
if(k!=kh_end(blocks))
kh_del(dynablocks, blocks, k);
}
return;
}
}
if(my_context->mmapsize)
dynarec_log(LOG_NONE, "Warning, block %p (size %d) not found in mmaplist for Free\n", (void*)addr, size);
}
dynablock_t* FindDynablockFromNativeAddress(void* addr)
{
// look in actual list
for(int i=0; i<my_context->mmapsize; ++i) {
if ((uintptr_t)addr>=(uintptr_t)my_context->mmaplist[i].block
&& ((uintptr_t)addr<(uintptr_t)my_context->mmaplist[i].block+MMAPSIZE))
return FindDynablockDynablocklist(addr, my_context->mmaplist[i].dblist);
}
// look in oversized
return FindDynablockDynablocklist(addr, my_context->dblist_oversized);
}
uintptr_t AllocDynarecMap(dynablock_t* db, int size)
{
if(!size)
return 0;
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
void *p = NULL;
if(posix_memalign(&p, box86_pagesize, size)) {
dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size);
return 0;
}
mprotect(p, size, PROT_READ | PROT_WRITE | PROT_EXEC);
kh_dynablocks_t *blocks = my_context->dblist_oversized;
if(!blocks) {
blocks = my_context->dblist_oversized = kh_init(dynablocks);
kh_resize(dynablocks, blocks, 64);
}
khint_t k;
int ret;
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
kh_value(blocks, k) = db;
return (uintptr_t)p;
}
if(pthread_mutex_trylock(&my_context->mutex_mmap)) {
sched_yield(); // give it a chance
if(pthread_mutex_trylock(&my_context->mutex_mmap))
return 0; // cannot lock, baillout
}
uintptr_t ret = FindFreeDynarecMap(db, size);
if(!ret)
ret = AddNewDynarecMap(db, size);
pthread_mutex_unlock(&my_context->mutex_mmap);
return ret;
}
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
{
if(size>MMAPSIZE) {
munmap((void*)addr, size);
kh_dynablocks_t *blocks = my_context->dblist_oversized;
if(blocks) {
khint_t k = kh_get(dynablocks, blocks, (uintptr_t)db);
if(k!=kh_end(blocks))
kh_del(dynablocks, blocks, k);
}
return;
}
pthread_mutex_lock(&my_context->mutex_mmap);
ActuallyFreeDynarecMap(db, addr, size);
pthread_mutex_unlock(&my_context->mutex_mmap);
}
// each dynmap is 64k of size
dynablocklist_t* getDBFromAddress(uintptr_t addr)
{
int idx = (addr>>16);
if(!my_context->dynmap[idx]) {
return NULL;
}
return my_context->dynmap[idx]->dynablocks;
}
void addDBFromAddressRange(uintptr_t addr, uintptr_t size)
void addDBFromAddressRange(box86context_t* context, uintptr_t addr, uintptr_t size, int nolinker)
{
dynarec_log(LOG_DEBUG, "addDBFromAddressRange %p -> %p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>16);
uintptr_t end = ((addr+size-1)>>16);
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
if(!my_context->dynmap[i]) {
my_context->dynmap[i] = (dynmap_t*)calloc(1, sizeof(dynmap_t));
my_context->dynmap[i]->dynablocks = NewDynablockList(i<<16, i<<16, 1<<16, 1, 0);
if(!context->dynmap[i]) {
context->dynmap[i] = NewDynablockList(i<<DYNAMAP_SHIFT, i<<DYNAMAP_SHIFT, 1<<DYNAMAP_SHIFT, nolinker, 0);
}
}
protectDB(addr, size);
}
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy)
void cleanDBFromAddressRange(box86context_t* context, uintptr_t addr, uintptr_t size, int destroy)
{
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p -> %p %s\n", (void*)addr, (void*)(addr+size-1), destroy?"destroy":"mark");
uintptr_t idx = (addr>box86_dynarec_largest && !destroy)?((addr-box86_dynarec_largest)>>16):(addr>>16);
uintptr_t end = ((addr+size-1)>>16);
uintptr_t idx = (addr>box86_dynarec_largest && !destroy)?((addr-box86_dynarec_largest)>>DYNAMAP_SHIFT):(addr>>DYNAMAP_SHIFT);
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
dynmap_t* dynmap = my_context->dynmap[i];
if(dynmap) {
uintptr_t startdb = StartDynablockList(dynmap->dynablocks);
uintptr_t enddb = EndDynablockList(dynmap->dynablocks);
dynablocklist_t* dblist = context->dynmap[i];
if(dblist) {
uintptr_t startdb = StartDynablockList(dblist);
uintptr_t enddb = EndDynablockList(dblist);
uintptr_t startaddr = addr;
if(startaddr<startdb) startaddr = startdb;
uintptr_t endaddr = addr + size - 1;
if(endaddr>enddb) endaddr = enddb;
if(startaddr==startdb && endaddr==enddb) {
if(destroy) {
my_context->dynmap[i] = NULL;
FreeDynablockList(&dynmap->dynablocks);
free(dynmap);
context->dynmap[i] = NULL;
FreeDynablockList(&dblist);
} else
MarkDynablockList(&dynmap->dynablocks);
MarkDynablockList(&dblist);
} else
if(destroy)
FreeRangeDynablock(dynmap->dynablocks, startaddr, endaddr-startaddr+1);
FreeRangeDynablock(dblist, startaddr, endaddr-startaddr+1);
else
MarkRangeDynablock(dynmap->dynablocks, startaddr, endaddr-startaddr+1);
MarkRangeDynablock(dblist, startaddr, endaddr-startaddr+1);
}
}
@@ -209,7 +342,7 @@ void unprotectDB(uintptr_t addr, uintptr_t size)
uintptr_t end = (addr+size+(box86_pagesize-1))&~(box86_pagesize-1);
// should get "end" according to last block inside the window
mprotect((void*)start, end-start, PROT_READ|PROT_WRITE|PROT_EXEC);
cleanDBFromAddressRange(start, end-start, 0);
cleanDBFromAddressRange(my_context, start, end-start, 0);
}
#endif
@@ -222,18 +355,23 @@ void initAllHelpers(box86context_t* context)
return;
my_context = context;
init_pthread_helper();
init_signal_helper();
init_signal_helper(context);
#ifdef DYNAREC
if(box86_dynarec)
DynablockEmuMarker(context);
#endif
inited = 1;
}
EXPORTDYN
void finiAllHelpers()
void finiAllHelpers(box86context_t* context)
{
static int finied = 0;
if(finied)
return;
fini_pthread_helper();
fini_pthread_helper(context);
fini_signal_helper();
cleanAlternate();
finied = 1;
}
@@ -277,11 +415,19 @@ box86context_t *NewBox86Context(int argc)
#else
context->deferedInit = 1;
#endif
context->sel_serial = 1;
#ifdef DYNAREC
pthread_mutex_init(&context->mutex_blocks, NULL);
pthread_mutex_init(&context->mutex_mmap, NULL);
context->dynmap = (dynablocklist_t**)calloc(DYNAMAP_SIZE, sizeof(dynablocklist_t*));
#endif
context->maplib = NewLibrarian(context, 1);
context->local_maplib = NewLibrarian(context, 1);
context->system = NewBridge();
// create vsyscall
context->vsyscall = AddBridge(context->system, vFv, x86Syscall, 0);
context->vsyscall = AddBridge(context->system, context, vFv, x86Syscall, 0);
#ifdef BUILD_LIB
context->box86lib = RTLD_DEFAULT; // not ideal
#else
@@ -289,24 +435,22 @@ box86context_t *NewBox86Context(int argc)
#endif
context->dlprivate = NewDLPrivate();
context->callbacks = NewCallbackList();
context->argc = argc;
context->argv = (char**)calloc(context->argc+1, sizeof(char*));
pthread_mutex_init(&context->mutex_once, NULL);
pthread_mutex_init(&context->mutex_once2, NULL);
pthread_mutex_init(&context->mutex_trace, NULL);
#ifndef DYNAREC
pthread_mutex_init(&context->mutex_lock, NULL);
#endif
pthread_mutex_init(&context->mutex_tls, NULL);
pthread_mutex_init(&context->mutex_thread, NULL);
#ifdef DYNAREC
pthread_mutex_init(&context->mutex_dyndump, NULL);
#endif
pthread_key_create(&context->tlskey, free_tlsdatasize);
#ifdef DYNAREC
pthread_mutex_init(&context->mutex_blocks, NULL);
pthread_mutex_init(&context->mutex_mmap, NULL);
context->dynablocks = NewDynablockList(0, 0, 0, 0, 0);
#endif
InitFTSMap(context);
for (int i=0; i<4; ++i) context->canary[i] = 1 + getrand(255);
@@ -345,24 +489,6 @@ void FreeBox86Context(box86context_t** context)
if(ctx->local_maplib)
FreeLibrarian(&ctx->local_maplib);
#ifdef DYNAREC
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
if(ctx->dynablocks)
FreeDynablockList(&ctx->dynablocks);
for (int i=0; i<ctx->mmapsize; ++i)
if(ctx->mmaplist[i].block)
munmap(ctx->mmaplist[i].block, MMAPSIZE);
free(ctx->mmaplist);
pthread_mutex_destroy(&ctx->mutex_blocks);
pthread_mutex_destroy(&ctx->mutex_mmap);
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
cleanDBFromAddressRange(0, 0xffffffff, 1);
#endif
*context = NULL; // bye bye my_context
CleanStackSize(ctx);
FreeCollection(&ctx->box86_path);
FreeCollection(&ctx->box86_ld_lib);
FreeCollection(&ctx->box86_emulated_libs);
@@ -375,6 +501,49 @@ void FreeBox86Context(box86context_t** context)
if(ctx->deferedInitList)
free(ctx->deferedInitList);
free(ctx->argv);
for (int i=0; i<ctx->envc; ++i)
free(ctx->envv[i]);
free(ctx->envv);
if(ctx->atfork_sz) {
free(ctx->atforks);
ctx->atforks = NULL;
ctx->atfork_sz = ctx->atfork_cap = 0;
}
for(int i=0; i<MAX_SIGNAL; ++i)
if(ctx->signals[i]!=0 && ctx->signals[i]!=1) {
signal(i, SIG_DFL);
}
#ifdef DYNAREC
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
for (int i=0; i<ctx->mmapsize; ++i) {
if(ctx->mmaplist[i].block)
free(ctx->mmaplist[i].block);
if(ctx->mmaplist[i].dblist) {
kh_destroy(dynablocks, ctx->mmaplist[i].dblist);
ctx->mmaplist[i].dblist = NULL;
}
}
if(ctx->dblist_oversized) {
kh_destroy(dynablocks, ctx->dblist_oversized);
ctx->dblist_oversized = NULL;
}
ctx->mmapsize = 0;
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
cleanDBFromAddressRange(ctx, 0, 0xffffffff, 1);
pthread_mutex_destroy(&ctx->mutex_blocks);
pthread_mutex_destroy(&ctx->mutex_mmap);
free(ctx->mmaplist);
#endif
*context = NULL; // bye bye my_context
CleanStackSize(ctx);
#ifndef BUILD_LIB
if(ctx->box86lib)
dlclose(ctx->box86lib);
@@ -382,12 +551,6 @@ void FreeBox86Context(box86context_t** context)
FreeDLPrivate(&ctx->dlprivate);
free(ctx->argv);
for (int i=0; i<ctx->envc; ++i)
free(ctx->envv[i]);
free(ctx->envv);
free(ctx->stack);
free(ctx->fullpath);
@@ -398,8 +561,6 @@ void FreeBox86Context(box86context_t** context)
freeGLProcWrapper(ctx);
freeALProcWrapper(ctx);
FreeCallbackList(&ctx->callbacks);
void* ptr;
if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
free_tlsdatasize(ptr);
@@ -420,26 +581,23 @@ void FreeBox86Context(box86context_t** context)
pthread_mutex_destroy(&ctx->mutex_once);
pthread_mutex_destroy(&ctx->mutex_once2);
pthread_mutex_destroy(&ctx->mutex_trace);
#ifndef DYNAREC
pthread_mutex_destroy(&ctx->mutex_lock);
#endif
pthread_mutex_destroy(&ctx->mutex_tls);
pthread_mutex_destroy(&ctx->mutex_thread);
#ifdef DYNAREC
pthread_mutex_destroy(&ctx->mutex_dyndump);
free(ctx->dynmap);
ctx->dynmap = NULL;
#endif
free_neededlib(&ctx->neededlibs);
if(ctx->atfork_sz) {
free(ctx->atforks);
ctx->atforks = NULL;
ctx->atfork_sz = ctx->atfork_cap = 0;
}
for(int i=0; i<MAX_SIGNAL; ++i)
if(ctx->signals[i]!=0 && ctx->signals[i]!=1) {
signal(i, SIG_DFL);
}
if(ctx->emu_sig)
FreeX86Emu(&ctx->emu_sig);
finiAllHelpers();
finiAllHelpers(ctx);
free(ctx);
}
@@ -463,6 +621,13 @@ int AddTLSPartition(box86context_t* context, int tlssize) {
context->tlsdata = realloc(context->tlsdata, context->tlssize);
memmove(context->tlsdata+tlssize, context->tlsdata, oldsize); // move to the top, using memmove as regions will probably overlap
memset(context->tlsdata, 0, tlssize); // fill new space with 0 (not mandatory)
// clean GS segment for current emu
if(my_context) {
ResetSegmentsCache(thread_get_emu());
if(!(++context->sel_serial))
++context->sel_serial;
}
return -context->tlssize; // negative offset
}
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX86_MAJOR 0
#define BOX86_MINOR 1
#define BOX86_REVISION 2
#define BOX86_REVISION 8
#endif //__BOX86_VERSION_H_
+5 -6
View File
@@ -1,11 +1,15 @@
#include <stdio.h>
#include "debug.h"
#include "box86version.h"
#ifdef NOGIT
#define GITREV "nogit"
#else
#include "git_head.h"
#endif
void PrintBox86Version()
{
printf("Box86%s%s%s v%d.%d.%d %s built on %s %s\n",
printf("Box86%s%s v%d.%d.%d %s built on %s %s\n",
#ifdef HAVE_TRACE
" with trace",
#else
@@ -15,11 +19,6 @@ void PrintBox86Version()
" with Dynarec",
#else
"",
#endif
#ifdef USE_FLOAT
" (float only)",
#else
"",
#endif
BOX86_MAJOR, BOX86_MINOR, BOX86_REVISION,
GITREV,
+110 -12
View File
@@ -122,7 +122,7 @@ Op is 20-27
#define SUB_IMM8(dst, src, imm8) \
EMIT(0xe2400000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// sub cond dst, src, #(imm8)
#define SUB_COND_IMM8(dst, src, imm8) \
#define SUB_COND_IMM8(cond, dst, src, imm8) \
EMIT((cond) | 0x02400000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// sub.s dst, src, #(imm8)
#define SUBS_IMM8(dst, src, imm8) \
@@ -178,6 +178,9 @@ Op is 20-27
// add dst, src, #(imm8)
#define ADD_IMM8(dst, src, imm8) \
EMIT(0xe2800000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// add dst, src, #imm8 ror rot*2
#define ADD_IMM8_ROR(dst, src, imm8, rot) \
EMIT(0xe2800000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM((imm8)) )
// add.s dst, src, #(imm8)
#define ADDS_IMM8(dst, src, imm8) \
EMIT(0xe2900000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
@@ -207,6 +210,12 @@ Op is 20-27
// cmp.s dst, src1, src2, lsl #imm
#define CMPS_REG_LSL_IMM5(src1, src2, imm5) \
EMIT(0xe1500000 | ((0) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// cmp.cond.s dst, src1, src2, lsl #imm
#define CMPS_REG_LSL_IMM5_COND(cond, src1, src2, imm5) \
EMIT((cond) | 0x01500000 | ((0) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// cmp.s dst, src, #imm
#define CMPS_IMM8_COND(cond, src, imm8) \
EMIT((cond) | 0x03500000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
// cmp.s dst, src, #imm
#define CMPS_IMM8(src, imm8) \
EMIT(0xe3500000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
@@ -316,6 +325,8 @@ Op is 20-27
// str reg, [addr, #+/-imm9]
#define STR_IMM9(reg, addr, imm9) EMIT(0xe5000000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
// str with cond reg, [addr, #+/-imm9]
#define STR_IMM9_COND(cond, reg, addr, imm9) EMIT(cond | 0x05000000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
// strb reg, [addr, #+/-imm9]
#define STRB_IMM9(reg, addr, imm9) EMIT(0xe5400000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
// str reg, [addr], #+/-imm9
@@ -382,8 +393,14 @@ Op is 20-27
#define LDRH_REG(reg, addr, rm) EMIT(HWS_REG(c__, 1, 1, 0, 1, addr, reg, 0, 1, rm))
#define STRH_REG(reg, addr, rm) EMIT(HWS_REG(c__, 1, 1, 0, 0, addr, reg, 0, 1, rm))
#define LDRHAI_REG_LSL_IMM5(reg, addr, rm) EMIT(HWS_REG(c__, 0, 1, 0, 1, addr, reg, 0, 1, rm))
#define STRHAI_REG_LSL_IMM5(reg, addr, rm) EMIT(HWS_REG(c__, 0, 1, 0, 0, addr, reg, 0, 1, rm))
#define LDRHAI_REG_LSL_IMM5(reg, addr, rm) EMIT(HWS_REG(c__, 0, 1, 0, 1, addr, reg, 0, 1, rm))
#define STRHAI_REG_LSL_IMM5(reg, addr, rm) EMIT(HWS_REG(c__, 0, 1, 0, 0, addr, reg, 0, 1, rm))
#define LDRHB_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 1, 1, addr, reg, 0, 1, abs(imm8)))
#define LDRHA_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 0, (((imm8)<0)?0:1), 0, 1, addr, reg, 0, 1, abs(imm8)))
#define STRHB_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 1, 0, addr, reg, 0, 1, abs(imm8)))
#define STRHA_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 0, (((imm8)<0)?0:1), 0, 0, addr, reg, 0, 1, abs(imm8)))
#define PUSH16(reg, addr) EMIT(HWS_OFF(c__, 1, 0, 1, 0, addr, reg, 0, 1, 2))
#define POP16(reg, addr) EMIT(HWS_OFF(c__, 0, 1, 0, 1, addr, reg, 0, 1, 2))
// Mul Long construction
#define MULLONG(Cond, U, A, S, RdHi, RdLo, Rs, Rm) (Cond | 0b00001<<23 | (U)<<22 | (A)<<21 | (S)<<20 | (RdHi)<<16 | (RdLo)<<12 | (Rs)<<8 | 0b1001<<4 | (Rm))
@@ -422,6 +439,9 @@ Op is 20-27
#define SSAT_gen(cond, sat_imm, Rd, imm5, sh, Rn) (cond | 0b0110101<<21 | (sat_imm)<<16 | (Rd)<<12 | (imm5)<<7 | (sh)<<6 | 0b01<<4 | (Rn))
// Signed Staturate Rn to 2^(staturate_to-1) into Rd. Optionnaly shift left Rn before saturate
#define SSAT_REG_LSL_IMM5(Rd, saturate_to, Rn, shift) EMIT(SSAT_gen(c__, (saturate_to)-1, Rd, shift, 0, Rn))
// Signed Staturate Rn to 2^(staturate_to-1) into Rd. Optionnaly shift left Rn before saturate
#define SSAT_REG_LSL_IMM5_COND(cond, Rd, saturate_to, Rn, shift) EMIT(SSAT_gen((cond), (saturate_to)-1, Rd, shift, 0, Rn))
#define USAT_gen(cond, sat_imm, Rd, imm5, sh, Rn) (cond | 0b0110111<<21 | (sat_imm)<<16 | (Rd)<<12 | (imm5)<<7 | (sh)<<6 | 0b01<<4 | (Rn))
// Unsigned Staturate Rn to 2^(staturate_to-1) into Rd. Optionnaly shift left Rn before saturate
#define USAT_REG_LSL_IMM5(Rd, saturate_to, Rn, shift) EMIT(SSAT_gen(c__, (saturate_to), Rd, shift, 0, Rn))
@@ -438,11 +458,33 @@ Op is 20-27
#define LDREXD_gen(cond, Rn, Rt) (cond | 0b000<<25 | 0b11011<<20 | (Rn)<<16 | (Rt)<<12 | 0b1111<<8 | 0b1001<<4 | 0b1111)
// Load Exclusive Rt/Rt+1 from Rn (tagging the memory)
#define LDREXD(Rn, Rt) EMIT(LDREXD_gen(c__, Rn, Rt))
#define LDREXD(Rt, Rn) EMIT(LDREXD_gen(c__, Rn, Rt))
#define LDREXD_COND(cond, Rt, Rn) EMIT(LDREXD_gen(cond, Rn, Rt))
#define STREXD_gen(cond, Rd, Rn, Rt) (cond | 0b000<<25 | 0b11010<<20 | (Rn)<<16 | (Rd)<<12 | 0b1111<<8 | 0b1001<<4 | (Rt))
// Store Exclusive Rt/Rt+1 to Rn, with result in Rd if tag is ok (Rd!=Rn && Rd!=Rt && Rd!=Rt+1), Rd==1 if store failed
#define STREXD(Rd, Rn, Rt) EMIT(STREXD_gen(c__, Rd, Rn, Rt))
#define STREXD(Rd, Rt, Rn) EMIT(STREXD_gen(c__, Rd, Rn, Rt))
#define STREXD_COND(cond, Rd, Rt, Rn) EMIT(STREXD_gen(cond, Rd, Rn, Rt))
#define LDREX_gen(cond, Rn, Rt) (cond | 0b0001100<<21 | 1<<20 | (Rn)<<16 | (Rt)<<12 | 0b1111<<8 | 0b1001<<4 | 0b1111)
// Load Exclusive Rt from Rn (tagging the memory)
#define LDREX(Rt, Rn) EMIT(LDREX_gen(c__, Rn, Rt))
#define LDREX_COND(cond, Rt, Rn) EMIT(LDREX_gen(cond, Rn, Rt))
#define STREX_gen(cond, Rd, Rn, Rt) (cond | 0b0001100<<21 | 0<<20 | (Rn)<<16 | (Rd)<<12 | 0b1111<<8 | 0b1001<<4 | (Rt))
// Store Exclusive Rt to Rn, with result in Rd=0 if tag is ok, Rd==1 if store failed (Rd!=Rn && Rd!=Rt)
#define STREX(Rd, Rt, Rn) EMIT(STREX_gen(c__, Rd, Rn, Rt))
#define STREX_COND(cond, Rd, Rt, Rn) EMIT(STREX_gen(cond, Rd, Rn, Rt))
#define LDREXB_gen(cond, Rn, Rt) (cond | 0b0001110<<21 | 1<<20 | (Rn)<<16 | (Rt)<<12 | 0b1111<<8 | 0b1001<<4 | 0b1111)
// Load Exclusive Byte Rt from Rn (tagging the memory)
#define LDREXB(Rt, Rn) EMIT(LDREXB_gen(c__, Rn, Rt))
#define LDREXB_COND(cond, Rt, Rn) EMIT(LDREXB_gen(cond, Rn, Rt))
#define STREXB_gen(cond, Rd, Rn, Rt) (cond | 0b0001110<<21 | 0<<20 | (Rn)<<16 | (Rd)<<12 | 0b1111<<8 | 0b1001<<4 | (Rt))
// Store Exclusive byte Rt to Rn, with result in Rd=0 if tag is ok, Rd==1 if store failed (Rd!=Rn && Rd!=Rt)
#define STREXB(Rd, Rt, Rn) EMIT(STREXB_gen(c__, Rd, Rn, Rt))
#define STREXB_COND(cond, Rd, Rt, Rn) EMIT(STREXB_gen(cond, Rd, Rn, Rt))
// Count leading 0 bit of Rm, store result in Rd
#define CLZ(Rd, Rm) EMIT(c__ | 0b00010110<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0001<<4 | (Rm))
@@ -469,6 +511,9 @@ Op is 20-27
// Unsigned Div Rd <- Rn/Rm
#define UDIV(Rd, Rm, Rn) EMIT(UDIV_gen(c__, Rd, Rm, Rn))
// Yield
#define YIELD(cond) EMIT(cond | 0b00110010<<20 | 0b1111<<12 | 1)
// VFPU
#define TRANSFERT64(C, op) ((0b1100<<24) | (0b010<<21) | (0b101<<9) | ((C)<<8) | ((op)<<4))
@@ -553,9 +598,9 @@ Op is 20-27
// Convert from int32 Sm to single Dd
#define VCVT_F32_S32(Sd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b111<<19) | (0b000<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (1<<7) | (1<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
#define VCVT_16_gen(cond, D, op, U, Vd, sf, sx, i, imm4) (cond | 0b1110<<24 | 1<<23 | (D)<<22 | 0b11<<20 | 1<<19 | (op)<<18 | 1<<17 | (U)<<16 | (Vd)<<12 | 0b101<<9 | (sf)<<8 | (sx)<<7 | 1<<6 | (i)<<5 | (imm4))
#define VCVT_FP_gen(cond, D, op, U, Vd, sf, sx, i, imm4) (cond | 0b1110<<24 | 1<<23 | (D)<<22 | 0b11<<20 | 1<<19 | (op)<<18 | 1<<17 | (U)<<16 | (Vd)<<12 | 0b101<<9 | (sf)<<8 | (sx)<<7 | 1<<6 | (i)<<5 | (imm4))
// Inplace convert from F64 to S16. Rounding is not selectable
#define VCVT_S16_F64(Dd) EMIT(VCVT_16_gen(c__, ((Dd)>>4)&1, 1, 0, (Dd)&15, 1, 0, 16&1, (16>>1)&15))
#define VCVT_S16_F64(Dd) EMIT(VCVT_FP_gen(c__, ((Dd)>>4)&1, 1, 0, (Dd)&15, 1, 0, 16&1, (16>>1)&15))
// Mutiply F64 Dd = Dn*Dm
#define VMUL_F64(Dd, Dn, Dm) EMIT(c__ | (0b1110<<24) | (0<<23) | ((((Dd)>>4)&1)<<22) | (0b10<<20) | (((Dn)&15)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | ((((Dn)>>4)&1)<<7) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
@@ -658,16 +703,26 @@ Op is 20-27
#define VEORQ(Dd, Dn, Dm) EMIT(VEOR_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VMOVL_gen(U, D, imm3, Vd, M, Vm) (0b1111<<28 | 0b001<<25 | (U)<<24 | 1<<23 | (D)<<22 | (imm3)<<19 | (Vd)<<12 | 0b1010<<8 | (M)<<5 | 1<<4 | (Vm))
#define VMOVL_S8(Dd, Dm) EMIT(VMOVL_gen(0, ((Dd)>>4)&1, 0b001, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define VMOVL_U8(Dd, Dm) EMIT(VMOVL_gen(1, ((Dd)>>4)&1, 0b001, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define VMOVL_S32(Dd, Dm) EMIT(VMOVL_gen(0, ((Dd)>>4)&1, 0b100, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define VMOVL_U32(Dd, Dm) EMIT(VMOVL_gen(1, ((Dd)>>4)&1, 0b100, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define VMOV_gen(D,Vd, M, Vm, Q) (0b1111<<28 | 0b0010<<24 | 0<<23 | (D)<<22 | 0b10<<20 | (Vm)<<16 | (Vd)<<12 | 0b0001<<8 | (M)<<7 | (Q)<<6 | (M)<<5 | 1<<4 | (Vm))
#define VMOVD(Dd, Dm) EMIT(VMOV_gen(((Dd)>>4)&1, (Dd)&15, ((Dm)>>4)&1, (Dm)&15, 0))
#define VMOVQ(Dd, Dm) EMIT(VMOV_gen(((Dd)>>4)&1, (Dd)&15, ((Dm)>>4)&1, (Dm)&15, 1))
#define VMOVD(Dd, Dm) if((Dd)!=(Dm)) {EMIT(VMOV_gen(((Dd)>>4)&1, (Dd)&15, ((Dm)>>4)&1, (Dm)&15, 0));}
#define VMOVQ(Dd, Dm) if((Dd)!=(Dm)) {EMIT(VMOV_gen(((Dd)>>4)&1, (Dd)&15, ((Dm)>>4)&1, (Dm)&15, 1));}
#define VMOV_igen(i, D, imm3, Vd, cmode, Q, op, imm4) (0b1111<<28 | 0b001<<25 | (i)<<24 | 1<<23 | (D)<<22 | (imm3)<<16 | (Vd)<<12 | (cmode)<<8 | (Q)<<6 | (op)<<5 | 1<<4 | (imm4))
#define VMOV_8(Dd, imm) EMIT(VMOV_igen(((imm)>>7)&1, ((Dd)>>4)&1, ((imm)>>4)&7, (Dd)&15, 0b1110, 0, 0, (imm)&15))
#define VMOVQ_8(Dd, imm) EMIT(VMOV_igen(((imm)>>7)&1, ((Dd)>>4)&1, ((imm)>>4)&7, (Dd)&15, 0b1110, 1, 0, (imm)&15))
// Dd <= imm8 in high bits
#define VMOV_H32(Dd, imm8) EMIT(VMOV_igen(((imm8)>>7)&1, ((Dd)>>4)&1, ((imm8)>>4)&7, (Dd)&15, 0b0110, 0, 0, (imm8)&15))
// Dd <= imm8 in high bits
#define VMOV_H16(Dd, imm8) EMIT(VMOV_igen(((imm8)>>7)&1, ((Dd)>>4)&1, ((imm8)>>4)&7, (Dd)&15, 0b1010, 0, 0, (imm8)&15))
// Qd <= imm8 in high bits
#define VMOVQ_H32(Dd, imm8) EMIT(VMOV_igen(((imm8)>>7)&1, ((Dd)>>4)&1, ((imm8)>>4)&7, (Dd)&15, 0b0110, 1, 0, (imm8)&15))
// Qd <= imm8 in high bits
#define VMOVQ_H16(Dd, imm8) EMIT(VMOV_igen(((imm8)>>7)&1, ((Dd)>>4)&1, ((imm8)>>4)&7, (Dd)&15, 0b1010, 1, 0, (imm8)&15))
#define VLD1LANE_gen(D, Rn, Vd, size, index_align, Rm) (0b1111<<28 | 0b0100<<24 | 1<<23 | (D)<<22 | 0b10<<20 | (Rn)<<16 | (Vd)<<12 | (size)<<10 | (index_align)<<4 | (Rm))
#define VLD1LANE_8(Dd, Rn, index) EMIT(VLD1LANE_gen(((Dd)>>4)&1, Rn, (Dd)&15, 0, (index)<<1, 15))
@@ -732,6 +787,14 @@ Op is 20-27
#define VCEQ_F32(Dd, Dn, Dm) EMIT(VCEQ_F_gen(0, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCEQQ_F32(Dd, Dn, Dm) EMIT(VCEQ_F_gen(0, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCEQ_0_gen(D, size, Vd, F, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b01<<16 | (Vd)<<12 | (F)<<10 | 0b010<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VCEQ_0_8(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 0, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCEQ_0_16(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 1, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCEQ_0_32(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCEQQ_0_8(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 0, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCEQQ_0_16(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 1, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCEQQ_0_32(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCGT_I_gen(U, D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b001<<25 | (U)<<24 | 0<<23 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b0011<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VCGT_U8(Dd, Dn, Dm) EMIT(VCGT_I_gen(1, ((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCGTQ_U8(Dd, Dn, Dm) EMIT(VCGT_I_gen(1, ((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
@@ -757,6 +820,15 @@ Op is 20-27
#define VCGE_F32(Dd, Dn, Dm) EMIT(VCGE_F_gen(((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCGEQ_F32(Dd, Dn, Dm) EMIT(VCGE_F_gen(((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCLT_0_gen(D, size, Vd, F, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b01<<16 | (Vd)<<12 | (F)<<10 | 0b100<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VCLT_0_8(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 0, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCLT_0_16(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 1, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCLT_0_32(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCLTQ_0_8(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 0, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCLTQ_0_16(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 1, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCLTQ_0_32(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VSHR_gen(U, D, imm6, Vd, L, Q, M, Vm) (0b1111<<28 | 0b001<<25 | (U)<<24 | 1<<23 | (D)<<22 | (imm6)<<16 | (Vd)<<12 | (L)<<7 | (Q)<<6 | (M)<<5 | 1<<4 | (Vm))
#define VSHR_U8(Dd, Dm, imm3) EMIT(VSHR_gen(1, ((Dd)>>4)&1, 0b001<<3 | (8-(imm3)), (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VSHR_S8(Dd, Dm, imm3) EMIT(VSHR_gen(0, ((Dd)>>4)&1, 0b001<<3 | (8-(imm3)), (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
@@ -803,6 +875,11 @@ Op is 20-27
#define VSHLQ_S32(Dd, Dm, Dn) EMIT(VSHLR_gen(0, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VSHLQ_S64(Dd, Dm, Dn) EMIT(VSHLR_gen(0, ((Dd)>>4)&1, 0b11, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VSHRN_gen(D, imm6, Vd, M, Vm) (0b1111<<28 | 0b0010<<24 | 1<<23 | (D)<<22 | (imm6)<<16 | (Vd)<<12 | 1<<11 | (M)<<5 | 1<<4 | (Vm))
#define VSHRN_16(Dd, Dm, imm3) EMIT(VSHRN_gen(((Dd)>>4)&1, 0b001<<3 | (8-(imm3)), (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define VSHRN_32(Dd, Dm, imm4) EMIT(VSHRN_gen(((Dd)>>4)&1, 0b01<<4 | (16-(imm4)), (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define VSHRN_64(Dd, Dm, imm5) EMIT(VSHRN_gen(((Dd)>>4)&1, 0b1<<5 | (32-(imm5)), (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define VTRN_gen(D, size, Vd, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b10<<16 | (Vd)<<12 | 0b0000<<8 | 1<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VTRN_32(Dd, Dm) EMIT(VTRN_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15))
@@ -855,8 +932,8 @@ Op is 20-27
#define VMUL_16(Dd, Dn, Dm) EMIT(VMUL_NEON_gen(0, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VEXT_gen(D, Vn, Vd, imm4, N, Q, M, Vm) (0b1111<<28 | 0b0010<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (Vn)<<16 | (Vd)<<12 | (imm4)<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VEXT_8(Dd, Dn, Dm, imm4) EMIT(VEXT_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, (imm4), ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VEXTQ_8(Dd, Dn, Dm, imm4) EMIT(VEXT_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, (imm4), ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VEXT_8(Dd, Dn, Dm, imm4) EMIT(VEXT_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, (imm4)&0xf, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VEXTQ_8(Dd, Dn, Dm, imm4) EMIT(VEXT_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, (imm4)&0xf, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VMVN_gen(D, size, Vd, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b1011<<7 | (Q)<<6 | (M)<<5 | 0<<4 | (Vm))
#define VMVNQ(Dd, Dm) EMIT(VMVN_gen(((Dd)>>4)&1, 0, (Dd)&15, 1, ((Dm)>>4)&1, (Dm)&15))
@@ -1062,7 +1139,7 @@ Op is 20-27
#define VPADD_Fgen(D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1101<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | 0<<4 | (Vm))
// Add pair of F32, store result in F32
#define VPADD_F32(Dd, Dn, Dm) EMIT(VPADD_gen(((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VPADD_F32(Dd, Dn, Dm) EMIT(VPADD_Fgen(((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VMINMAX_gen(U, D, size, Vn, Vd, N, Q, M, op, Vm) (0b1111<<28 | 0b001<<25 | (U)<<24 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b110<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (op)<<4 | (Vm))
#define VMIN_U8(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b00, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 1, (Dm)&15))
@@ -1113,4 +1190,25 @@ Op is 20-27
#define VRHADDQ_S16(Dd, Dn, Dm) EMIT(VRHADD_gen(0, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VRHADDQ_S32(Dd, Dn, Dm) EMIT(VRHADD_gen(0, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VQRDMULH_gen(D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b0011 <<24 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1011<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (Vm))
// Dd <= (2*Dn*Dm + 1<<(size-1))>>size
#define VQRDMULH_S16(Dd, Dn, Dm) EMIT(VQRDMULH_gen(((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VQRDMULH_S32(Dd, Dn, Dm) EMIT(VQRDMULH_gen(((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VQRDMULHQ_S16(Dd, Dn, Dm) EMIT(VQRDMULH_gen(((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VQRDMULHQ_S32(Dd, Dn, Dm) EMIT(VQRDMULH_gen(((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VDUP_sgen(D, imm4, Vd, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (imm4)<<16 | (Vd)<<12 | 0b1100<<8 | (Q)<<6 | (M)<<5 | (Vm))
// Dd <= Dup(Dm[x])
#define VDUP_32(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<3)|0b100), (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15))
#define VABS_vgen(D, size, Vd, F, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b01<<16 | (Vd)<<12 | (F)<<10 | 0b110<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VABS_S32(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VABS_S16(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 1, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VABS_S8(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 0, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VABS_F(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VABSQ_S32(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VABSQ_S16(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 1, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VABSQ_S8(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 0, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VABSQ_F(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
#endif //__ARM_EMITTER_H__
+13 -13
View File
@@ -89,10 +89,10 @@ NEON 1 1 1 1 0 0 1 0 0 D 1 1 Vn Vd 0 0 0 1 N Q M 1 Vm VORN<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D @<2> Vn Vd 0 0 0 1 N Q M 1 Vm @ param=0b00=0b01=0b10 const char* op op,"EOR","BSL","BIT","BIF"@ @ V\op\<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 0 N Q M 1 Vm VQSUB<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 1 N Q M op Vm @ op=0 const char* strict strict,"T","E"@ @ VCG\strict\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 0 Vm VSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 1 Vm VQSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 0 Vm VRSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 1 Vm VQRSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 0 Vm VSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 1 Vm VQSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 0 Vm VRSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 1 Vm VQRSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 0 N Q M op Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ V\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 0 Vm VABD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 1 Vm VABA<c>.<dt> <Qd>, <Qn>, <Qm>
@@ -135,12 +135,12 @@ NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=1110 0 Q op/=1 1 imm4 VMOV<c>.<dt>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 0 0 0 <11> 0 <2> 1 <4>
# Special case for VMOVL (harder to do it on the documented place)
NEON 1 1 1 1 0 0 1 0 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S8 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 0 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S16 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 0 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U8 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U16 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 0 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S8 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S16 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S32 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U8 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U16 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U32 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 0 L Q M 1 Vm VSHR<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 1 L Q M 1 Vm VSRA<c>.<dt> <Qd>, <Qm>, #<imm>
@@ -150,7 +150,7 @@ NEON 1 1 1 1 0 0 1 1 1 D imm6 Vd 0 1 0 0 L Q M 1 Vm VSRI<c>.<size> <Qd>, <Qm>, #
NEON 1 1 1 1 0 0 1 0 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSHL<c>.I<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 1 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSLI<c>.<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D Imm6 Vd 0 1 1 op L Q M 1 Vm VQSHL\((u & op) ? "U" : "")\<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 0 M 1 Vm VSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 0 M 1 Vm @ set ++size@ @ VSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 1 M 1 Vm VRSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 0 M 1 Vm VQSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 1 M 1 Vm VQRSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
@@ -194,7 +194,7 @@ NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 0 Q M 0 Vm VUZP<c>.\%d8 &l&l si
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 1 Q M 0 Vm VZIP<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 0 M 0 Vm VMOVN<c>.<dt> <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 1 M 0 Vm VQMOVUN<c>.S\%d16 &l&l size\ <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 1 U M 0 Vm @ set u = 1 - u@ set ++size@ @ VQMOVN<c>.<dt> <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 1 U M 0 Vm @ set ++size@ @ VQMOVN<c>.<dt> <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 1 0 0 M 0 Vm VSHLL<c>.I\%d8 &l&l size\ <Qd>, <Dm>, #\%d8 &l&l size\
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 0 0 0 M 0 Vm VCVT<c>.F16.F32 <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 1 0 0 M 0 Vm VCVT<c>.F32.F16 <Qd>, <Dm>
@@ -557,7 +557,7 @@ VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 1 1 (0) (0) (0) (0) VDUP<c>.16 <Qd>,
VFPU cond 1 1 1 0 1 1 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.8 <Qd>, <Rt>
VFPU cond 1 1 1 0 0 0 0 1 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Rt>, <Sn>
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> <Rt>, FPSCR
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 3) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 4) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 1 <4>
VFPU cond 1 1 1 0 0 D 0 0 Vn Vd 1 0 1 sz N op M 0 Vm VML\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
+89
View File
@@ -0,0 +1,89 @@
//arm lock helper
//there is 2 part: read and write
// write return 0 on success, 1 on fail (value has been changed)
.text
.align 4
.global arm_lock_read_b
.global arm_lock_write_b
.global arm_lock_read_h
.global arm_lock_write_h
.global arm_lock_read_d
.global arm_lock_write_d
.global arm_lock_read_dd
.global arm_lock_write_dd
.global arm_lock_xchg
.global arm_lock_storeifnull
arm_lock_read_b:
// address is r0, return is r0
ldrexb r0, [r0]
bx lr
arm_lock_write_b:
// address is r0, value is r1, return is r0
mov r2, r0
strexb r0, r1, [r2]
bx lr
arm_lock_read_h:
// address is r0, return is r0
ldrexh r0, [r0]
bx lr
arm_lock_write_h:
// address is r0, value is r1, return is r0
mov r2, r0
strexh r0, r1, [r2]
bx lr
arm_lock_read_d:
// address is r0, return is r0
// r0 needs to be aligned
ldrex r0, [r0]
bx lr
arm_lock_write_d:
// address is r0, value is r1, return is r0
// r0 needs to be aligned
mov r2, r0
strex r0, r1, [r2]
bx lr
arm_lock_read_dd:
// address is r2, return is r0, r1
ldrexd r2, r3, [r2]
str r2, [r0]
str r3, [r1]
bx lr
arm_lock_write_dd:
// address is r2, value is r0, r1, return is r0
// r0 needs to be aligned
strexd r3, r0, r1, [r2]
mov r0, r3
bx lr
arm_lock_xchg:
// address is r0, value is r1, return old value in r0
// r0 needs to be aligned
ldrex r2, [r0]
strex r3, r1, [r0]
cmp r3, #1
beq arm_lock_xchg
mov r0, r2
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)
// r0 needs to be aligned
ldrex r2, [r0]
cmp r2, #0
moveq r2, r1
strex r3, r2, [r0]
cmp r3, #1
beq arm_lock_storeifnull
mov r0, r2
bx lr
+31
View File
@@ -0,0 +1,31 @@
#ifndef __ARM_LOCK_HELPER__H__
#define __ARM_LOCK_HELPER__H__
#include <stdint.h>
// LDREXB of ADDR
extern uint8_t arm_lock_read_b(void* addr);
// STREXB of ADDR, return 0 if ok, 1 if not
extern int arm_lock_write_b(void* addr, uint8_t val);
// LDREXH of ADDR
extern uint16_t arm_lock_read_h(void* addr);
// STREXH of ADDR, return 0 if ok, 1 if not
extern int arm_lock_write_h(void* addr, uint16_t val);
// LDREX of ADDR
extern uint32_t arm_lock_read_d(void* addr);
// STREX of ADDR, return 0 if ok, 1 if not
extern int arm_lock_write_d(void* addr, uint32_t val);
// LDREXD of ADDR
extern void arm_lock_read_dd(uint32_t* a, uint32_t* b, void* addr);
// STREX of ADDR, return 0 if ok, 1 if not
extern int arm_lock_write_dd(uint32_t a, uint32_t b, void* addr);
// Atomicaly exchange value at [p] with val, return old p
extern uintptr_t arm_lock_xchg(void* p, uintptr_t val);
// Atomicaly store value to [p] only if [p] is NULL. Return new [p] value (so val or old)
extern void* arm_lock_storeifnull(void*p, void* val);
#endif //__ARM_LOCK_HELPER__H__
+28 -27
View File
@@ -96,7 +96,7 @@ const char* print_shift(int shift, int comma) {
return ret;
}
#define print_modified_imm_ARM(imm12) (((imm12 & 0xFF) >> (imm12 >> 8)) | ((imm12 & 0xFF) << (32 - (imm12 >> 8))))
#define print_modified_imm_ARM(imm12) (((imm12 & 0xFF) >> (2*(imm12 >> 8))) | ((imm12 & 0xFF) << (32 - 2*(imm12 >> 8))))
const char* print_register_list(int list, int size) {
int last = -2;
@@ -396,7 +396,7 @@ const char* arm_print(uint32_t opcode) {
int n = ((opcode >> 7) & 1) << 4 | ((opcode >> 16) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
sprintf(ret, "VSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + n], vecname[(q << 5) + 0x20 + m]);
sprintf(ret, "VSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + m], vecname[(q << 5) + 0x20 + n]);
} else if ((opcode & 0xFE800F10) == 0xF2000410) {
int u = (opcode >> 24) & 1;
int size = (opcode >> 20) & 0x3;
@@ -405,7 +405,7 @@ const char* arm_print(uint32_t opcode) {
int n = ((opcode >> 7) & 1) << 4 | ((opcode >> 16) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
sprintf(ret, "VQSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + n], vecname[(q << 5) + 0x20 + m]);
sprintf(ret, "VQSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + m], vecname[(q << 5) + 0x20 + n]);
} else if ((opcode & 0xFE800F10) == 0xF2000500) {
int u = (opcode >> 24) & 1;
int size = (opcode >> 20) & 0x3;
@@ -414,7 +414,7 @@ const char* arm_print(uint32_t opcode) {
int n = ((opcode >> 7) & 1) << 4 | ((opcode >> 16) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
sprintf(ret, "VRSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + n], vecname[(q << 5) + 0x20 + m]);
sprintf(ret, "VRSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + m], vecname[(q << 5) + 0x20 + n]);
} else if ((opcode & 0xFE800F10) == 0xF2000510) {
int u = (opcode >> 24) & 1;
int size = (opcode >> 20) & 0x3;
@@ -423,7 +423,7 @@ const char* arm_print(uint32_t opcode) {
int n = ((opcode >> 7) & 1) << 4 | ((opcode >> 16) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
sprintf(ret, "VQRSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + n], vecname[(q << 5) + 0x20 + m]);
sprintf(ret, "VQRSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + m], vecname[(q << 5) + 0x20 + n]);
} else if ((opcode & 0xFE800F00) == 0xF2000600) {
int op = (opcode >> 4) & 1;
int u = (opcode >> 24) & 1;
@@ -797,38 +797,38 @@ const char* arm_print(uint32_t opcode) {
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
sprintf(ret, "VMOVL.S8 %s, %s", vecname[0x40 + d], vecname[0x40 + m]);
sprintf(ret, "VMOVL.S8 %s, %s", vecname[0x40 + d], vecname[0x20 + m]);
} else if ((opcode & 0xFFBF0FD0) == 0xF2900A10) {
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
sprintf(ret, "VMOVL.S16 %s, %s", vecname[0x40 + d], vecname[0x40 + m]);
sprintf(ret, "VMOVL.S16 %s, %s", vecname[0x40 + d], vecname[0x20 + m]);
} else if ((opcode & 0xFFBF0FD0) == 0xF2A00A10) {
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
sprintf(ret, "VMOVL.S32 %s, %s", vecname[0x40 + d], vecname[0x40 + m]);
sprintf(ret, "VMOVL.S32 %s, %s", vecname[0x40 + d], vecname[0x20 + m]);
} else if ((opcode & 0xFFBF0FD0) == 0xF3880A10) {
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
sprintf(ret, "VMOVL.U8 %s, %s", vecname[0x40 + d], vecname[0x40 + m]);
sprintf(ret, "VMOVL.U8 %s, %s", vecname[0x40 + d], vecname[0x20 + m]);
} else if ((opcode & 0xFFBF0FD0) == 0xF3900A10) {
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
sprintf(ret, "VMOVL.U16 %s, %s", vecname[0x40 + d], vecname[0x40 + m]);
sprintf(ret, "VMOVL.U16 %s, %s", vecname[0x40 + d], vecname[0x20 + m]);
} else if ((opcode & 0xFFBF0FD0) == 0xF3A00A10) {
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
sprintf(ret, "VMOVL.U32 %s, %s", vecname[0x40 + d], vecname[0x40 + m]);
sprintf(ret, "VMOVL.U32 %s, %s", vecname[0x40 + d], vecname[0x20 + m]);
} else if ((opcode & 0xFE800F10) == 0xF2800010) {
int u = (opcode >> 24) & 1;
int q = (opcode >> 6) & 1;
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
uint8_t l = (opcode >> 1) & 0x1;
uint8_t l = (opcode >> 7) & 0x1;
uint8_t imm6 = (opcode >> 16) & 0x3F;
uint8_t decodedImm = 0;
uint8_t size = 0;
@@ -851,7 +851,7 @@ const char* arm_print(uint32_t opcode) {
int q = (opcode >> 6) & 1;
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
uint8_t l = (opcode >> 1) & 0x1;
uint8_t l = (opcode >> 7) & 0x1;
uint8_t imm6 = (opcode >> 16) & 0x3F;
uint8_t decodedImm = 0;
uint8_t size = 0;
@@ -874,7 +874,7 @@ const char* arm_print(uint32_t opcode) {
int q = (opcode >> 6) & 1;
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
uint8_t l = (opcode >> 1) & 0x1;
uint8_t l = (opcode >> 7) & 0x1;
uint8_t imm6 = (opcode >> 16) & 0x3F;
uint8_t decodedImm = 0;
uint8_t size = 0;
@@ -897,7 +897,7 @@ const char* arm_print(uint32_t opcode) {
int q = (opcode >> 6) & 1;
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
uint8_t l = (opcode >> 1) & 0x1;
uint8_t l = (opcode >> 7) & 0x1;
uint8_t imm6 = (opcode >> 16) & 0x3F;
uint8_t decodedImm = 0;
uint8_t size = 0;
@@ -919,7 +919,7 @@ const char* arm_print(uint32_t opcode) {
int q = (opcode >> 6) & 1;
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
uint8_t l = (opcode >> 1) & 0x1;
uint8_t l = (opcode >> 7) & 0x1;
uint8_t imm6 = (opcode >> 16) & 0x3F;
uint8_t decodedImm = 0;
uint8_t size = 0;
@@ -941,7 +941,7 @@ const char* arm_print(uint32_t opcode) {
int q = (opcode >> 6) & 1;
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
uint8_t l = (opcode >> 1) & 0x1;
uint8_t l = (opcode >> 7) & 0x1;
uint8_t imm6 = (opcode >> 16) & 0x3F;
uint8_t decodedImm = 0;
uint8_t size = 0;
@@ -963,7 +963,7 @@ const char* arm_print(uint32_t opcode) {
int q = (opcode >> 6) & 1;
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
uint8_t l = (opcode >> 1) & 0x1;
uint8_t l = (opcode >> 7) & 0x1;
uint8_t imm6 = (opcode >> 16) & 0x3F;
uint8_t decodedImm = 0;
uint8_t size = 0;
@@ -987,7 +987,7 @@ const char* arm_print(uint32_t opcode) {
int q = (opcode >> 6) & 1;
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
uint8_t l = (opcode >> 1) & 0x1;
uint8_t l = (opcode >> 7) & 0x1;
uint8_t imm6 = (opcode >> 16) & 0x3F;
uint8_t decodedImm = 0;
uint8_t size = 0;
@@ -1021,6 +1021,8 @@ const char* arm_print(uint32_t opcode) {
decodedImm = 16 - imm6;
}
++size;
sprintf(ret, "VSHRN.I%d %s, %s, #%d", 8 << size, vecname[0x20 + d], vecname[0x40 + m], decodedImm);
} else if ((opcode & 0xFF800FD0) == 0xF2800850) {
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
@@ -1316,7 +1318,6 @@ const char* arm_print(uint32_t opcode) {
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
u = 1 - u;
++size;
sprintf(ret, "VQMOVN.%s %s, %s", dts[(u << 2) + size], vecname[0x20 + d], vecname[0x40 + m]);
@@ -4446,24 +4447,24 @@ const char* arm_print(uint32_t opcode) {
} else if ((opcode & 0x0FE0007F) == 0x07C0001F) {
const char* cond = conds[(opcode >> 28) & 0xF];
int rd = (opcode >> 12) & 0xF;
int lsb = (opcode >> 7) & 0xF;
int msb = (opcode >> 16) & 0xF;
int lsb = (opcode >> 7) & 0x1F;
int msb = (opcode >> 16) & 0x1F;
sprintf(ret, "BFC%s %s, #%d, #%d", cond, regname[rd], lsb, msb - lsb + 1);
} else if ((opcode & 0x0FE00070) == 0x07C00010) {
const char* cond = conds[(opcode >> 28) & 0xF];
int rd = (opcode >> 12) & 0xF;
int rn = (opcode >> 0) & 0xF;
int lsb = (opcode >> 7) & 0xF;
int msb = (opcode >> 16) & 0xF;
int lsb = (opcode >> 7) & 0x1F;
int msb = (opcode >> 16) & 0x1F;
sprintf(ret, "BFI%s %s, %s, #%d, #%d", cond, regname[rd], regname[rn], lsb, msb - lsb + 1);
} else if ((opcode & 0x0FE00070) == 0x07E00050) {
const char* cond = conds[(opcode >> 28) & 0xF];
int rd = (opcode >> 12) & 0xF;
int rn = (opcode >> 0) & 0xF;
int lsb = (opcode >> 7) & 0xF;
int widthm1 = (opcode >> 16) & 0xF;
int lsb = (opcode >> 7) & 0x1F;
int widthm1 = (opcode >> 16) & 0x1F;
sprintf(ret, "UBFX%s %s, %s, #%d, #%d", cond, regname[rd], regname[rn], lsb, widthm1 + 1);
} else if ((opcode & 0x0FDF0000) == 0x080D0000) {
@@ -4826,7 +4827,7 @@ const char* arm_print(uint32_t opcode) {
int param1_2 = (opcode >> 21) & 0x3;
int param2_2 = (opcode >> 5) & 0x3;
uint8_t opc = (u << 3) + (param1_2 << 2) + param2_2;
uint8_t opc = (u << 4) + (param1_2 << 2) + param2_2;
uint8_t shift, size;
if ((opc & 0b01000) == 0b01000) {
shift = 0;
+146 -307
View File
@@ -20,6 +20,7 @@
#include "elfloader.h"
#ifdef ARM
#include "dynarec_arm.h"
#include "arm_lock_helper.h"
#else
#error Unsupported architecture!
#endif
@@ -28,8 +29,6 @@
KHASH_MAP_INIT_INT(dynablocks, dynablock_t*)
KHASH_SET_INIT_INT(mark)
uint32_t X31_hash_code(void* addr, int len)
{
if(!len) return 0;
@@ -41,13 +40,15 @@ uint32_t X31_hash_code(void* addr, int len)
dynablocklist_t* NewDynablockList(uintptr_t base, uintptr_t text, int textsz, int nolinker, int direct)
{
if(!textsz) {
printf_log(LOG_NONE, "Error, creating a NULL sized Dynablock\n");
return NULL;
}
dynablocklist_t* ret = (dynablocklist_t*)calloc(1, sizeof(dynablocklist_t));
ret->blocks = (nolinker && direct)?NULL:kh_init(dynablocks);
ret->base = base;
ret->text = text;
ret->textsz = textsz;
ret->nolinker = nolinker;
pthread_rwlock_init(&ret->rwlock_blocks, NULL);
if(direct && textsz) {
ret->direct = (dynablock_t**)calloc(textsz, sizeof(dynablock_t*));
if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
@@ -58,8 +59,11 @@ dynablocklist_t* NewDynablockList(uintptr_t base, uintptr_t text, int textsz, in
void FreeDynablock(dynablock_t* db)
{
if(db) {
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p father=%p, tablesz=%d, %swith %d son(s)\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->father, db->tablesz, db->marks?"with marks, ":"", db->sons_size);
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p father=%p, tablesz=%d, with %d son(s) already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->father, db->tablesz, db->sons_size, db->gone);
if(db->gone)
return; // already in the process of deletion!
db->done = 0;
db->gone = 1;
// remove from direct if there
uintptr_t startdb = db->parent->text;
uintptr_t enddb = db->parent->text + db->parent->textsz;
@@ -68,52 +72,19 @@ void FreeDynablock(dynablock_t* db)
if(addr>=startdb && addr<enddb)
db->parent->direct[addr-startdb] = NULL;
}
// remove from hash if there
if (db->parent->blocks) {
khint_t kdb;
kdb = kh_get(dynablocks, db->parent->blocks, (uintptr_t) db->x86_addr - db->parent->base);
if(kdb!=kh_end(db->parent->blocks))
kh_del(dynablocks, db->parent->blocks, kdb);
}
if(db->marks) {
// Follow mark and set arm_linker instead
khint_t k;
kh_foreach_key(db->marks, k,
void** p = (void**)(uintptr_t)k;
dynarec_log(LOG_DEBUG, " -- resettable(%p)\n", p);
resettable(p);
);
// free mark
kh_destroy(mark, db->marks);
db->marks = NULL;
}
for(int i=0; i<db->tablesz; i+=4) {
dynablock_t* p = (dynablock_t*)db->table[i+3];
dynarec_log(LOG_DEBUG, " -- table[%d+3] = %p ", i, p);
if(p && p!=db && p->marks) {
khint_t kd = kh_get(mark, p->marks, (uintptr_t)(&db->table[i+0]));
if(kd!=kh_end(p->marks)) {
kh_del(mark, p->marks, kd);
dynarec_log(LOG_DEBUG, "cleaned");
}
else {dynarec_log(LOG_DEBUG, "not found");}
}
dynarec_log(LOG_DEBUG, "\n");
}
// remove and free the sons
for (int i=0; i<db->sons_size; ++i) {
dynablock_t *son = db->sons[i];
db->sons[i] = NULL;
dynablock_t *son = (dynablock_t*)arm_lock_xchg(&db->sons[i], 0);
FreeDynablock(son);
}
// only the father free the DynarecMap
if(!db->father) {
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
FreeDynarecMap((uintptr_t)db->block, db->size);
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
}
free(db->sons);
free(db->table);
free(db->instsize);
free(db);
}
}
@@ -124,21 +95,7 @@ void FreeDynablockList(dynablocklist_t** dynablocks)
return;
if(!*dynablocks)
return;
dynarec_log(LOG_INFO, "Free %d Blocks from Dynablocklist (with %d buckets, nolinker=%d) %s\n", (*dynablocks)->blocks?kh_size((*dynablocks)->blocks):0, (*dynablocks)->blocks?kh_n_buckets((*dynablocks)->blocks):0, (*dynablocks)->nolinker, ((*dynablocks)->direct)?" With Direct mapping enabled":"");
dynablock_t* db;
if((*dynablocks)->blocks) {
// create a list of the parent db to delete (because there are sons in the middle that will be invalid if father is removed)
dynablock_t** list = (dynablock_t**)calloc(kh_size((*dynablocks)->blocks), sizeof(dynablock_t*));
int n = 0;
kh_foreach_value((*dynablocks)->blocks, db,
if(!db->father) list[n++] = db;
);
for (int i=0; i<n; ++i)
FreeDynablock(list[i]);
kh_destroy(dynablocks, (*dynablocks)->blocks);
(*dynablocks)->blocks = NULL;
free(list);
}
dynarec_log(LOG_DEBUG, "Free Direct Blocks %p from Dynablocklist nolinker=%d\n", (*dynablocks)->direct, (*dynablocks)->nolinker);
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father)
@@ -146,9 +103,7 @@ void FreeDynablockList(dynablocklist_t** dynablocks)
}
free((*dynablocks)->direct);
}
(*dynablocks)->direct = 0;
pthread_rwlock_destroy(&(*dynablocks)->rwlock_blocks);
(*dynablocks)->direct = NULL;
free(*dynablocks);
*dynablocks = NULL;
@@ -159,17 +114,8 @@ void MarkDynablock(dynablock_t* db)
if(db) {
if(db->father)
db = db->father; // mark only father
if(db->marks && !db->need_test) {
// Follow mark and set arm_linker instead
khint_t k;
kh_foreach_key(db->marks, k,
void** p = (void**)(uintptr_t)k;
resettable(p);
);
// free mark
kh_clear(mark, db->marks);
}
db->need_test = 1;
if(db->nolinker)
db->need_test = 1; // test only blocks that can be marked (and so deleted)
}
}
@@ -182,79 +128,38 @@ void ProtectDynablock(dynablock_t* db)
}
}
void RemoveMark(void** table)
{
// remove old value if any
dynablock_t *old = (dynablock_t*)table[3];
if(old && old->father)
old = old->father;
if(old && old->marks) {
khint_t kd = kh_get(mark, old->marks, (uintptr_t)table);
if(kd!=kh_end(old->marks))
kh_del(mark, old->marks, kd);
}
table[3] = NULL;
}
// source is linked to dest (i.e. source->table[x] = dest->block), so add a "mark" in dest, add a "linked" info to source
void AddMark(dynablock_t* source, dynablock_t* dest, void** table)
{
int ret;
// remove old value if any
dynablock_t *old = (dynablock_t*)table[3];
if(old && old->father)
old = old->father;
if(old && old->marks) {
khint_t kd = kh_get(mark, old->marks, (uintptr_t)table);
if(kd!=kh_end(old->marks))
kh_del(mark, old->marks, kd);
}
// add mark if needed
if(dest->father)
dest = dest->father;
if(dest->marks) {
kh_put(mark, dest->marks, (uintptr_t)table, &ret);
table[3] = (void*)dest;
} else
table[3] = NULL;
}
void MarkDynablockList(dynablocklist_t** dynablocks)
{
if(!dynablocks)
return;
if(!*dynablocks)
return;
dynarec_log(LOG_DEBUG, "Marked %d Blocks from Dynablocklist (with %d buckets, nolinker=%d) %p:0x%x %s\n", (*dynablocks)->blocks?(kh_size((*dynablocks)->blocks)):0, (*dynablocks)->blocks?(kh_n_buckets((*dynablocks)->blocks)):0, (*dynablocks)->nolinker, (void*)(*dynablocks)->text, (*dynablocks)->textsz, ((*dynablocks)->direct)?" With Direct mapping enabled":"");
if(!(*dynablocks)->nolinker)
return;
dynarec_log(LOG_DEBUG, "Marked Blocks from Dynablocklist nolinker=%d %p:0x%x\n", (*dynablocks)->nolinker, (void*)(*dynablocks)->text, (*dynablocks)->textsz);
dynablock_t* db;
if((*dynablocks)->blocks) {
kh_foreach_value((*dynablocks)->blocks, db,
MarkDynablock(db);
);
}
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
MarkDynablock((*dynablocks)->direct[i]);
db = (*dynablocks)->direct[i];
if(db)
MarkDynablock(db);
}
}
}
void ProtectkDynablockList(dynablocklist_t** dynablocks)
void ProtectDynablockList(dynablocklist_t** dynablocks)
{
if(!dynablocks)
return;
if(!*dynablocks)
return;
dynarec_log(LOG_DEBUG, "Protect %d Blocks from Dynablocklist (with %d buckets, nolinker=%d) %p:0x%x %s\n", (*dynablocks)->blocks?(kh_size((*dynablocks)->blocks)):0, (*dynablocks)->blocks?(kh_n_buckets((*dynablocks)->blocks)):0, (*dynablocks)->nolinker, (void*)(*dynablocks)->text, (*dynablocks)->textsz, ((*dynablocks)->direct)?" With Direct mapping enabled":"");
dynarec_log(LOG_DEBUG, "Protect Blocks from Dynablocklist nolinker=%d %p:0x%x\n", (*dynablocks)->nolinker, (void*)(*dynablocks)->text, (*dynablocks)->textsz);
dynablock_t* db;
if((*dynablocks)->blocks) {
kh_foreach_value((*dynablocks)->blocks, db,
ProtectDynablock(db);
);
}
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
ProtectDynablock((*dynablocks)->direct[i]);
db = (*dynablocks)->direct[i];
if(db)
ProtectDynablock(db);
}
}
}
@@ -268,31 +173,15 @@ uintptr_t StartDynablockList(dynablocklist_t* db)
uintptr_t EndDynablockList(dynablocklist_t* db)
{
if(db)
return db->text+db->textsz;
return db->text+db->textsz-1;
return 0;
}
void FreeDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
uintptr_t start = addr;
uintptr_t end = addr+size;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i)
if(dynablocks->direct[i-startdb]) {
FreeDynablock(dynablocks->direct[i-startdb]);
}
}
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
if(!dynablocks->nolinker)
return;
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
uintptr_t start = addr;
@@ -328,128 +217,87 @@ void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
{
if(!dynablocks)
return;
if(dynablocks->direct)
FreeDirectDynablock(dynablocks, addr, size);
if(dynablocks->blocks) {
if(dynablocks->direct) {
dynablock_t* db;
uintptr_t s, e;
kh_foreach_value(dynablocks->blocks, db,
s = (uintptr_t)db->x86_addr;
e = (uintptr_t)db->x86_addr+db->x86_size-1;
if((s>=addr && s<(addr+size)) || (e>=addr && e<(addr+size)))
ProtectDynablock(db);
int ret;
khint_t k;
kh_dynablocks_t *blocks = kh_init(dynablocks);
// copy in a temporary list
if(dynablocks->direct) {
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
uintptr_t start = addr;
uintptr_t end = addr+size;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i) {
db = (dynablock_t*)arm_lock_xchg(&dynablocks->direct[i-startdb], 0);
if(db) {
if(db->father)
db = db->father;
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
kh_value(blocks, k) = db;
}
}
}
// purge the list
kh_foreach_value(blocks, db,
FreeDynablock(db);
);
kh_destroy(dynablocks, blocks);
}
}
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
if(!dynablocks->nolinker)
return;
if(dynablocks->direct)
MarkDirectDynablock(dynablocks, addr, size);
if(dynablocks->blocks) {
dynablock_t* db;
uintptr_t s, e;
kh_foreach_value(dynablocks->blocks, db,
s = (uintptr_t)db->x86_addr;
e = (uintptr_t)db->x86_addr+db->x86_size-1;
if((s>=addr && s<(addr+size)) || (e>=addr && e<(addr+size)))
MarkDynablock(db);
);
}
}
dynablock_t* FindDynablockDynablocklist(void* addr, dynablocklist_t* dynablocks)
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks)
{
if(!dynablocks)
return NULL;
if(dynablocks->direct)
for(int i=0; i<dynablocks->textsz; ++i) {
if(dynablocks->direct[i]) {
dynablock_t* db = dynablocks->direct[i];
uintptr_t s = (uintptr_t)db->block;
uintptr_t e = (uintptr_t)db->block+db->size;
if(s>=(uintptr_t)addr && e<(uintptr_t)addr)
return db->father?db->father:db;
}
}
if(dynablocks->blocks) {
dynablock_t* db;
uintptr_t s, e;
kh_foreach_value(dynablocks->blocks, db,
s = (uintptr_t)db->block;
e = (uintptr_t)db->block+db->size;
if((uintptr_t)addr>=s && (uintptr_t)addr<e)
return db->father?db->father:db;
);
}
dynablock_t* db;
kh_foreach_value(dynablocks, db,
uintptr_t s = (uintptr_t)db->block;
uintptr_t e = (uintptr_t)db->block+db->size;
if((uintptr_t)addr>=s && (uintptr_t)addr<e)
return db->father?db->father:db;
)
return NULL;
}
dynablock_t* FindDynablockFromNativeAddress(void* addr)
static dynablocklist_t* getDBFromAddress(uintptr_t addr)
{
// unoptimized search through all dynablockslist for the dynablock that contains native addr (NULL if not found)
// search "volatile" dynarec first
dynablock_t *ret = NULL;
for(int idx=0; idx<65536 && !ret; ++idx)
if(my_context->dynmap[idx])
ret = FindDynablockDynablocklist(addr, my_context->dynmap[idx]->dynablocks);
if(ret)
return ret;
// search elfs
for(int idx=0; idx<my_context->elfsize && !ret; ++idx)
ret = FindDynablockDynablocklist(addr, GetDynablocksFromElf(my_context->elfs[idx]));
// last, search context dynablocks
if(my_context->dynablocks)
ret = FindDynablockDynablocklist(addr, my_context->dynablocks);
return ret;
const int idx = (addr>>DYNAMAP_SHIFT);
return (my_context->dynmap[idx])?my_context->dynmap[idx]:NULL;
}
void ConvertHash2Direct(dynablocklist_t* dynablocks)
{
if(dynablocks->textsz==0 || dynablocks->text==0 || !dynablocks->blocks)
return; // nothing to do
// create the new set
dynablock_t **direct = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*));
kh_dynablocks_t *blocks = kh_init(dynablocks);
// transfert
int ret;
khint_t k;
dynablock_t* db;
uintptr_t key;
uintptr_t start = dynablocks->text;
uintptr_t end = start + dynablocks->textsz;
kh_foreach(dynablocks->blocks, key, db,
key += dynablocks->base;
if(key>=start && key<end)
direct[key-start] = db;
else {
k = kh_put(dynablocks, blocks, key-dynablocks->base, &ret);
if(ret) { // don't try to insert if already done...
kh_value(blocks, k) = db;
}
}
);
// destroy old and do the swap (should swap before destroy, but hash access is always behind mutex)
kh_destroy(dynablocks, dynablocks->blocks);
dynablocks->blocks = blocks;
dynablocks->direct = direct;
}
#define MAGIC_SIZE 256
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int with_marks, int* created)
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created)
{
if(!dynablocks) {
dynarec_log(LOG_INFO, "Warning: Ask to create a dynblock with a NULL dynablocklist (addr=%p)\n", (void*)addr);
dynarec_log(LOG_INFO, "Warning: Ask to create a dynablock with a NULL dynablocklist (addr=%p)\n", (void*)addr);
*created = 0;
return NULL;
}
khint_t k;
int ret;
if((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz))) {
// this should be useless
//dynarec_log(LOG_INFO, "Warning: Refused to create a Direct Block that is out-of-bound: dynablocks=%p (%p:%p), addr=%p\n", dynablocks, (void*)(dynablocks->text), (void*)(dynablocks->text+dynablocks->textsz), (void*)addr);
//*created = 0;
//return NULL;
return AddNewDynablock(getDBFromAddress(addr), addr, created);
}
dynablock_t* block = NULL;
// first, check if it exist in direct access mode
if(dynablocks->direct && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))) {
if(dynablocks->direct) {
block = dynablocks->direct[addr-dynablocks->text];
if(block) {
dynarec_log(LOG_DUMP, "Block already exist in Direct Map\n");
@@ -458,58 +306,25 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int wi
}
}
if(dynablocks->blocks) {
pthread_rwlock_rdlock(&dynablocks->rwlock_blocks);
// check if the block exist
khint_t k;
k = kh_get(dynablocks, dynablocks->blocks, addr-dynablocks->base);
if(k!=kh_end(dynablocks->blocks)) {
block = kh_value(dynablocks->blocks, k);
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
dynarec_log(LOG_DUMP, "Block already exist in Hash Map\n");
*created = 0;
return block;
}
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
}
if (!*created)
return block;
// Lock as write now!
pthread_rwlock_wrlock(&dynablocks->rwlock_blocks);
if(!dynablocks->direct)
dynablocks->direct = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*));
// create and add new block
dynarec_log(LOG_DUMP, "Ask for DynaRec Block creation @%p\n", (void*)addr);
if(dynablocks->direct && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))) {
block = dynablocks->direct[addr-dynablocks->text] = (dynablock_t*)calloc(1, sizeof(dynablock_t));
} else {
if(dynablocks->nolinker && ((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz)))) {
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
//dynarec_log(LOG_INFO, "Warning: Refused to create a Direct Block that is out-of-bound: dynablocks=%p (%p:%p), addr=%p\n", dynablocks, (void*)(dynablocks->text), (void*)(dynablocks->text+dynablocks->textsz), (void*)addr);
//*created = 0;
//return NULL;
return AddNewDynablock(getDBFromAddress(addr), addr, with_marks, created);
}
k = kh_put(dynablocks, dynablocks->blocks, addr-dynablocks->base, &ret);
if(!ret) {
// Ooops, block is already there? retreive it and bail out
dynarec_log(LOG_DUMP, "Block already exist in Hash Map\n");
block = kh_value(dynablocks->blocks, k);
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
*created = 0;
return block;
}
block = kh_value(dynablocks->blocks, k) = (dynablock_t*)calloc(1, sizeof(dynablock_t));
// check if size of hash map == magic size, if yes, convert to direct before unlocking
if(!dynablocks->direct && kh_size(dynablocks->blocks)==MAGIC_SIZE)
ConvertHash2Direct(dynablocks);
}
block->parent = dynablocks;
// add mark if needed
if(with_marks)
block->marks = kh_init(mark);
// create an empty block first, so if other thread want to execute the same block, they can, but using interpretor path
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
block = (dynablock_t*)calloc(1, sizeof(dynablock_t));
dynablock_t* tmp = (dynablock_t*)arm_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
if(tmp != block) {
// a block appeard!
free(block);
*created = 0;
return tmp;
}
block->parent = dynablocks;
*created = 1;
return block;
@@ -519,65 +334,89 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int wi
return NULL if block is not found / cannot be created.
Don't create if create==0
*/
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t* current)
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current)
{
// try the quickest way first: get parent of current and check if ok!
dynablocklist_t *dynablocks = NULL;
dynablock_t* block = NULL;
if(current) {
dynablocks = current->parent;
if(!(addr>=dynablocks->text && addr<(dynablocks->text+dynablocks->textsz)))
dynablocks = current->parent;
if(dynablocks && !(addr>=dynablocks->text && addr<(dynablocks->text+dynablocks->textsz)))
dynablocks = NULL;
else if(dynablocks->direct && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))) {
block = dynablocks->direct[addr-dynablocks->text];
if(block)
return block;
}
}
// nope, lets do the long way
if(!dynablocks)
dynablocks = GetDynablocksFromAddress(emu->context, addr);
if(!dynablocks)
return NULL;
if(!dynablocks) {
dynablocks = getDBFromAddress(addr);
if(!dynablocks) {
dynablocks = GetDynablocksFromAddress(emu->context, addr);
if(!dynablocks)
return NULL;
}
}
// check direct first, without lock
if(dynablocks->direct && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz)))
block = dynablocks->direct[addr-dynablocks->text];
if(block)
return block;
if(dynablocks->direct/* && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))*/)
if((block = dynablocks->direct[addr-dynablocks->text]))
return block;
int created = create;
block = AddNewDynablock(dynablocks, addr, (dynablocks->nolinker)&&(dynablocks->direct), &created);
if(!created || !create)
block = AddNewDynablock(dynablocks, addr, &created);
if(!created)
return block; // existing block...
if(box86_dynarec_dump)
pthread_mutex_lock(&my_context->mutex_lock);
pthread_mutex_lock(&my_context->mutex_dyndump);
// fill the block
block->x86_addr = (void*)addr;
FillBlock(block);
if(!FillBlock(block, filladdr)) {
dynablocks->direct[addr-dynablocks->text] = NULL;
free(block);
block = NULL;
}
if(box86_dynarec_dump)
pthread_mutex_unlock(&my_context->mutex_lock);
pthread_mutex_unlock(&my_context->mutex_dyndump);
dynarec_log(LOG_DEBUG, " --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, %swith %d son(s))\n", created?"created":"recycled", (void*)addr, (void*)(addr+block->x86_size), block->block, block->size, block->marks?"with Marks, ":"", block->sons_size);
dynarec_log(LOG_DEBUG, " --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, with %d son(s))\n", created?"created":"recycled", (void*)addr, (void*)(addr-((block)?block->x86_size:0)), (block)?block->block:0, (block)?block->size:0, (block)?block->sons_size:0);
return block;
}
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current)
{
dynablock_t *db = internalDBGetBlock(emu, addr, create, *current);
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current);
if(db && (db->need_test || (db->father && db->father->need_test))) {
dynablock_t *father = db->father?db->father:db;
uint32_t hash = X31_hash_code(father->x86_addr, father->x86_size);
uint32_t hash = father->nolinker?X31_hash_code(father->x86_addr, father->x86_size):0;
if(hash!=father->hash) {
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X)%s with %d son(s)\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->marks?" with Mark,":"", father->sons_size);
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s)\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size);
// no more current if it gets invalidated too
if(*current && father->x86_addr>=(*current)->x86_addr && (father->x86_addr+father->x86_size)<(*current)->x86_addr)
*current = NULL;
// Free father, it's now invalid!
FreeDynablock(father);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, create, *current);
db = internalDBGetBlock(emu, addr, addr, create, *current);
} else {
father->need_test = 0;
protectDB((uintptr_t)father->x86_addr, father->x86_size);
}
}
return db;
}
dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
{
dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr);
int create = 1;
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
if(db && (db->need_test || (db->father && db->father->need_test))) {
dynablock_t *father = db->father?db->father:db;
uint32_t hash = father->nolinker?X31_hash_code(father->x86_addr, father->x86_size):0;
if(hash!=father->hash) {
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s)\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size);
// Free father, it's now invalid!
FreeDynablock(father);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
} else {
father->need_test = 0;
protectDB((uintptr_t)father->x86_addr, father->x86_size);
+12 -9
View File
@@ -2,35 +2,38 @@
#define __DYNABLOCK_PRIVATE_H_
typedef struct dynablocklist_s dynablocklist_t;
typedef struct kh_dynablocks_s kh_dynablocks_t;
typedef struct kh_mark_s kh_mark_t;
typedef struct instsize_s {
unsigned int x86:4;
unsigned int nat:4;
} instsize_t;
typedef struct dynablock_s {
dynablocklist_t* parent;
kh_mark_t* marks; // List of blocks that marked this block
void* block;
int size;
void* x86_addr;
int x86_size;
uint32_t hash;
int need_test;
uintptr_t* table;
int tablesz;
int done;
uint8_t need_test;
uint8_t done;
uint8_t gone;
uint8_t nolinker;
int isize;
dynablock_t** sons; // sons (kind-of dummy dynablock...)
int sons_size;
dynablock_t* father; // set only in the case of a son
instsize_t* instsize;
} dynablock_t;
typedef struct dynablocklist_s {
kh_dynablocks_t *blocks;
pthread_rwlock_t rwlock_blocks;
uintptr_t base;
uintptr_t text;
int textsz;
uintptr_t base;
int nolinker; // in case this dynablock can disapear (also, block memory are allocated with a temporary scheme)
dynablock_t **direct; // direct mapping (waste of space, so not always there)
dynablock_t** direct; // direct mapping (waste of space, so not always there)
} dynablocklist_t;
#endif //__DYNABLOCK_PRIVATE_H_
+63 -14
View File
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <setjmp.h>
#include "debug.h"
#include "box86context.h"
@@ -14,6 +15,7 @@
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "threads.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "dynablock_private.h"
@@ -54,18 +56,15 @@ void* UpdateLinkTable(x86emu_t* emu, void** table, uintptr_t addr)
dynablock_t* current = (dynablock_t*)table[2];
if(current->father)
current = current->father;
void * jblock;
dynablock_t* block = DBGetBlock(emu, addr, 1, &current);
if(!current) { // current has been invalidated, stop running it...
//dynarec_log(LOG_DEBUG, "--- Current invalidated while linking.\n");
return arm_epilog_fast;
}
if(table[3]) {
//dynarec_log(LOG_DEBUG, "--- Remove mark from %p (%p)\n", current, table[3]);
RemoveMark(table);
}
if(!block) {
// no block, don't try again, ever
tableupdate(arm_epilog, addr, table);
// no block, let link table as is...
//tableupdate(arm_epilog, addr, table);
return arm_epilog_fast;
}
if(!block->done) {
@@ -73,25 +72,38 @@ void* UpdateLinkTable(x86emu_t* emu, void** table, uintptr_t addr)
//tableupdate(arm_linker, addr, table);
return arm_epilog_fast;
}
if(!block->block) {
if(!(jblock=block->block)) {
// null block, but done: go to epilog, no linker here
tableupdate(arm_epilog, addr, table);
return arm_epilog_fast;
}
dynablock_t *father = block->father?block->father:block;
if(!block->parent->nolinker || (current && father->marks)) {
//dynablock_t *father = block->father?block->father:block;
if(!block->parent->nolinker) {
//dynarec_log(LOG_DEBUG, "--- Linking %p/%p to %p (table=%p[%p/%p/%p/%p])\n", block, block->block, current, table, table[0], table[1], table[2], table[3]);
// only update block if linker is allowed or if marks is possibe
if(current && father->marks && current!=father)
AddMark(current, father, table);
tableupdate(block->block, addr, table);
// only update block if linker is allowed
tableupdate(jblock, addr, table);
}
return block->block;
return jblock;
}
#endif
void DynaCall(x86emu_t* emu, uintptr_t addr)
{
// prepare setjump for signal handling
emu_jmpbuf_t *ejb = NULL;
int jmpbuf_reset = 0;
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
if(!ejb->jmpbuf_ok) {
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) {
printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
addr = R_EIP; // not sure if it should still be inside DynaCall!
}
}
}
#ifdef DYNAREC
if(!box86_dynarec)
#endif
@@ -130,6 +142,16 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
emu->quit = 0;
emu->fork = 0;
emu = x86emu_fork(emu, forktype);
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) {
printf_log(LOG_DEBUG, "Setjmp inner DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
addr = R_EIP;
}
}
}
}
emu->quit = 0; // reset Quit flags...
@@ -146,10 +168,26 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
}
}
#endif
// clear the setjmp
if(ejb && jmpbuf_reset)
ejb->jmpbuf_ok = 0;
}
int DynaRun(x86emu_t* emu)
{
// prepare setjump for signal handling
emu_jmpbuf_t *ejb = NULL;
int jmpbuf_reset = 1;
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
if(!ejb->jmpbuf_ok) {
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
}
}
#ifdef DYNAREC
if(!box86_dynarec)
#endif
@@ -178,9 +216,20 @@ int DynaRun(x86emu_t* emu)
emu->quit = 0;
emu->fork = 0;
emu = x86emu_fork(emu, forktype);
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
}
}
}
}
// clear the setjmp
if(ejb && jmpbuf_reset)
ejb->jmpbuf_ok = 0;
return 0;
#endif
}
+71 -11
View File
@@ -114,8 +114,11 @@ int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n)
uint32_t needed_flags(dynarec_arm_t *dyn, int ninst, uint32_t setf, int recurse)
{
if(ninst == dyn->size || (recurse==5))
return X_ALL; // no more instructions, or too many jmp loop, stop
if(recurse == 10)
return X_PEND;
if(ninst == dyn->size)
return X_PEND; // no more instructions, or too many jmp loop, stop
uint32_t needed = dyn->insts[ninst].x86.use_flags;
if(needed) {
setf &= ~needed;
@@ -156,14 +159,42 @@ uint32_t needed_flags(dynarec_arm_t *dyn, int ninst, uint32_t setf, int recurse)
return needed;
}
instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86_size, int arm_size)
{
// x86 instruction is <16 bytes
int toadd;
if(x86_size>arm_size)
toadd = 1 + x86_size/15;
else
toadd = 1 + arm_size/15;
if((*size)+toadd>(*cap)) {
*cap = (*size)+toadd;
insts = (instsize_t*)realloc(insts, (*cap)*sizeof(instsize_t));
}
while(toadd) {
if(x86_size>15)
insts[*size].x86 = 15;
else
insts[*size].x86 = x86_size;
x86_size -= insts[*size].x86;
if(arm_size>15)
insts[*size].nat = 15;
else
insts[*size].nat = arm_size;
arm_size -= insts[*size].nat;
++(*size);
--toadd;
}
return insts;
}
void arm_pass0(dynarec_arm_t* dyn, uintptr_t addr);
void arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
void arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
void arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
void* FillBlock(dynablock_t* block) {
void* FillBlock(dynablock_t* block, uintptr_t addr) {
// init the helper
uintptr_t addr = (uintptr_t)block->x86_addr;
dynarec_arm_t helper = {0};
helper.nolinker = box86_dynarec_linker?(block->parent->nolinker):1;
helper.start = addr;
@@ -209,11 +240,12 @@ void* FillBlock(dynablock_t* block) {
arm_pass2(&helper, addr);
// ok, now allocate mapped memory, with executable flag on
int sz = helper.arm_size;
void* p = (void*)AllocDynarecMap(sz, block->parent->nolinker);
void* p = (void*)AllocDynarecMap(block, sz);
if(p==NULL) {
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %d) failed, cancelling block\n", block, sz);
free(helper.insts);
free(helper.next);
return (void*)block;
return NULL;
}
helper.block = p;
helper.arm_start = (uintptr_t)p;
@@ -232,9 +264,32 @@ void* FillBlock(dynablock_t* block) {
}
helper.arm_size = 0;
arm_pass3(&helper, addr);
if(sz!=helper.arm_size) {printf_log(LOG_NONE, "BOX86: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size);}
if(sz!=helper.arm_size) {
printf_log(LOG_NONE, "BOX86: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size);
uint8_t *dump = (uint8_t*)helper.start;
printf_log(LOG_NONE, "Dump of %d x86 opcodes:\n", helper.size);
for(int i=0; i<helper.size; ++i) {
printf_log(LOG_NONE, "%p:", dump);
for(; dump<(uint8_t*)helper.insts[i+1].x86.addr; ++dump)
printf_log(LOG_NONE, " %02X", *dump);
printf_log(LOG_NONE, "\t%d -> %d\n", helper.insts[i].size2, helper.insts[i].size);
}
printf_log(LOG_NONE, " ------------\n");
}
// all done...
__builtin___clear_cache(p, p+sz); // need to clear the cache before execution...
__clear_cache(p, p+sz); // need to clear the cache before execution...
// keep size of instructions for signal handling
{
size_t cap = 1;
for(int i=0; i<helper.size; ++i)
cap += 1 + ((helper.insts[i].x86.size>helper.insts[i].size)?helper.insts[i].x86.size:helper.insts[i].size)/15;
size_t size = 0;
block->instsize = (instsize_t*)calloc(cap, sizeof(instsize_t));
for(int i=0; i<helper.size; ++i)
block->instsize = addInst(block->instsize, &size, &cap, helper.insts[i].x86.size, helper.insts[i].size/4);
block->instsize = addInst(block->instsize, &size, &cap, 0, 0); // add a "end of block" mark, just in case
}
// ok, free the helper now
free(helper.insts);
free(helper.next);
block->table = helper.table;
@@ -244,8 +299,9 @@ void* FillBlock(dynablock_t* block) {
block->size = sz;
block->isize = helper.size;
block->block = p;
block->nolinker = helper.nolinker;
block->need_test = 0;
block->x86_addr = (void*)start;
//block->x86_addr = (void*)start;
block->x86_size = end-start;
if(box86_dynarec_largest<block->x86_size)
box86_dynarec_largest = block->x86_size;
@@ -257,8 +313,8 @@ void* FillBlock(dynablock_t* block) {
sons = (dynablock_t**)calloc(helper.sons_size, sizeof(dynablock_t*));
for (int i=0; i<helper.sons_size; ++i) {
int created = 1;
dynablock_t *son = AddNewDynablock(block->parent, helper.sons_x86[i], 0, &created);
if(created) { // avoid breaking a working block! also, block could be outside this parent...
dynablock_t *son = AddNewDynablock(block->parent, helper.sons_x86[i], &created);
if(created || !son->parent) { // avoid breaking a working block! also, block could be outside this parent...
son->block = helper.sons_arm[i];
son->x86_addr = (void*)helper.sons_x86[i];
son->x86_size = end-helper.sons_x86[i];
@@ -266,6 +322,8 @@ void* FillBlock(dynablock_t* block) {
son->father = block;
son->done = 1;
sons[sons_size++] = son;
if(!son->parent)
son->parent = block->parent;
}
}
if(sons_size) {
@@ -276,6 +334,8 @@ void* FillBlock(dynablock_t* block) {
}
if(block->parent->nolinker)
protectDB((uintptr_t)block->x86_addr, block->x86_size);
free(helper.sons_x86);
free(helper.sons_arm);
block->done = 1;
return (void*)block;
}
+189 -117
View File
@@ -23,15 +23,12 @@
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop, opcode;
uintptr_t natcall;
int retn;
uint8_t gd, ed;
int8_t i8;
int32_t i32, tmp;
int32_t i32, j32, tmp;
uint8_t u8;
uint8_t gb1, gb2, eb1, eb2;
uint32_t u32;
@@ -42,6 +39,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(tmp);
MAYUSE(j32);
switch(opcode) {
case 0x00:
@@ -105,7 +103,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
POP(xESP, 1<<x2);
STRH_REG(x2, xEmu, x1);
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[_ES]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_serial[_ES]));
break;
case 0x08:
INST_NAME("OR Eb, Gb");
@@ -283,7 +281,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
POP(xESP, 1<<x2);
STRH_REG(x2, xEmu, x1);
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[_DS]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_serial[_DS]));
break;
case 0x20:
INST_NAME("AND Eb, Gb");
@@ -590,15 +588,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV_REG(x1, xESP);
// cannot use PUSH (STMdb!) because order of regs are reversed!
//PUSH(x1, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI));
PUSH(x1, (1<<xEAX));
PUSH(x1, (1<<xECX));
PUSH(x1, (1<<xEDX));
PUSH(x1, (1<<xEBX));
PUSH(x1, (1<<xESP));
PUSH(x1, (1<<xEBP));
PUSH(x1, (1<<xESI));
PUSH(x1, (1<<xEDI));
MOV_REG(xESP, x1);
PUSH(xESP, (1<<xEAX));
PUSH(xESP, (1<<xECX));
PUSH(xESP, (1<<xEDX));
PUSH(xESP, (1<<xEBX));
PUSH(xESP, (1<<x1));
PUSH(xESP, (1<<xEBP));
PUSH(xESP, (1<<xESI));
PUSH(xESP, (1<<xEDI));
break;
case 0x61:
INST_NAME("POPAD");
@@ -636,8 +633,15 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x68:
INST_NAME("PUSH Id");
i32 = F32S;
MOV32(x3, i32);
PUSH(xESP, 1<<x3);
if(PK(0)==0xC3) {
MESSAGE(LOG_DUMP, "PUSH then RET, using indirect\n");
MOV32(x3, ip+1);
LDR_IMM9(x1, x3, 0);
PUSH(xESP, 1<<x1);
} else {
MOV32(x3, i32);
PUSH(xESP, 1<<x3);
}
break;
case 0x69:
INST_NAME("IMUL Gd, Ed, Id");
@@ -1001,25 +1005,16 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFI(gb1, x1, gb2*8, 8);
BFI(eb1, x12, eb2*8, 8);
} else {
if(0/*arm_swap*/) {
// use atomic swap...
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
GETGB(x12);
SWPB(x12, x12, ed);
BFI(gb1, x12, gb2*8, 8);
} else {
// Lock
LOCK;
// do the swap
GETGB(x12);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0);
LDRB_IMM9(x1, ed, fixedaddress); // 1 gets eb
// do the swap 12 -> strb(ed), 1 -> gd
BFI(gb1, x1, gb2*8, 8);
STRB_IMM9(x12, ed, fixedaddress);
// Unlock
UNLOCK;
}
GETGB(x12);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
MARKLOCK;
// do the swap with exclusive locking
LDREXB(x1, ed);
// do the swap 12 -> strb(ed), 1 -> gd
STREXB(x3, x12, ed);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
BFI(gb1, x1, gb2*8, 8);
}
break;
case 0x87:
@@ -1034,24 +1029,21 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
XOR_REG_LSL_IMM5(gd, gd, ed, 0);
}
} else {
if(0/*arm_swap*/) { // swap doesn't seem to really work like that, plus there seems to be alignement need on arm7
GETGD;
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
// use atomic swap
SWP(gd, gd, ed);
} else {
LOCK;
GETGD;
GETED;
// xor swap to avoid one more tmp reg
if(gd!=ed) {
XOR_REG_LSL_IMM5(gd, gd, ed, 0);
XOR_REG_LSL_IMM5(ed, gd, ed, 0);
XOR_REG_LSL_IMM5(gd, gd, ed, 0);
}
WBACK;
UNLOCK;
}
GETGD;
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
TSTS_IMM8(ed, 3);
B_MARK(cNE);
MARKLOCK;
LDREX(x1, ed);
STREX(x3, gd, ed);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
B_MARK2(c__);
MARK;
LDR_IMM9(x1, ed, 0);
STR_IMM9(gd, ed, 0);
MARK2;
MOV_REG(gd, x1);
}
break;
case 0x88:
@@ -1124,7 +1116,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x8C:
INST_NAME("MOV Ed, Seg");
nextop=F8;
MOV32(x3, offsetof(x86emu_t, segs[(nextop&38)>>3]));
MOV32(x3, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
if((nextop&0xC0)==0xC0) { // reg <= seg
LDRH_REG(xEAX+(nextop&7), xEmu, x3);
} else { // mem <= seg
@@ -1140,7 +1132,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= reg? that's an invalid operation
DEFAULT;
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
if(gd!=ed) { // it's sometimes used as a 3 bytes NOP
MOV_REG(gd, ed);
}
@@ -1156,15 +1148,15 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDRH_IMM8(x1, ed, fixedaddress);
ed = x1;
}
MOV32(x2, offsetof(x86emu_t, segs[(nextop&38)>>3]));
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
STRH_REG(ed, xEmu, x2);
if(((nextop&38)>>3)==_FS) {
if(((nextop&0x38)>>3)==_FS) {
// update default_fs, hack for wine
MOV32(x2, &default_fs);
STRH_IMM8(ed, x2, 0);
}
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[(nextop&38)>>3]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_serial[(nextop&0x38)>>3]));
break;
case 0x8F:
INST_NAME("POP Ed");
@@ -1556,7 +1548,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC2:
INST_NAME("RETN");
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
//SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
READFLAGS(X_PEND); // lets play safe here too
BARRIER(2);
i32 = F16;
retn_to_epilog(dyn, ninst, i32);
@@ -1565,7 +1558,9 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xC3:
INST_NAME("RET");
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
// SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
// ^^^ that hack break PlantsVsZombies and GOG Setup under wine....
READFLAGS(X_PEND); // so instead, force the defered flags, so it's not too slow, and flags are not lost
BARRIER(2);
ret_to_epilog(dyn, ninst);
*need_epilog = 0;
@@ -1628,6 +1623,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
*need_epilog = 1;
} else {
MESSAGE(LOG_DUMP, "Native Call to %s\n", GetNativeName(GetNativeFnc(ip)));
x87_forget(dyn, ninst, x3, x12, 0);
MOV32(x12, ip+1); // read the 0xCC
addr+=4+4;
STM(xEmu, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11)|(1<<12));
@@ -1674,7 +1670,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xCF:
INST_NAME("IRET");
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
SETFLAGS(X_ALL, SF_SET); // Not a hack, EFLAGS are restored
BARRIER(2);
iret_to_epilog(dyn, ninst);
*need_epilog = 0;
@@ -1942,7 +1938,39 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
}
break;
case 0xD4:
INST_NAME("AAM Ib");
SETFLAGS(X_ALL, SF_SET);
UBFX(x1, xEAX, 0, 8); // load AL
u8 = F8;
MOVW(x2, u8);
CALL_(aam16, x1, 0);
BFI(xEAX, x1, 0, 16);
break;
case 0xD5:
INST_NAME("AAD Ib");
SETFLAGS(X_ALL, SF_SET);
UBFX(x1, xEAX, 0, 16); // load AX
u8 = F8;
MOVW(x2, u8);
CALL_(aad16, x1, 0);
BFI(xEAX, x1, 0, 16);
break;
case 0xD6:
INST_NAME("SALC");
READFLAGS(X_CF);
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, flags[F_CF])); // load CC
CMPS_IMM8(x3, 1);
MOVW_COND(cEQ, x3, 0xff);
MOVW_COND(cNE, x3, 0x00);
BFI(xEAX, x3, 0, 8);
break;
case 0xD7:
INST_NAME("XLAT");
UBFX(x1, xEAX, 0, 8); // x1 = AL
LDRB_REG_LSL_IMM5(x1, xEBX, x1, 0); //x1 = byte ptr[EBX+AL]
BFI(xEAX, x1, 0, 8);
break;
case 0xD8:
addr = dynarecD8(dyn, addr, ip, ninst, ok, need_epilog);
break;
@@ -2018,64 +2046,102 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xE8:
INST_NAME("CALL Id");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
i32 = F32S;
if(addr+i32==0) {
#if STEP == 3
printf_log(LOG_NONE, "Warning, jump to 0x0 at %p (%p)\n", (void*)addr, (void*)(addr-1));
printf_log(LOG_NONE, "Warning, CALL to 0x0 at %p (%p)\n", (void*)addr, (void*)(addr-1));
#endif
}
if(isNativeCall(dyn, addr+i32, &natcall, &retn)) {
BARRIER(1);
BARRIER_NEXT(1);
MOV32(x2, addr);
PUSH(xESP, 1<<x2);
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(natcall-1)), retn);
// calling a native function
MOV32(x12, natcall); // read the 0xCC
STM(xEmu, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11)|(1<<12));
CALL_(x86Int3, -1, 0);
LDM(xEmu, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11)|(1<<12));
MOV32(x3, natcall+2+4+4);
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
B_MARK(cNE); // Not the expected address, exit dynarec block
POP(xESP, (1<<xEIP)); // pop the return address
if(retn) {
ADD_IMM8(xESP, xESP, retn);
}
MOV32(x3, addr);
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
B_MARK(cNE); // Not the expected address again
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, quit));
CMPS_IMM8(x1, 1);
B_NEXT(cNE); // not quitting, so lets continue
MARK;
jump_to_epilog(dyn, 0, xEIP, ninst);
} else if ((i32==0) && ((PK(0)>=0x58) && (PK(0)<=0x5F))) {
MESSAGE(LOG_DUMP, "Hack for Call 0, Pop reg\n");
u8 = F8;
gd = xEAX+(u8&7);
MOV32(gd, addr-1);
} else if (((addr+i32)>0x10000) && (PK(i32+0)==0x8B) && (((PK(i32+1))&0xC7)==0x04) && (PK(i32+2)==0x24) && (PK(i32+3)==0xC3)) {
MESSAGE(LOG_DUMP, "Hack for Call x86.get_pc_thunk.reg\n");
u8 = PK(i32+1);
gd = xEAX+((u8&0x38)>>3);
MOV32(gd, addr);
} else {
// regular call
BARRIER(1);
BARRIER_NEXT(1);
if(!dyn->nolinker && (!dyn->insts || ninst!=dyn->size-1)) {
PASS2(cstack_push(dyn, ninst, addr, dyn->insts[ninst+1].address, x1, x2);)
//cstatck_push put addr in x2, don't need to put it again
} else {
PASS2(cstack_push(dyn, ninst, 0, 0, x1, x2);)
*need_epilog = 0;
*ok = 0;
#if STEP == 0
if ((i32==0) && ((PK(0)>=0x58) && (PK(0)<=0x5F)))
tmp = 1;
else if (((addr+i32)>0x10000) && (PK(i32+0)==0x8B) && (((PK(i32+1))&0xC7)==0x04) && (PK(i32+2)==0x24) && (PK(i32+3)==0xC3))
tmp = 2;
else if(isNativeCall(dyn, addr+i32, NULL, NULL))
tmp = 3;
else
tmp = 0;
#elif STEP < 2
if ((i32==0) && ((PK(0)>=0x58) && (PK(0)<=0x5F)))
tmp = dyn->insts[ninst].pass2choice = 1;
else if (((addr+i32)>0x10000) && (PK(i32+0)==0x8B) && (((PK(i32+1))&0xC7)==0x04) && (PK(i32+2)==0x24) && (PK(i32+3)==0xC3))
tmp = dyn->insts[ninst].pass2choice = 2;
else if(isNativeCall(dyn, addr+i32, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
tmp = dyn->insts[ninst].pass2choice = 3;
else
tmp = dyn->insts[ninst].pass2choice = 0;
#else
tmp = dyn->insts[ninst].pass2choice;
#endif
switch(tmp) {
case 1:
//SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
MESSAGE(LOG_DUMP, "Hack for Call 0, Pop reg\n");
u8 = F8;
gd = xEAX+(u8&7);
MOV32(gd, addr-1);
break;
case 2:
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
MESSAGE(LOG_DUMP, "Hack for Call x86.get_pc_thunk.reg\n");
u8 = PK(i32+1);
gd = xEAX+((u8&0x38)>>3);
MOV32(gd, addr);
break;
case 3:
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
BARRIER(1);
BARRIER_NEXT(1);
MOV32(x2, addr);
}
PUSH(xESP, 1<<x2);
jump_to_linker(dyn, addr+i32, 0, ninst);
PUSH(xESP, 1<<x2);
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
// calling a native function
x87_forget(dyn, ninst, x3, x12, 0);
MOV32(x12, dyn->insts[ninst].natcall); // read the 0xCC already
STM(xEmu, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11)|(1<<12));
CALL_(x86Int3, -1, 0);
LDM(xEmu, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11)|(1<<12));
MOV32(x3, dyn->insts[ninst].natcall+2+4+4);
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
B_MARK(cNE); // Not the expected address, exit dynarec block
POP(xESP, (1<<xEIP)); // pop the return address
if(dyn->insts[ninst].retn) {
ADD_IMM8(xESP, xESP, dyn->insts[ninst].retn);
}
MOV32(x3, addr);
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
B_MARK(cNE); // Not the expected address again
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, quit));
CMPS_IMM8(x1, 1);
B_NEXT(cNE); // not quitting, so lets continue
MARK;
jump_to_epilog(dyn, 0, xEIP, ninst);
break;
default:
if(ninst && dyn->insts && dyn->insts[ninst-1].x86.set_flags) {
READFLAGS(X_PEND); // that's suspicious
} else {
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
}
// regular call
BARRIER(1);
BARRIER_NEXT(1);
if(!dyn->nolinker && (!dyn->insts || ninst!=dyn->size-1)) {
PASS2(cstack_push(dyn, ninst, addr, dyn->insts[ninst+1].address, x1, x2);)
//cstatck_push put addr in x2, don't need to put it again
} else {
PASS2(cstack_push(dyn, ninst, 0, 0, x1, x2);)
*need_epilog = 0;
*ok = 0;
MOV32(x2, addr);
}
PUSH(xESP, 1<<x2);
if(addr+i32==0) { // self modifying code maybe? so use indirect address fetching
MOV32(x12, addr-4);
LDR_IMM9(x12, x12, 0);
}
jump_to_linker(dyn, addr+i32, (addr+i32)?0:x12, ninst);
break;
}
break;
case 0xE9:
@@ -2090,7 +2156,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
JUMP(addr+i32);
if(dyn->insts) {
if(dyn->insts[ninst].x86.jmp_insts==-1) {
PASS2IF(dyn->insts[ninst].x86.jmp_insts==-1, 1) {
// out of the block
jump_to_linker(dyn, addr+i32, 0, ninst);
} else {
@@ -2196,8 +2262,10 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x7D:
case 0x7E:
case 0x7F:
case 0x9C:
case 0xE8:
case 0xE9:
case 0xEB:
if(opcode==0xF2) {INST_NAME("BND");} else {INST_NAME("F3");}
--addr; // put back opcode
break;
@@ -2594,7 +2662,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2: // CALL Ed
INST_NAME("CALL Ed");
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
PASS2IF(ninst && dyn->insts && dyn->insts[ninst-1].x86.set_flags, 1) {
READFLAGS(X_PEND); // that's suspicious
} else {
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
}
GETEDH(xEIP);
BARRIER(1);
BARRIER_NEXT(1);
+238 -80
View File
@@ -19,6 +19,7 @@
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "my_cpuid.h"
#include "emu/x87emu_private.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
@@ -54,7 +55,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
{
uint8_t opcode = F8;
uint8_t nextop, u8;
int32_t i32, i32_;
int32_t i32, i32_, j32;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2;
@@ -73,11 +74,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MAYUSE(eb2);
MAYUSE(eb1);
MAYUSE(wb2);
#if PASS == 3
MAYUSE(j32);
#if STEP == 3
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
#endif
switch(opcode) {
case 0x0B:
INST_NAME("UD2");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
@@ -87,11 +90,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOVUPS Gx,Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0);
//LDRD also have alignment requirements
LDR_IMM9(x2, ed, fixedaddress+0);
@@ -145,10 +149,17 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
VMOVD(v1, v0);
} else {
VMOVfrV_D(x2, x3, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
VST1_32(v0, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
} else {
VMOVfrV_D(x2, x3, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
}
break;
case 0x14:
@@ -184,9 +195,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
INST_NAME("MOVHPS Gx,Ex");
GETGX(v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 255, 0);
LDRD_IMM8(x2, ed, fixedaddress);
VMOVtoV_D(v0+1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
VLD1_64(v0+1, ed);
}
break;
case 0x17:
@@ -197,9 +207,17 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
VMOVD(v1, v0+1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 255, 0);
VMOVfrV_D(x2, x3, v0+1);
STRD_IMM8(x2, ed, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
VST1_32(v0+1, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
} else {
VMOVfrV_D(x2, x3, v0+1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
}
break;
case 0x18:
@@ -237,11 +255,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOVAPS Gx,Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
VLD1Q_32(v0, ed);
}
@@ -350,7 +369,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
parity = getedparity(dyn, ninst, addr, nextop, 2);
s0 = fpu_get_scratch_single(dyn);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
@@ -377,16 +396,36 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
//SSE3
nextop=F8;
switch(nextop) {
case 0x00:
INST_NAME("PSHUFB Gm, Em");
nextop = F8;
GETGM(d0);
GETEM(d1);
v1 = fpu_get_scratch_double(dyn);
VMOV_8(v1, 0b10000111);
VANDD(v1, d1, v1); // mask the index
VTBL1_8(d0, d0, v1);
break;
case 0x04:
INST_NAME("PMADDUBSW Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1);
v0 = fpu_get_scratch_quad(dyn);
VMULL_U16_U8(v0, d0, d1);
VPADDLQ_U16(v0, v0);
v1 = fpu_get_scratch_quad(dyn);
VMOVL_U8(v0, d0); // this is unsigned, so 0 extended
VMOVL_S8(v1, d1); // this is signed
VMULQ_16(v0, v0, v1);
VPADDLQ_S16(v0, v0);
VQMOVN_S32(d0, v0);
break;
case 0x0B:
INST_NAME("PMULHRSW Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1);
VQRDMULH_S16(d0, d0, d1);
break;
default:
DEFAULT;
}
@@ -556,10 +595,23 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
v2 = fpu_get_scratch_quad(dyn);
#if 0
VRSQRTEQ_F32(v2, q0);
//step?
VRECPEQ_F32(v0, v2);
//step?
#else
// more precise
if(v0==q0)
v1 = fpu_get_scratch_quad(dyn);
else
v1 = v0;
VRSQRTEQ_F32(v2, q0);
VMULQ_F32(v1, v2, q0);
VRSQRTSQ_F32(v1, v1, v2);
VMULQ_F32(v1, v1, v2);
VMULQ_F32(v0, v1, q0);
#endif
break;
case 0x52:
INST_NAME("RSQRTPS Gx, Ex");
@@ -567,8 +619,21 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEX(q0);
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
#if 0
VRSQRTEQ_F32(v0, q0);
//step?
#else
v2 = fpu_get_scratch_quad(dyn);
// more precise
if(v0==q0)
v1 = fpu_get_scratch_quad(dyn);
else
v1 = v0;
VRSQRTEQ_F32(v2, q0);
VMULQ_F32(v1, v2, q0);
VRSQRTSQ_F32(v1, v1, v2);
VMULQ_F32(v0, v1, v2);
#endif
break;
case 0x53:
INST_NAME("RCPPS Gx, Ex");
@@ -824,11 +889,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOVQ Gm, Em");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
v1 = mmx_get_reg(dyn, ninst, x1, nextop&7);
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
VMOVD(v0, v1);
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
VLD1_64(v0, ed);
}
@@ -1015,7 +1081,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
DEFAULT;
}
break;
case 0x74:
INST_NAME("PCMPEQB Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1);
VCEQ_8(d0, d0, d1);
break;
case 0x75:
INST_NAME("PCMPEQW Gm,Em");
nextop = F8;
@@ -1333,7 +1405,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
POP(xESP, 1<<x2);
STRH_REG(x2, xEmu, x1);
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[_FS]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_serial[_FS]));
break;
case 0xA2:
INST_NAME("CPUID");
@@ -1396,7 +1468,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
POP(xESP, 1<<x2);
STRH_REG(x2, xEmu, x1);
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[_GS]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_serial[_GS]));
break;
case 0xAB:
@@ -1466,7 +1538,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);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fxsave, -1, 0);
CALL(fpu_fxsave, -1, 0);
}
break;
case 1:
@@ -1477,7 +1549,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);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fxrstor, -1, 0);
CALL(fpu_fxrstor, -1, 0);
}
break;
case 2:
@@ -1521,26 +1593,14 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("CMPXCHG Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df)); // d_none == 0
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_AF]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_PF]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_SF]));
GETEB(x2)
UXTB(x1, xEAX, 0);
// Use a quick CMP, without setting A or P...
CMPS_REG_LSL_IMM5(x1, ed, 0);
MOVW_COND(cEQ, x1, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
B_MARK(cNE);
// AL == Eb
GETGB(x1);
MOV_REG(ed, x1);
EBBACK;
MOVW(x1, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
// done
B_MARK3(c__);
MARK;
// AL != Eb
@@ -1548,36 +1608,27 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
MARK3;
// done, do the cmp now
emit_cmp8(dyn, ninst, x1, x2, x3, x12);
break;
case 0xB1:
INST_NAME("CMPXCHG Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df)); // d_none == 0
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_AF]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_PF]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_SF]));
GETED;
GETGD;
// Use a quick CMP, without setting A or P...
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
MOVW_COND(cEQ, x1, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
B_MARK(cNE);
// EAX == Ed
MOV_REG(x3, ed);
MOV_REG(ed, gd);
WBACK;
MOVW(x1, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
// done
emit_cmp32(dyn, ninst, xEAX, x3, x1, x12);
B_MARK3(c__); // not next, in case its called with a LOCK prefix
MARK;
// EAX != Ed
emit_cmp32(dyn, ninst, xEAX, ed, x3, x12);
MOV_REG(xEAX, ed);
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
MARK3
break;
case 0xB3:
@@ -1641,29 +1692,60 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 4:
INST_NAME("BT Ed, Ib");
SETFLAGS(X_CF, SF_SET);
SETFLAGS(X_CF, SF_SUBSET);
gd = x2;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
u8 = F8;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095-32, 0);
u8 = F8;
fixedaddress+=(u8>>5)*4;
LDR_IMM9(x1, ed, fixedaddress);
ed = x1;
}
u8&=0x1f;
if(u8) {
MOV_REG_LSR_IMM5(x1, ed, u8);
ed = x1;
}
AND_IMM8(x1, ed, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
break;
case 5:
INST_NAME("BTS Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
gd = x2;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
u8 = F8;
MOVW(gd, u8);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095, 0);
u8 = F8;
MOVW(gd, u8);
UBFX(x1, gd, 5, 3); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x1, ed, x1, 2); //(&ed)+=r1*4;
LDR_IMM9(x1, x1, fixedaddress);
ADD_REG_LSL_IMM5(x3, ed, x1, 2); //(&ed)+=r1*4;
LDR_IMM9(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x1, ed, x2);
AND_IMM8(x1, x1, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
MOV_REG_LSR_REG(x12, ed, x2);
ANDS_IMM8(x12, x12, 1);
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
B_MARK3(cNE); // bit already set, jump to next instruction
MOVW(x12, 1);
XOR_REG_LSL_REG(ed, ed, x12, x2);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
}
MARK3;
break;
case 6:
INST_NAME("BTR Ed, Ib");
SETFLAGS(X_CF, SF_SET);
SETFLAGS(X_CF, SF_SUBSET);
gd = x2;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
@@ -1692,6 +1774,36 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
MARK3;
break;
case 7:
INST_NAME("BTC Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
gd = x2;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
u8 = F8;
MOVW(gd, u8);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095, 0);
u8 = F8;
MOVW(gd, u8);
UBFX(x1, gd, 5, 3); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, ed, x1, 2); //(&ed)+=r1*4;
LDR_IMM9(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x12, ed, x2);
ANDS_IMM8(x12, x12, 1);
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
MOVW_COND(cEQ, x12, 1); // may already 0x01
XOR_REG_LSL_REG(ed, ed, x12, x2);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
}
MARK3;
break;
default:
DEFAULT;
}
@@ -1834,7 +1946,18 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break; // not NaN
}
break;
case 0xC3:
INST_NAME("MOVNTI Ed, Gd");
// ignoring "NTI"
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd); // doesn't exist
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0);
STR_IMM9(gd, ed, fixedaddress);
}
break;
case 0xC4:
INST_NAME("PINSRW Gm,Ed,Ib");
nextop = F8;
@@ -1997,25 +2120,29 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xD7:
INST_NAME("PMOVMSKB Gd, Em");
nextop = F8;
GETEM(d0);
gd = xEAX+((nextop&0x38)>>3);
#if PASS == 3
MOV32_(x1, &mask_shift8);
#else
MOV32_(x1, 0);
#endif
d1 = fpu_get_scratch_double(dyn);
VLD1_8(d1, x1); // load shift
v2 = fpu_get_scratch_double(dyn);
VMOV_8(v2, 0x80); // load mask
VANDD(v2, v2, d0); // keep highest bit
VSHL_S8(v2, v2, d1);// shift
VPADD_8(v2, v2, v2);// accumulate the bits
VPADD_8(v2, v2, v2);// ...
VPADD_8(v2, v2, v2);// ...
VMOVfrDx_U8(gd, v2, 0);
if((nextop&0xC0)==0xC0) {
INST_NAME("PMOVMSKB Gd, Em");
GETEM(d0);
gd = xEAX+((nextop&0x38)>>3);
#if STEP == 3
MOV32_(x1, &mask_shift8);
#else
MOV32_(x1, 0);
#endif
d1 = fpu_get_scratch_double(dyn);
VLD1_8(d1, x1); // load shift
v2 = fpu_get_scratch_double(dyn);
VMOV_8(v2, 0x80); // load mask
VANDD(v2, v2, d0); // keep highest bit
VSHL_U8(v2, v2, d1);// shift
VPADD_8(v2, v2, v2);// accumulate the bits
VPADD_8(v2, v2, v2);// ...
VPADD_8(v2, v2, v2);// ...
VMOVfrDx_U8(gd, v2, 0);
} else {
DEFAULT;
}
break;
case 0xD8:
INST_NAME("PSUBUSB Gm,Em");
@@ -2031,7 +2158,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEM(d1);
VQSUB_U16(d0, d0, d1);
break;
case 0xDA:
INST_NAME("PMINUB Gm, Em");
nextop = F8;
GETGM(d0);
GETEM(d1);
VMIN_U8(d0, d0, d1);
break;
case 0xDB:
INST_NAME("PAND Gm, Em");
nextop = F8;
@@ -2053,7 +2186,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEM(d1);
VQADD_U16(d0, d0, d1);
break;
case 0xDE:
INST_NAME("PMAXUB Gm, Em");
nextop = F8;
GETGM(d0);
GETEM(d1);
VMAX_U8(d0, d0, d1);
break;
case 0xDF:
INST_NAME("PANDN Gm, Em");
nextop = F8;
@@ -2061,6 +2200,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEM(v1);
VBICD(v0, v1, v0);
break;
case 0xE0:
INST_NAME("PAVGB Gm, Em");
nextop = F8;
GETGM(v0);
GETEM(v1);
VRHADD_U8(v0, v0, v1);
break;
case 0xE4:
INST_NAME("PMULHUW Gm,Em");
@@ -2090,7 +2236,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
DEFAULT;
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
v0 = mmx_get_reg(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
VST1_64(v0, ed);
}
@@ -2109,7 +2255,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEM(d1);
VQSUB_S16(d0, d0, d1);
break;
case 0xEA:
INST_NAME("PMINPS Gm, Em");
nextop = F8;
GETGM(d0);
GETEM(d1);
VMIN_S16(d0, d0, d1);
break;
case 0xEB:
INST_NAME("POR Gm, Em");
nextop = F8;
@@ -2131,7 +2283,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEM(d1);
VQADD_S16(d0, d0, d1);
break;
case 0xEE:
INST_NAME("PMAXSW Gm, Em");
nextop = F8;
GETGM(d0);
GETEM(d1);
VMAX_S16(d0, d0, d1);
break;
case 0xEF:
INST_NAME("PXOR Gm, Em");
nextop = F8;
+179 -9
View File
@@ -25,12 +25,36 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
{
uint8_t opcode = F8;
uint8_t nextop;
int32_t i32;
int32_t i32, j32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback;
int fixedaddress;
MAYUSE(j32);
switch(opcode) {
case 0x03:
INST_NAME("ADD Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_fsdata(dyn, addr, ninst, x12);
nextop = F8;
GETGD;
GETEDO(x12);
emit_add32(dyn, ninst, gd, ed, x3, x12);
break;
case 0x2B:
INST_NAME("SUB Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_fsdata(dyn, addr, ninst, x12);
nextop = F8;
GETGD;
GETEDO(x12);
emit_sub32(dyn, ninst, gd, ed, x3, x12);
break;
case 0x33:
INST_NAME("XOR Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
@@ -51,6 +75,97 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_cmp32(dyn, ninst, gd, ed, x3, x12);
break;
case 0x67:
// reduced EA size...
opcode = F8;
switch(opcode) {
case 0x89:
INST_NAME("MOV FS:Ew16, Gw");
nextop = F8;
grab_fsdata(dyn, addr, ninst, x12);
GETGD; // don't need GETGW here
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(ed, gd, 0, 16);
}
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
STRH_REG(gd, x12, ed);
}
break;
case 0x8B:
INST_NAME("MOV Gd, FS:Ew16");
nextop=F8;
grab_fsdata(dyn, addr, ninst, x12);
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(gd, ed, x12, 0);
}
break;
case 0x8F:
INST_NAME("POP FS:Ew16");
nextop=F8;
grab_fsdata(dyn, addr, ninst, x12);
if((nextop&0xC0)==0xC0) {
POP(xESP, (1<<(xEAX+(nextop&7)))); // 67 ignored
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
POP(xESP, (1<<x2));
STR_REG_LSL_IMM5(x2, x1, x12, 0);
}
break;
case 0xA1:
INST_NAME("MOV EAX, FS:Ow");
grab_fsdata(dyn, addr, ninst, x1);
u32 = F16;
if(u32) {
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
LDR_IMM9(xEAX, x1, 0);
break;
case 0xA3:
INST_NAME("MOV FS:Ow, EAX");
grab_fsdata(dyn, addr, ninst, x1);
u32 = F16;
if(u32) {
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
STR_IMM9(xEAX, x1, 0);
break;
case 0xFF:
nextop = F8;
grab_fsdata(dyn, addr, ninst, x12);
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH FS:Ew");
if((nextop&0xC0)==0xC0) { // reg
DEFAULT;
} else { // mem <= i32
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x12, 0);
PUSH(xESP, 1<<x3);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
break;
case 0x89:
INST_NAME("MOV FS:Ed, Gd");
grab_fsdata(dyn, addr, ninst, x12);
@@ -90,6 +205,17 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
case 0xA0:
INST_NAME("MOV AL, FS:Id");
grab_fsdata(dyn, addr, ninst, x1);
i32 = F32S;
if(i32>-4096 && i32<4096) {
LDRB_IMM9(xEAX, x1, i32);
} else {
MOV32(x2, i32);
LDRB_REG_LSL_IMM5(xEAX, x1, x2, 0);
}
break;
case 0xA1:
INST_NAME("MOV EAX, FS:Id");
grab_fsdata(dyn, addr, ninst, x1);
@@ -98,18 +224,30 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDR_IMM9(xEAX, x1, i32);
} else {
MOV32(x2, i32);
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
LDR_IMM9(xEAX, x1, 0);
LDR_REG_LSL_IMM5(xEAX, x1, x2, 0);
}
break;
case 0xA2:
INST_NAME("MOV FS:Od, AL");
grab_fsdata(dyn, addr, ninst, x1);
i32 = F32S;
if(i32>-4096 && i32<4096) {
STRB_IMM9(xEAX, x1, i32);
} else {
MOV32(x2, i32);
STRB_REG_LSL_IMM5(xEAX, x1, x2, 0);
}
break;
case 0xA3:
INST_NAME("MOV FS:Od, EAX");
grab_fsdata(dyn, addr, ninst, x1);
u32 = F32;
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x2, x1, x2, 0);
STR_IMM9(xEAX, x2, 0);
i32 = F32S;
if(i32>-4096 && i32<4096) {
STR_IMM9(xEAX, x1, i32);
} else {
MOV32(x2, i32);
STR_REG_LSL_IMM5(xEAX, x2, x1, 0);
}
break;
case 0xC7:
@@ -128,12 +266,44 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
case 0xE9:
case 0xEB:
INST_NAME("(ignored) FS:");
--addr;
break;
case 0xFF:
nextop = F8;
grab_fsdata(dyn, addr, ninst, x12);
switch((nextop>>3)&7) {
case 2: // CALL Ed
INST_NAME("CALL Ed");
PASS2IF(ninst && dyn->insts && dyn->insts[ninst-1].x86.set_flags, 1) {
READFLAGS(X_PEND); // that's suspicious
} else {
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
}
if((nextop&0xC0)==0xC0) { // reg
MOV_REG(xEIP, xEAX+(nextop&7));
} else { // mem
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(xEIP, ed, x12, 0);
}
BARRIER(1);
BARRIER_NEXT(1);
if(!dyn->nolinker && (!dyn->insts || ninst!=dyn->size-1)) {
PASS2(cstack_push(dyn, ninst, addr, dyn->insts[ninst+1].address, x1, x2);)
} else {
PASS2(cstack_push(dyn, ninst, 0, 0, x1, x2);)
*need_epilog = 0;
*ok = 0;
MOV32(x2, addr);
}
PUSH(xESP, 1<<x2);
jump_to_linker(dyn, 0, xEIP, ninst); // smart linker
break;
case 6: // Push Ed
INST_NAME("PUSH Ed");
INST_NAME("PUSH FS:Ed");
if((nextop&0xC0)==0xC0) { // reg
DEFAULT;
} else { // mem <= i32
+142 -2
View File
@@ -25,12 +25,19 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
{
uint8_t opcode = F8;
uint8_t nextop;
int32_t i32;
int32_t i32, j32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback;
uint8_t wback, wb1, wb2;
uint8_t u8;
int fixedaddress;
MAYUSE(j32);
MAYUSE(wback);
MAYUSE(wb2);
switch(opcode) {
case 0x03:
INST_NAME("ADD Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET);
@@ -61,6 +68,101 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_xor32(dyn, ninst, gd, ed, x3, x12);
break;
case 0x3B:
INST_NAME("CMP Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x12);
nextop = F8;
GETGD;
GETEDO(x12);
emit_cmp32(dyn, ninst, gd, ed, x3, x12);
break;
case 0x80:
case 0x82:
nextop = F8;
switch((nextop>>3)&7) {
case 0: //ADD
INST_NAME("ADD GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
emit_add8c(dyn, ninst, x1, u8, x2, x12);
EBBACK;
break;
case 1: //OR
INST_NAME("OR GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
emit_or8c(dyn, ninst, x1, u8, x2, x12);
EBBACK;
break;
case 2: //ADC
INST_NAME("ADC GS:Eb, Ib");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
emit_adc8c(dyn, ninst, x1, u8, x2, x12);
EBBACK;
break;
case 3: //SBB
INST_NAME("SBB GS:Eb, Ib");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
emit_sbb8c(dyn, ninst, x1, u8, x2, x12);
EBBACK;
break;
case 4: //AND
INST_NAME("AND GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
emit_and8c(dyn, ninst, x1, u8, x2, x12);
EBBACK;
break;
case 5: //SUB
INST_NAME("SUB GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
emit_sub8c(dyn, ninst, x1, u8, x2, x12);
EBBACK;
break;
case 6: //XOR
INST_NAME("XOR GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
emit_xor8c(dyn, ninst, x1, u8, x2, x12);
EBBACK;
break;
case 7: //CMP
INST_NAME("CMP GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
if(u8) {
MOVW(x2, u8);
emit_cmp8(dyn, ninst, x1, x2, x3, x12);
} else {
emit_cmp8_0(dyn, ninst, x1, x3, x12);
}
break;
}
break;
case 0x89:
INST_NAME("MOV GS:Ed, Gd");
grab_tlsdata(dyn, addr, ninst, x12);
@@ -87,6 +189,19 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
case 0x8F:
INST_NAME("POP GS:Ed");
grab_tlsdata(dyn, addr, ninst, x12);
nextop = F8;
if((nextop&0xC0)==0xC0) {
POP(xESP, (1<<(xEAX+(nextop&7))));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
POP(xESP, (1<<x2));
STR_REG_LSL_IMM5(x2, ed, x12, 0);
}
break;
case 0xA1:
INST_NAME("MOV EAX, GS:Id");
grab_tlsdata(dyn, addr, ninst, x1);
@@ -125,6 +240,31 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
case 0xE9:
case 0xEB:
INST_NAME("(ignored) GS:");
--addr;
break;
case 0xFF:
nextop = F8;
grab_tlsdata(dyn, addr, ninst, x12);
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH GS:Ed");
if((nextop&0xC0)==0xC0) { // reg
DEFAULT;
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x12, 0);
PUSH(xESP, 1<<x3);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
+89 -18
View File
@@ -20,6 +20,7 @@
#include "arm_printer.h"
#include "dynarec_arm_helper.h"
#include "dynarec_arm_functions.h"
uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
@@ -27,7 +28,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
uint8_t opcode = F8;
uint8_t nextop, u8;
uint32_t u32;
int32_t i32;
int32_t i32, j32;
int16_t i16;
uint16_t u16;
uint8_t gd, ed;
@@ -35,6 +36,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int fixedaddress;
MAYUSE(u16);
MAYUSE(u8);
MAYUSE(j32);
while(opcode==0x66) opcode = F8; // "unlimited" 0x66 as prefix for variable sized NOP
if(opcode==0x2E) opcode = F8; // cs: is ignored
switch(opcode) {
@@ -81,7 +83,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STRH_IMM8(x2, x1, 0);
ADD_IMM8(xESP, xESP, 2);
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[_ES]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_serial[_ES]));
break;
case 0x09:
@@ -168,10 +170,9 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("SBB AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
i32 = F16;
MOV32(x2, i32);
i16 = F16;
UXTH(x1, xEAX, 0);
emit_sbb16c(dyn, ninst, x1, i32, x3, x12);
emit_sbb16c(dyn, ninst, x1, i16, x3, x12);
BFI(xEAX, x1, 0, 16);
break;
@@ -324,8 +325,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x56:
case 0x57:
INST_NAME("PUSH Reg16");
SUB_IMM8(xESP, xESP, 2);
STRH_IMM8(xEAX+(opcode&7), xESP, 0); //TODO: use a single STRH pre-decrement instruction
PUSH16(xEAX+(opcode&7), xESP);
break;
case 0x58:
case 0x59:
@@ -336,17 +336,45 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x5E:
case 0x5F:
INST_NAME("POP Reg16");
LDRH_IMM8(x1, xESP, 0); //TODO: use a single LDRH post-increment instruction
POP16(x1, xESP);
BFI(xEAX+(opcode&7), x1, 0, 16);
ADD_IMM8(xESP, xESP, 2);
break;
case 0x60:
INST_NAME("PUSHA");
MOV_REG(x1, xESP);
PUSH16(xEAX, xESP);
PUSH16(xECX, xESP);
PUSH16(xEDX, xESP);
PUSH16(xEBX, xESP);
PUSH16(x1, xESP);
PUSH16(xEBP, xESP);
PUSH16(xESI, xESP);
PUSH16(xEDI, xESP);
break;
case 0x61:
INST_NAME("POPA");
POP16(x1, xESP);
BFI(xEDI, x1, 0, 16);
POP16(x1, xESP);
BFI(xESI, x1, 0, 16);
POP16(x1, xESP);
BFI(xEBP, x1, 0, 16);
ADD_IMM8(xESP, xESP, 2); //POP16(xESP, xESP);
POP16(x1, xESP);
BFI(xEBX, x1, 0, 16);
POP16(x1, xESP);
BFI(xEDX, x1, 0, 16);
POP16(x1, xESP);
BFI(xECX, x1, 0, 16);
POP16(x1, xESP);
BFI(xEAX, x1, 0, 16);
break;
case 0x68:
INST_NAME("PUSH Iw");
u16 = F16;
MOVW(x2, u16);
SUB_IMM8(xESP, xESP, 2);
STRH_IMM8(x2, xESP, 0);
PUSH16(x2, xESP);
break;
case 0x69:
INST_NAME("IMUL Gw,Ew,Iw");
@@ -364,8 +392,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("PUSH Ib");
i16 = F8S;
MOVW(x2, i16);
SUB_IMM8(xESP, xESP, 2);
STRH_IMM8(x2, xESP, 0);
PUSH16(x2, xESP);
break;
case 0x6B:
INST_NAME("IMUL Gw,Ew,Ib");
@@ -501,7 +528,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x8C:
INST_NAME("MOV Ew,Seg");
nextop = F8;
MOV32(x2, offsetof(x86emu_t, segs[(nextop&38)>>3]));
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
LDRH_REG(x1, xEmu, x2);
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
@@ -517,16 +544,16 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
MOV32(x2, offsetof(x86emu_t, segs[(nextop&38)>>3]));
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
STRH_REG(ed, xEmu, x2);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0);
LDRH_IMM8(x1, ed, fixedaddress);
MOV32(x2, offsetof(x86emu_t, segs[(nextop&38)>>3]));
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
STRH_REG(x1, xEmu, x2);
}
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[(nextop&38)>>3]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_serial[(nextop&0x38)>>3]));
break;
case 0x90:
@@ -545,12 +572,32 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFI(xEAX, gd, 0, 16);
BFI(gd, x2, 0, 16);
break;
case 0x98:
INST_NAME("CBW");
SXTB(x1, xEAX, 0);
BFI(xEAX, x1, 0, 16);
break;
case 0x99:
INST_NAME("CWD");
SXTH(x1, xEAX, 0);
BFI(xEDX, x1, 16, 16);
break;
case 0x9C:
INST_NAME("PUSHF (16b)");
READFLAGS(X_ALL);
CALL(PackFlags, -1, 0);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, packed_eflags.x32));
STRHB_IMM8(x1, xESP, -2);
break;
case 0x9D:
INST_NAME("POPF (16b)");
SETFLAGS(X_ALL, SF_SET); // lower 16bits is all flags handled in dynarec
LDRHA_IMM8(x1, xESP, 2);
CALL(arm_popf16, -1, 0);
MOVW(x1, d_none);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
break;
case 0xA1:
INST_NAME("MOV, AX, Od");
@@ -974,6 +1021,30 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
}
break;
case 0xF8:
INST_NAME("CLC");
i32 = dyn->state_flags; //TODO: find a better way to do this
SETFLAGS(X_CF, SF_SUBSET);
if(i32!=SF_SET) {
MOVW(x1, d_none);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
} else {
MOVW(x1, 0);
}
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
break;
case 0xF9:
INST_NAME("STC");
i32 = dyn->state_flags; //TODO: find a better way to do this
SETFLAGS(X_CF, SF_SUBSET);
if(i32!=SF_SET) {
MOVW(x1, d_none);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
}
MOVW(x1, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
break;
case 0xFF:
nextop = F8;
switch((nextop>>3)&7) {
+400 -86
View File
@@ -39,7 +39,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
{
uint8_t opcode = F8;
uint8_t nextop, u8;
int32_t i32;
int32_t i32, j32;
uint8_t gd, ed;
uint8_t wback, wb1;
uint8_t eb1, eb2;
@@ -54,6 +54,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
MAYUSE(q1);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(j32);
#if STEP == 3
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
#endif
switch(opcode) {
@@ -61,11 +65,12 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVUPD Gx,Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
@@ -84,7 +89,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 255-8, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 255-16, 0);
VMOVfrV_D(x2, x3, v0);
STR_IMM9(x2, ed, fixedaddress+0);
STR_IMM9(x3, ed, fixedaddress+4);
@@ -114,8 +119,16 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
DEFAULT;
return addr;
}
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VSTR_64(v0, ed, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VSTR_64(v0, ed, fixedaddress);
} else {
VMOVfrV_D(x2, x3, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
break;
case 0x14:
INST_NAME("UNPCKLPD Gx, Ex");
@@ -151,8 +164,16 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
DEFAULT;
return addr;
}
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_64(v0+1, ed, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_64(v0+1, ed, fixedaddress); // vfpu opcode here
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0+1,x2, x3);
}
break;
case 0x17:
INST_NAME("MOVHPD Ed, Gx");
@@ -163,8 +184,16 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
DEFAULT;
return addr;
}
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VSTR_64(v0+1, ed, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VSTR_64(v0+1, ed, fixedaddress);
} else {
VMOVfrV_D(x2, x3, v0+1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
break;
case 0x1F:
@@ -177,11 +206,12 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVAPD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
VLD1Q_32(v0, ed);
}
@@ -223,31 +253,165 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
q1 = fpu_get_scratch_quad(dyn);
if((nextop&0xC0)==0xC0) {
v0 = sse_get_reg(dyn, ninst, x1, nextop&7);
VMOVQ(q1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
VLD1Q_64(q1, ed);
v0 = q1;
}
v1 = fpu_get_scratch_quad(dyn);
VMOVQ_8(v1, 0b10001111);
VANDQ(q1, q1, v1); // mask the index
VANDQ(q1, v0, v1); // mask the index
VMOVQ(v1, q0);
VTBL2_8(q0+0, v1, q1+0);
VTBL2_8(q0+1, v1, q1+1);
break;
case 0x01:
INST_NAME("PHADDW Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
VPADD_16(q0, q0, q0+1);
if(q0==q1) {
VMOVD(q0+1, q0);
} else {
VPADD_16(q0+1, q1, q1+1);
}
break;
case 0x02:
INST_NAME("PHADDD Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
VPADD_32(q0, q0, q0+1);
if(q0==q1) {
VMOVD(q0+1, q0);
} else {
VPADD_32(q0+1, q1, q1+1);
}
break;
case 0x03:
INST_NAME("PHADDSW Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
if((nextop&0xC0) == 0xC0) {
v1 = fpu_get_scratch_quad(dyn);
VMOVQ(v1, q1);
} else
v1 = q1;
VUZPQ_16(q0, v1);
VQADDQ_S16(q0, q0, v1);
break;
case 0x04:
INST_NAME("PMADDUBSW Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
v0 = fpu_get_scratch_quad(dyn);
VMULL_U16_U8(v0, q0+0, q1+0);
VPADDLQ_U16(v0, v0);
v1 = fpu_get_scratch_quad(dyn);
VMOVL_U8(v0, q0+0); // this is unsigned, so 0 extended
VMOVL_S8(v1, q1+0); // this is signed
VMULQ_16(v0, v0, v1);
VPADDLQ_S16(v0, v0);
VQMOVN_S32(q0+0, v0);
VMULL_U16_U8(v0, q0+1, q1+1);
VPADDLQ_U16(v0, v0);
VMOVL_U8(v0, q0+1); // this is unsigned
VMOVL_S8(v1, q1+1); // this is signed
VMULQ_16(v0, v0, v1);
VPADDLQ_S16(v0, v0);
VQMOVN_S32(q0+1, v0);
break;
case 0x05:
INST_NAME("PHSUBW Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
if((nextop&0xC0) == 0xC0) {
v1 = fpu_get_scratch_quad(dyn);
VMOVQ(v1, q1);
} else
v1 = q1;
VUZPQ_16(q0, v1);
VSUBQ_16(q0, q0, v1);
break;
case 0x08:
INST_NAME("PSIGNB Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
v1 = fpu_get_scratch_quad(dyn);
v0 = fpu_get_scratch_quad(dyn);
VNEGNQ_8(v0, q0); // get NEG
VCLTQ_0_8(v1, q1); // calculate mask
VBICQ(q0, q0, v1); // apply not mask on dest
VANDQ(v0, v0, v1); // apply mask on src
VORRQ(q0, q0, v0); // merge
VCEQQ_0_8(v1, q1); // handle case where Ex is 0
VBICQ(q0, q0, v1);
break;
case 0x09:
INST_NAME("PSIGNW Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
v1 = fpu_get_scratch_quad(dyn);
v0 = fpu_get_scratch_quad(dyn);
VNEGNQ_16(v0, q0); // get NEG
VCLTQ_0_16(v1, q1); // calculate mask
VBICQ(q0, q0, v1); // apply not mask on dest
VANDQ(v0, v0, v1); // apply mask on src
VORRQ(q0, q0, v0); // merge
VCEQQ_0_16(v1, q1); // handle case where Ex is 0
VBICQ(q0, q0, v1);
break;
case 0x0A:
INST_NAME("PSIGND Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
v1 = fpu_get_scratch_quad(dyn);
v0 = fpu_get_scratch_quad(dyn);
VNEGNQ_32(v0, q0); // get NEG
VCLTQ_0_32(v1, q1); // calculate mask
VBICQ(q0, q0, v1); // apply not mask on dest
VANDQ(v0, v0, v1); // apply mask on src
VORRQ(q0, q0, v0); // merge
VCEQQ_0_32(v1, q1); // handle case where Ex is 0
VBICQ(q0, q0, v1);
break;
case 0x0B:
INST_NAME("PMULHRSW Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
VQRDMULHQ_S16(q0, q0, q1);
break;
case 0x1C:
INST_NAME("PABSB Gx,Ex");
nextop = F8;
GETEX(q1);
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VABSQ_S8(q0, q1);
break;
case 0x1D:
INST_NAME("PABSW Gx,Ex");
nextop = F8;
GETEX(q1);
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VABSQ_S16(q0, q1);
break;
case 0x1E:
INST_NAME("PABSD Gx,Ex");
nextop = F8;
GETEX(q1);
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VABSQ_S32(q0, q1);
break;
default:
DEFAULT;
}
@@ -265,10 +429,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if(u8>31) {
VEORQ(q0, q0, q0);
} else if(u8>15) {
VEORQ(q0, q0, q0);
VEXTQ_8(q0, q1, q0, u8-16);
d0 = fpu_get_scratch_quad(dyn);
VEORQ(d0, d0, d0);
VEXTQ_8(q0, q0, d0, u8-16);
} else {
VEXTQ_8(q0, q0, q1, u8);
VEXTQ_8(q0, q1, q0, u8);
}
break;
default:
@@ -397,7 +562,20 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
, cNE, cEQ, X_OF|X_SF|X_ZF)
break;
#undef GO
case 0x50:
INST_NAME("MOVMSKPD Gd, Ex");
nextop = F8;
GETEX(q0);
gd = xEAX+((nextop&0x38)>>3);
if((nextop&0xC0)==0xC0)
q1 = fpu_get_scratch_quad(dyn);
else
q1 = q0;
VSHRQ_U64(q1, q0, 63); // only bit 63 left
VSHL_U64(q1+1, q1+1, 1); // shift 1 left for higher bit
VADD_8(q1, q1, q1+1); // add low and high
VMOVfrDx_U8(gd, q1, 0); // grab the 2 sign bits
break;
case 0x54:
INST_NAME("ANDPD Gx, Ex");
nextop = F8;
@@ -460,7 +638,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
GETGX(v0);
GETEX(v1);
VCVTQ_F32_S32(v0, v1);
VCVTQ_S32_F32(v0, v1);
break;
case 0x5C:
INST_NAME("SUBPD Gx, Ex");
@@ -528,11 +706,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
gd = (nextop&0x38)>>3;
GETEX(q0);
v0 = sse_get_reg(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
q1 = fpu_get_scratch_quad(dyn);
VMOVQ(q1, q0);
} else q1 = q0;
VZIPQ_32(v0, q1);
VMOVD(v0+1, q0); // get a copy
VTRN_32(v0, v0+1); // same as VZIP_32
break;
case 0x63:
INST_NAME("PACKSSWB Gx,Ex");
@@ -540,7 +715,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0);
GETEX(q1);
VQMOVN_S16(q0+0, q0);
VQMOVN_S16(q0+1, q1);
if(q0==q1) {
VMOVD(q0+1, q0+0);
} else {
VQMOVN_S16(q0+1, q1);
}
break;
case 0x64:
INST_NAME("PCMPGTB Gx,Ex");
@@ -602,12 +781,9 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
gd = (nextop&0x38)>>3;
GETEX(q0);
v0 = sse_get_reg(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
q1 = fpu_get_scratch_quad(dyn);
VMOVQ(q1, q0);
} else q1 = q0;
VZIPQ_32(v0, q1);
VMOVQ(v0, q1);
VMOVD(v0, v0+1); // get high part into low
VMOVD(v0+1, q0+1); // get a copy
VZIP_32(v0, v0+1);
break;
case 0x6B:
INST_NAME("PACKSSDW Gx,Ex");
@@ -651,12 +827,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVD Gx, Ed");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
d0 = fpu_get_scratch_double(dyn);
VEOR(d0, d0, d0); // d0 = U32{0, 0}
GETED;
VMOVtoV(d0*2, ed);// d0 = U32{ed, 0}
VMOVL_U32(v0, d0);// U32/U32 -> U64/U64
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VEORQ(v0, v0, v0); // v0 = U32{0, 0}
VMOVtoDx_32(v0, 0, ed);// d0 = U32{ed, 0}
break;
case 0x6F:
INST_NAME("MOVDQA Gx,Ex");
@@ -681,26 +855,35 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
u8 = F8;
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
// use stack as temporary storage
SUB_IMM8(xSP, xSP, 4);
if(v1==v0) {
q0 = fpu_get_scratch_quad(dyn);
VMOVQ(q0, v1);
} else q0 = v1;
if (u8) {
for (int i=0; i<4; ++i) {
int32_t idx = (u8>>(i*2))&3;
if(idx!=i32) {
VST1LANE_32(q0+(idx/2), xSP, idx&1);
i32 = idx;
}
VLD1LANE_32(v0+(i/2), xSP, i&1);
if(u8==0x4E) {
if(v0==v1) {
VSWP(v0, v0+1);
} else {
VMOVD(v0, v1+1);
VMOVD(v0+1, v1);
}
} else {
VST1LANE_32(v1, xSP, 0);
VLD1QALL_32(v0, xSP);
uint32_t swp[4] = {
(0)|(1<<8)|(2<<16)|(3<<24),
(4)|(5<<8)|(6<<16)|(7<<24),
(8)|(9<<8)|(10<<16)|(11<<24),
(12)|(13<<8)|(14<<16)|(15<<24)
};
d0 = fpu_get_scratch_double(dyn);
if(v0==v1) {
q1 = fpu_get_scratch_quad(dyn);
VMOVQ(q1, v1);
} else
q1 = v1;
MOV32(x2, swp[(u8>>(0*2))&3]);
MOV32(x3, swp[(u8>>(1*2))&3]);
VMOVtoV_D(d0, x2, x3);
MOV32(x2, swp[(u8>>(2*2))&3]);
MOV32(x3, swp[(u8>>(3*2))&3]);
VTBL2_8(v0+0, q1, d0);
VMOVtoV_D(d0, x2, x3);
VTBL2_8(v0+1, q1, d0);
}
ADD_IMM8(xSP, xSP, 4);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
u8 = F8;
@@ -1110,6 +1293,19 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
BFI(gd, x1, 0, 16);
break;
case 0xB7:
INST_NAME("MOVZX Gw, Ew");
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX + (nextop&7);
UXTH(x1, ed, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0);
LDRH_IMM8(x1, ed, fixedaddress);
}
BFI(gd, x1, 0, 16);
break;
case 0xBB:
INST_NAME("BTC Ew, Gw");
@@ -1175,7 +1371,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
BFI(gd, x1, 0, 16);
break;
case 0xC2:
INST_NAME("CMPPD Gx, Ex");
nextop = F8;
@@ -1249,13 +1445,18 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(v0);
GETEX(v1);
u8 = F8;
q0 = fpu_get_scratch_quad(dyn);
if(v0==v1 && u8==0) {
VMOVD(q0+1, q0);
VMOVD(v0+1, v0);
} else {
if(v0==v1)
q0 = fpu_get_scratch_quad(dyn);
else
q0 = v0;
VMOVD(q0, v0+(u8&1));
VMOVD(q0+1, v1+((u8>>1)&1));
VMOVQ(v0, q0);
if(v0==v1) {
VMOVQ(v0, q0);
}
}
break;
@@ -1287,7 +1488,19 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVD(v0+1, v0);
VSHLQ_U32(q0, q0, v0);
break;
case 0xD3:
INST_NAME("PSRLQ Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
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
VSHLQ_U64(q0, q0, v0);
break;
case 0xD4:
INST_NAME("PADDQ Gx,Ex");
nextop = F8;
@@ -1324,7 +1537,40 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
}
break;
case 0xD7:
nextop = F8;
if((nextop&0xC0)==0xC0) {
INST_NAME("PMOVMSKB Gd, Ex");
GETEX(q0);
gd = xEAX+((nextop&0x38)>>3);
#if STEP == 3
MOV32_(x1, &mask_shift8);
#else
MOV32_(x1, 0);
#endif
v0 = fpu_get_scratch_double(dyn);
VLD1_8(v0, x1); // load shift
v1 = fpu_get_scratch_double(dyn);
VMOV_8(v1, 0x80); // load mask
VANDD(v1, v1, q0+0); // keep highest bit
VSHL_U8(v1, v1, v0);// shift
VPADD_8(v1, v1, v1);// accumulate the bits
VPADD_8(v1, v1, v1);// ...
VPADD_8(v1, v1, v1);// ...
VMOVfrDx_U8(gd, v1, 0);
// and now the high part
VMOV_8(v1, 0x80); // load mask
VANDD(v1, v1, q0+1); // keep highest bit
VSHL_U8(v1, v1, v0);// shift
VPADD_8(v1, v1, v1);// accumulate the bits
VPADD_8(v1, v1, v1);// ...
VPADD_8(v1, v1, v1);// ...
VMOVfrDx_U8(x1, v1, 0);
BFI(gd, x1, 8, 8);
} else {
DEFAULT;
}
break;
case 0xD8:
INST_NAME("PSUBUSB Gx, Ex");
nextop = F8;
@@ -1339,7 +1585,13 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(q1);
VQSUBQ_U16(q0, q0, q1);
break;
case 0xDA:
INST_NAME("PMINUB Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
VMINQ_U8(q0, q0, q1);
break;
case 0xDB:
INST_NAME("PAND Gx,Ex");
nextop = F8;
@@ -1354,7 +1606,13 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(q1);
VQADDQ_U8(q0, q0, q1);
break;
case 0xDD:
INST_NAME("PADDUSW Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
VQADDQ_U16(q0, q0, q1);
break;
case 0xDE:
INST_NAME("PMAXUB Gx, Ex");
nextop = F8;
@@ -1411,7 +1669,17 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(q0);
VRHADDQ_U16(v0, v0, q0);
break;
case 0xE4:
INST_NAME("PMULHUW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(v1);
q0 = fpu_get_scratch_quad(dyn);
VMULL_U32_U16(q0, v0, v1);
VSHRN_32(v0, q0, 16);
VMULL_U32_U16(q0, v0+1, v1+1);
VSHRN_32(v0+1, q0, 16);
break;
case 0xE5:
INST_NAME("PMULHW Gx,Ex");
nextop = F8;
@@ -1419,11 +1687,9 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(v1);
q0 = fpu_get_scratch_quad(dyn);
VMULL_S32_S16(q0, v0, v1);
VUZP_16(q0, q0+1);
VMOVD(v0, q0+1);
VSHRN_32(v0, q0, 16);
VMULL_S32_S16(q0, v0+1, v1+1);
VUZP_16(q0, q0+1);
VMOVD(v0+1, q0+1);
VSHRN_32(v0+1, q0, 16);
break;
case 0xE6:
INST_NAME("CVTTPD2DQ Gx, Ex");
@@ -1451,7 +1717,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
VST1Q_32(v0, ed);
VST1Q_64(v0, ed);
}
break;
case 0xE8:
@@ -1468,7 +1734,13 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(q0);
VQSUBQ_S16(v0, v0, q0);
break;
case 0xEA:
INST_NAME("PMINSW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0);
VMINQ_S16(v0, v0, q0);
break;
case 0xEB:
INST_NAME("POR Gx,Ex");
nextop = F8;
@@ -1490,15 +1762,64 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(q0);
VQADDQ_S16(v0, v0, q0);
break;
case 0xEF:
INST_NAME("PXOR Gx,Ex");
case 0xEE:
INST_NAME("PMAXSW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0);
VEORQ(v0, v0, q0);
VMAXQ_S16(v0, v0, q0);
break;
case 0xEF:
INST_NAME("PXOR Gx,Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if(nextop==0xC0+gd) {
// special case for PXOR Gx, Gx
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VEORQ(q0, q0, q0);
} else {
q0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(q1);
VEORQ(q0, q0, q1);
}
break;
case 0xF1:
INST_NAME("PSLLW Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
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);
VSHLQ_U16(q0, q0, v0);
break;
case 0xF2:
INST_NAME("PSLLD Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
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);
VSHLQ_U32(q0, q0, v0);
break;
case 0xF3:
INST_NAME("PSLLQ Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VSHLQ_U64(q0, q0, v0);
break;
case 0xF4:
INST_NAME("PMULUDQ Gx,Ex");
nextop = F8;
@@ -1521,18 +1842,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
GETGX(v0);
GETEX(v1);
if((nextop&0xC0)==0xC0) {
q1 = fpu_get_scratch_quad(dyn);
VMOVQ(q1, v1);
} else {
q1 = v1;
}
VUZP_16(v0, v0+1);
VUZP_16(q1, q1+1);
VSWP(v0, q1+1);
VMULL_S32_S16(q1, q1, q1+1);
VMULL_S32_S16(v0, v0, v0+1);
VADDQ_32(v0, v0, q1);
q1 = fpu_get_scratch_quad(dyn);
VMULL_S32_S16(q1, v0, v1);
VPADD_32(v0, q1, q1+1);
VMULL_S32_S16(q1, v0+1, v1+1);
VPADD_32(v0+1, q1, q1+1);
break;
case 0xF6:
INST_NAME("PSADBW Gx, Ex");
+103 -3
View File
@@ -21,17 +21,117 @@
#include "dynarec_arm_helper.h"
uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop;
uint8_t nextop, opcode;
int8_t i8;
int32_t i32;
int32_t i32, j32;
uint32_t u32;
uint8_t gd, ed;
int fixedaddress;
MAYUSE(i32);
MAYUSE(j32);
nextop = F8;
switch(nextop) {
case 0x64:
// reduced EA size...
opcode = F8;
switch(opcode) {
case 0x89:
INST_NAME("MOV FS:Ew16, Gw");
nextop = F8;
grab_fsdata(dyn, addr, ninst, x12);
GETGD; // don't need GETGW here
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(ed, gd, 0, 16);
}
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
STRH_REG(gd, x12, ed);
}
break;
case 0x8B:
INST_NAME("MOV Gd, FS:Ew16");
nextop=F8;
grab_fsdata(dyn, addr, ninst, x12);
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(gd, ed, 0, 16);
}
} else { // mem <= reg
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(gd, x12, ed, 0);
}
break;
case 0x8F:
INST_NAME("POP FS:Ew16");
nextop=F8;
grab_fsdata(dyn, addr, ninst, x12);
if((nextop&0xC0)==0xC0) {
POP(xESP, (1<<(xEAX+(nextop&7)))); // 67 ignored
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
POP(xESP, (1<<x2));
STR_REG_LSL_IMM5(x2, x12, ed, 0);
}
break;
case 0xA1:
INST_NAME("MOV EAX, FS:Ow");
grab_fsdata(dyn, addr, ninst, x1);
u32 = F16;
if(u32) {
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
LDR_IMM9(xEAX, x1, 0);
break;
case 0xA3:
INST_NAME("MOV FS:Ow, EAX");
grab_fsdata(dyn, addr, ninst, x1);
u32 = F16;
if(u32) {
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
STR_IMM9(xEAX, x1, 0);
break;
case 0xFF:
nextop = F8;
grab_fsdata(dyn, addr, ninst, x12);
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH FS:Ew");
if((nextop&0xC0)==0xC0) { // reg
DEFAULT;
} else { // mem <= i32
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x12, 0);
PUSH(xESP, 1<<x3);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
break;
#define GO(NO, YES) \
BARRIER(2); \
JUMP(addr+i8);\
+32 -3
View File
@@ -205,6 +205,28 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fxtract, -1, 0);
break;
case 0xF5:
INST_NAME("FPREM1");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fprem1, -1, 0);
break;
case 0xF6:
INST_NAME("FDECSTP");
fpu_purgecache(dyn, ninst, x1, x2, x3);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
SUB_IMM8(x2, x2, 1);
AND_IMM8(x2, x2, 7);
STR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
break;
case 0xF7:
INST_NAME("FINCSTP");
fpu_purgecache(dyn, ninst, x1, x2, x3);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
ADD_IMM8(x2, x2, 1);
AND_IMM8(x2, x2, 7);
STR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
break;
case 0xF8:
INST_NAME("FPREM");
x87_forget(dyn, ninst, x1, x2, 0);
@@ -260,9 +282,6 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xE6:
case 0xE7:
case 0xEF:
case 0xF5:
case 0xF6:
case 0xF7:
DEFAULT;
break;
@@ -331,6 +350,16 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
UBFX(x1, x1, 10, 2); // extract round
STR_IMM9(x1, xEmu, offsetof(x86emu_t, round));
break;
case 6:
INST_NAME("FNSTENV Ed");
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {
MOV_REG(x1, ed);
}
MOVW(x2, 0);
CALL(fpu_savenv, -1, 0);
break;
case 7:
INST_NAME("FNSTCW Ew");
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0);
+2 -2
View File
@@ -26,7 +26,7 @@
uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
int32_t i32;
int32_t j32;
uint8_t ed;
uint8_t wback;
int v1, v2;
@@ -39,7 +39,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(ed);
MAYUSE(i32);
MAYUSE(j32);
switch(nextop) {
case 0xC0:
+5 -3
View File
@@ -26,7 +26,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
{
uint8_t nextop = F8;
uint8_t u8;
int32_t i32;
int32_t j32;
uint8_t ed;
uint8_t wback;
int v1, v2;
@@ -37,7 +37,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MAYUSE(s0);
MAYUSE(v1);
MAYUSE(v2);
MAYUSE(i32);
MAYUSE(j32);
switch(nextop) {
case 0xC0:
@@ -105,6 +105,9 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
TSTS_REG_LSL_IMM5(x1, x1, 0);
VMOVcond_64(cEQ, v1, v2); // F_PF==0
break;
case 0xE1:
INST_NAME("FDISI8087_NOP"); // so.. NOP?
break;
case 0xE2:
INST_NAME("FNCLEX");
MOVW(x1, 0);
@@ -150,7 +153,6 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xE0:
case 0xE1:
case 0xE4:
case 0xE5:
case 0xE6:
+18 -7
View File
@@ -144,16 +144,16 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_64(v1, ed, fixedaddress);
#else
parity = getedparity(dyn, ninst, addr, nextop, 3);
if (parity) {
parity = getedparity(dyn, ninst, addr, nextop, 3);
if (parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_64(v1, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress + 4);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress + 4);
VMOVtoV_D(v1, x2, x3);
}
}
#endif
break;
case 1:
@@ -207,6 +207,17 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fsave, -1, 0);
break;
case 7:
INST_NAME("FNSTSW m2byte");
fpu_purgecache(dyn, ninst, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x12, &fixedaddress, 0, 0);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, top));
MOVW(x2, offsetof(x86emu_t, sw));
ADD_REG_LSL_IMM5(x2, xEmu, x2, 0);
LDRH_IMM8(x3, x2, 0);
BFI(x3, x1, 11, 3); // inject TOP at bit 11 (3 bits)
STRH_IMM8(x3, ed, 0); // store whole sw flags
break;
default:
DEFAULT;
}
+17 -9
View File
@@ -59,7 +59,23 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMUL_F64(v2, v2, v1);
x87_do_pop(dyn, ninst);
break;
case 0xD9: /* FCOMPP */
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
INST_NAME("FCOMP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOM(x1, x2);
x87_do_pop(dyn, ninst);
break;
case 0xD9:
INST_NAME("FCOMPP ST0, ST1");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, 1);
@@ -125,14 +141,6 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
x87_do_pop(dyn, ninst);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
case 0xD8:
case 0xDA:
case 0xDB:
+49 -37
View File
@@ -28,7 +28,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
{
uint8_t nextop = F8;
uint8_t u8;
int32_t i32;
int32_t j32;
uint8_t wback;
uint8_t ed;
int v1, v2;
@@ -38,9 +38,22 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(i32);
MAYUSE(j32);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FFREEP STx");
// not handling Tag...
x87_do_pop(dyn, ninst);
break;
case 0xE0:
INST_NAME("FNSTSW AX");
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
@@ -82,14 +95,6 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
x87_do_pop(dyn, ninst);
break;
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
case 0xC8:
case 0xC9:
case 0xCA:
@@ -146,22 +151,23 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 1:
INST_NAME("FISTTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x12);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
VCVT_S32_F64(s0, v1);
MSR_nzcvq_0();
// x1 already have FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b001, 6); // 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);
MSR_nzcvq_0(); // reset Q flag (and all other flags too)
SSAT_REG_LSL_IMM5(ed, 16, ed, 0);
MRS_aspr(x3); // check Q flag
TSTS_IMM8_ROR(x3, 0b10, 3);
B_MARK(cEQ); // not saturated, continue
MOV32(ed, 0xffff8000);
MARK;
STRH_IMM8(ed, wback, fixedaddress);
TSTS_IMM8_ROR(x3, 0b00000001, 0);
SSAT_REG_LSL_IMM5_COND(cEQ, x3, 16, ed, 0);
CMPS_REG_LSL_IMM5_COND(cEQ, ed, x3, 0);
MOVW_COND(cNE, x3, 0x8000); // saturated
STRH_IMM8(x3, wback, fixedaddress);
x87_do_pop(dyn, ninst);
x87_restoreround(dyn, ninst, u8);
break;
case 2:
INST_NAME("FIST Ew, ST0");
@@ -170,16 +176,19 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// x1 already have FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
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);
MSR_nzcvq_0(); // reset Q flag (and all other flags too)
SSAT_REG_LSL_IMM5(ed, 16, ed, 0);
MRS_aspr(x3); // check Q flag
TSTS_IMM8_ROR(x3, 0b10, 3);
B_MARK(cEQ); // not saturated, continue
MOV32(ed, 0xffff8000);
MARK;
STRH_IMM8(ed, wback, fixedaddress);
TSTS_IMM8_ROR(x3, 0b00000001, 0);
SSAT_REG_LSL_IMM5_COND(cEQ, x3, 16, ed, 0);
CMPS_REG_LSL_IMM5_COND(cEQ, ed, x3, 0);
MOVW_COND(cNE, x3, 0x8000); // saturated
STRH_IMM8(x3, wback, fixedaddress);
x87_restoreround(dyn, ninst, u8);
break;
case 3:
@@ -189,16 +198,19 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// x1 already have FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
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);
MSR_nzcvq_0(); // reset Q flag (and all other flags too)
SSAT_REG_LSL_IMM5(ed, 16, ed, 0);
MRS_aspr(x3); // check Q flag
TSTS_IMM8_ROR(x3, 0b10, 3);
B_MARK(cEQ); // not saturated, continue
MOV32(ed, 0xffff8000);
MARK;
STRH_IMM8(ed, wback, fixedaddress);
TSTS_IMM8_ROR(x3, 0b00000001, 0);
SSAT_REG_LSL_IMM5_COND(cEQ, x3, 16, ed, 0);
CMPS_REG_LSL_IMM5_COND(cEQ, ed, x3, 0);
MOVW_COND(cNE, x3, 0x8000); // saturated
STRH_IMM8(x3, wback, fixedaddress);
x87_do_pop(dyn, ninst);
x87_restoreround(dyn, ninst, u8);
break;
+9 -9
View File
@@ -432,7 +432,7 @@ void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int
void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c);
MOV32(s3, c&0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_or8);
@@ -543,7 +543,7 @@ void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c);
MOV32(s3, c&0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_xor8);
@@ -654,7 +654,7 @@ void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c);
MOV32(s3, c&0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_and8);
@@ -766,7 +766,7 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c);
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_or16);
@@ -783,7 +783,7 @@ void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
ORR_IMM8(s1, s1, c, 0);
}
} else {
IFX(X_PEND) {} else {MOV32(s3, c);}
IFX(X_PEND) {} else {MOVW(s3, c);}
IFX(X_ALL) {
ORRS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
@@ -886,7 +886,7 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c);
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_xor16);
@@ -903,7 +903,7 @@ void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
XOR_IMM8(s1, s1, c);
}
} else {
IFX(X_PEND) {} else {MOV32(s3, c);}
IFX(X_PEND) {} else {MOVW(s3, c);}
IFX(X_ALL) {
XORS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
@@ -1006,7 +1006,7 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c);
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_and16);
@@ -1023,7 +1023,7 @@ void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
AND_IMM8(s1, s1, c);
}
} else {
IFX(X_ALL) {} else {MOVW(s3, c);}
IFX(X_PEND) {} else {MOVW(s3, c);}
IFX(X_ALL) {
ANDS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
+137 -185
View File
@@ -104,7 +104,7 @@ void emit_add32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
ORR_IMM8(s3, s1, c, 0); // s3 = op1 | op2
AND_IMM8(s4, s1, c); // s4 = op1 & op2
} else {
MOV32(s3, c);
IFX(X_PEND) {} else {MOV32(s3, c);}
MOV_REG(s4, s3);
ORR_REG_LSL_IMM5(s3, s1, s3, 0);
AND_REG_LSL_IMM5(s4, s1, s4, 0);
@@ -118,7 +118,7 @@ void emit_add32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
ADD_IMM8(s1, s1, c);
}
} else {
MOV32(s3, c);
IFXN(X_PEND, X_AF) {} else {MOV32(s3, c);}
IFX(X_ALL) {
ADDS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
@@ -251,7 +251,7 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
AND_IMM8(s4, s3, c); // s4 = ~op1 & op2
ORR_IMM8(s3, s3, c, 0); // s3 = ~op1 | op2
} else {
MOV32(s3, c);
IFX(X_PEND) {} else {MOV32(s3, c);}
MVN_REG_LSL_IMM5(s4, s1, 0);
ORR_REG_LSL_IMM5(s3, s4, s3, 0);
MOV32(s4, c);
@@ -266,7 +266,7 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
SUB_IMM8(s1, s1, c);
}
} else {
MOV32(s3, c);
IFXN(X_PEND, X_AF) {} else {MOV32(s3, c);}
IFX(X_ALL) {
SUBS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
@@ -353,13 +353,11 @@ void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
UBFX(s3, s1, 8, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
IFX(X_PEND|X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
@@ -385,7 +383,7 @@ void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
MOVW(s3, c&0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s3, d_add8);
@@ -419,14 +417,11 @@ void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
UBFX(s3, s1, 8, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
IFX(X_PEND|X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
@@ -468,11 +463,8 @@ void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
}
SUB_REG_LSL_IMM5(s1, s1, s2, 0);
IFX(X_PEND|X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF|X_CF) {
AND_REG_LSL_IMM5(s3, s3, s1, 0); // s3 = (~op1 | op2) & res
@@ -493,6 +485,7 @@ void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
}
}
IFX(X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
@@ -518,7 +511,7 @@ void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
MOVW(s3, c&0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s3, d_sub8);
@@ -530,16 +523,13 @@ void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
}
IFX(X_AF|X_OF|X_CF) {
MVN_REG_LSL_IMM5(s3, s1, 0);
MOVW(s4, c);
MOVW(s4, c&0xff);
ORR_IMM8(s3, s3, c, 0); // s3 = ~op1 | op2
BIC_REG_LSL_IMM5(s4, s4, s1, 0); // s4 = ~op1 & op2
}
SUB_IMM8(s1, s1, c);
IFX(X_PEND|X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF|X_CF) {
AND_REG_LSL_IMM5(s3, s3, s1, 0); // s3 = (~op1 | op2) & res
@@ -560,6 +550,7 @@ void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
}
}
IFX(X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
@@ -618,13 +609,11 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
UBFX(s3, s1, 16, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
IFX(X_PEND|X_ZF) {
UXTH(s1, s1, 0);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
UXTH(s1, s1, 0);
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
@@ -654,12 +643,12 @@ void emit_add16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s3, d_add16);
MOVW(s4, d_add16);
} else IFX(X_ALL) {
MOVW(s3, d_none);
MOVW(s4, d_none);
}
IFX(X_PEND|X_ALL) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
}
IFX(X_AF | X_OF) {
MOV_REG(s4, s1);
@@ -667,7 +656,7 @@ void emit_add16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
if(c>=0 && c<256) {
ADD_IMM8(s1, s1, c);
} else {
MOVW(s3, c);
IFX(X_PEND) {} else {MOVW(s3, c);}
ADD_REG_LSL_IMM5(s1, s1, s3, 0);
}
@@ -700,13 +689,11 @@ void emit_add16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
UBFX(s3, s1, 16, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
IFX(X_PEND|X_ZF) {
UXTH(s1, s1, 0);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
UXTH(s1, s1, 0);
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
@@ -749,11 +736,8 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
}
SUB_REG_LSL_IMM5(s1, s1, s2, 0);
IFX(X_PEND|X_ZF) {
UXTH(s1, s1, 0);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF|X_CF) {
AND_REG_LSL_IMM5(s3, s3, s1, 0); // s3 = (~op1 | op2) & res
@@ -774,6 +758,7 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
}
}
IFX(X_ZF) {
UXTH(s1, s1, 0);
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
@@ -803,12 +788,12 @@ void emit_sub16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s3, d_sub16);
MOVW(s4, d_sub16);
} else IFX(X_ALL) {
MOVW(s3, d_none);
MOVW(s4, d_none);
}
IFX(X_PEND|X_ALL) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
}
IFX(X_AF|X_OF|X_CF) {
MVN_REG_LSL_IMM5(s4, s1, 0);
@@ -816,14 +801,11 @@ void emit_sub16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
if(c>=0 && c<255) {
SUB_IMM8(s1, s1, c);
} else {
MOVW(s3, c);
IFX(X_PEND) {} else {MOVW(s3, c);}
SUB_REG_LSL_IMM5(s1, s1, s3, 0);
}
IFX(X_PEND|X_ZF) {
UXTH(s1, s1, 0);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF|X_CF) {
if(c>=0 && c<256) {
@@ -854,6 +836,7 @@ void emit_sub16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
}
}
IFX(X_ZF) {
UXTH(s1, s1, 0);
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
@@ -881,10 +864,10 @@ void emit_inc32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
MOVW(s4, d_inc32);
} else IFX(X_ALL) {
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
MOVW(s4, d_none);
}
IFX(X_PEND|X_ALL) {
IFX(X_PEND|X_ZF|X_OF|X_AF|X_SF|X_PF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
}
IFX(X_AF) {
@@ -937,10 +920,10 @@ void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
MOVW(s3, d_inc8);
} else IFX(X_ALL) {
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
MOVW(s3, d_none);
}
IFX(X_PEND|X_ALL) {
IFX(X_PEND|X_ZF|X_OF|X_AF|X_SF|X_PF) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
}
IFX(X_AF | X_OF) {
@@ -948,7 +931,9 @@ void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
AND_IMM8(s4, s1, 1); // s4 = op1 & op2
}
ADD_IMM8(s1, s1, 1);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF) {
BIC_REG_LSL_IMM5(s3, s3, s1, 0); // s3 = (op1 | op2) & ~ res
ORR_REG_LSL_IMM5(s3, s3, s4, 0); // s4 = (op1 & op2) | ((op1 | op2) & ~ res)
@@ -964,13 +949,8 @@ void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
}
}
IFX(X_PEND|X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
}
IFX(X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
@@ -997,17 +977,19 @@ void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
MOVW(s3, d_inc16);
} else IFX(X_ALL) {
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
MOVW(s3, d_none);
}
IFX(X_PEND|X_ALL) {
IFX(X_PEND|X_ZF|X_OF|X_AF|X_SF|X_PF) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
}
IFX(X_AF | X_OF) {
MOV_REG(s4, s1);
}
ADD_IMM8(s1, s1, 1);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF) {
ORR_IMM8(s3, s4, 1, 0); // s3 = op1 | op2
AND_IMM8(s4, s4, 1); // s4 = op1 & op2
@@ -1025,13 +1007,8 @@ void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
}
}
IFX(X_PEND|X_ZF) {
UXTH(s1, s1, 0);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
}
IFX(X_ZF) {
UXTH(s1, s1, 0);
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
@@ -1059,10 +1036,10 @@ void emit_dec32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
MOVW(s4, d_dec32);
} else IFX(X_ALL) {
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
MOVW(s4, d_none);
}
IFX(X_PEND|X_ALL) {
IFX(X_PEND|X_ZF|X_OF|X_AF|X_SF|X_PF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
}
IFX(X_AF) {
@@ -1116,10 +1093,10 @@ void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s3, d_dec8);
} else IFX(X_ALL) {
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
MOVW(s3, d_none);
}
IFX(X_PEND|X_ALL) {
IFX(X_PEND|X_ZF|X_OF|X_AF|X_SF|X_PF) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
}
IFX(X_AF|X_OF) {
@@ -1128,11 +1105,8 @@ void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
ORR_IMM8(s3, s3, 1, 0); // s3 = ~op1 | op2
}
SUB_IMM8(s1, s1, 1);
IFX(X_PEND|X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF) {
AND_REG_LSL_IMM5(s3, s3, s1, 0); // s3 = (~op1 | op2) & res
@@ -1149,6 +1123,7 @@ void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
}
}
IFX(X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
@@ -1175,21 +1150,18 @@ void emit_dec16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
MOVW(s3, d_dec16);
} else IFX(X_ALL) {
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
MOVW(s3, d_none);
}
IFX(X_PEND|X_ALL) {
IFX(X_PEND|X_ZF|X_OF|X_AF|X_SF|X_PF) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
}
IFX(X_AF|X_OF) {
MVN_REG_LSL_IMM5(s4, s1, 0);
}
SUB_IMM8(s1, s1, 1);
IFX(X_PEND|X_ZF) {
UXTH(s1, s1, 0);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF) {
ORR_IMM8(s3, s4, 1, 0); // s3 = ~op1 | op2
@@ -1208,6 +1180,7 @@ void emit_dec16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
}
}
IFX(X_ZF) {
UXTH(s1, s1, 0);
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
@@ -1247,7 +1220,7 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF])); // load CC
MOVS_REG_LSR_IMM5(s3, s3, 1); // load into ARM CF
IFX(X_ALL) {
IFX(X_ZF|X_CF|X_OF) {
ADCS_REG_LSL_IMM5(s1, s1, s2, 0);
} else {
ADC_REG_LSL_IMM5(s1, s1, s2, 0);
@@ -1397,6 +1370,9 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF])); // load CC
MOVS_REG_LSR_IMM5(s3, s3, 1); // load into ARM CF
ADC_REG_LSL_IMM5(s1, s1, s2, 0);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF) {
ORR_REG_LSL_IMM5(s3, s4, s2, 0); // s3 = op1 | op2
AND_REG_LSL_IMM5(s4, s4, s2, 0); // s4 = op1 & op2
@@ -1417,13 +1393,8 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
UBFX(s3, s1, 8, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
IFX(X_PEND|X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
}
IFX(X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
@@ -1449,15 +1420,15 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
MOVW(s3, c&0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s3, d_adc8);
MOVW(s4, d_adc8);
} else IFX(X_ALL) {
MOVW(s3, d_none);
MOVW(s4, d_none);
}
IFX(X_PEND|X_ALL) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
}
IFX(X_AF | X_OF) {
MOV_REG(s4, s1);
@@ -1465,7 +1436,9 @@ void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF])); // load CC
MOVS_REG_LSR_IMM5(s3, s3, 1); // load into ARM CF
ADC_IMM8(s1, s1, c);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF) {
ORR_IMM8(s3, s4, c, 0); // s3 = op1 | op2
AND_IMM8(s4, s4, c); // s4 = op1 & op2
@@ -1486,17 +1459,11 @@ void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
UBFX(s3, s1, 8, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
IFX(X_PEND|X_ZF) {
IFX(X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_SF) {
UBFX(s3, s1, 7, 1);
@@ -1534,7 +1501,9 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF])); // load CC
MOVS_REG_LSR_IMM5(s3, s3, 1); // load into ARM CF
ADC_REG_LSL_IMM5(s1, s1, s2, 0);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF) {
ORR_REG_LSL_IMM5(s3, s4, s2, 0); // s3 = op1 | op2
AND_REG_LSL_IMM5(s4, s4, s2, 0); // s4 = op1 & op2
@@ -1555,17 +1524,12 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
UBFX(s3, s1, 16, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
IFX(X_PEND|X_ZF) {
IFX(X_ZF) {
UXTH(s1, s1, 0);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_SF) {
UBFX(s3, s1, 15, 1);
@@ -1609,7 +1573,9 @@ void emit_adc16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
MOVW(s3, c);
ADC_REG_LSL_IMM5(s1, s1, s3, 0);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF) {
if(c>=0 && c<256) {
ORR_IMM8(s3, s4, c, 0); // s3 = op1 | op2
@@ -1639,17 +1605,12 @@ void emit_adc16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
UBFX(s3, s1, 16, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
IFX(X_PEND|X_ZF) {
IFX(X_ZF) {
UXTH(s1, s1, 0);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_SF) {
UBFX(s3, s1, 15, 1);
@@ -1839,16 +1800,8 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
XOR_IMM8(s3, s3, 1); // invert CC because it's reverted for SUB on ARM
MOVS_REG_LSR_IMM5(s3, s3, 1); // load into ARM CF
SBC_REG_LSL_IMM5(s1, s1, s2, 0);
IFX(X_PEND|X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF|X_CF) {
ORR_REG_LSL_IMM5(s3, s4, s2, 0); // s3 = ~op1 | op2
@@ -1870,6 +1823,12 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
}
}
IFX(X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_SF) {
UBFX(s3, s1, 7, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_SF]));
@@ -1891,7 +1850,7 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
MOVW(s3, c&0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s3, d_sbb8);
@@ -1908,11 +1867,8 @@ void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
XOR_IMM8(s3, s3, 1); // invert CC because it's reverted for SUB on ARM
MOVS_REG_LSR_IMM5(s3, s3, 1); // load into ARM CF
SBC_IMM8(s1, s1, c);
IFX(X_PEND|X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF|X_CF) {
ORR_IMM8(s3, s4, c, 0); // s3 = ~op1 | op2
@@ -1935,6 +1891,7 @@ void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
}
}
IFX(X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
@@ -1977,11 +1934,8 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
XOR_IMM8(s3, s3, 1); // invert CC because it's reverted for SUB on ARM
MOVS_REG_LSR_IMM5(s3, s3, 1); // load into ARM CF
SBC_REG_LSL_IMM5(s1, s1, s2, 0);
IFX(X_PEND|X_ZF) {
UXTH(s1, s1, 0);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF|X_CF) {
ORR_REG_LSL_IMM5(s3, s4, s2, 0); // s3 = ~op1 | op2
@@ -2004,6 +1958,7 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
}
}
IFX(X_ZF) {
UXTH(s1, s1, 0);
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
@@ -2052,11 +2007,8 @@ void emit_sbb16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
MOVW(s3, c);
SBC_REG_LSL_IMM5(s1, s1, s3, 0);
}
IFX(X_PEND|X_ZF) {
UXTH(s1, s1, 0);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF|X_CF) {
if(c>=0 && c<256) {
@@ -2087,6 +2039,7 @@ void emit_sbb16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
}
}
IFX(X_ZF) {
UXTH(s1, s1, 0);
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
@@ -2134,6 +2087,9 @@ void emit_neg32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
} else {
RSB_IMM8(s1, s1, 0);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW_COND(cEQ, s4, 1);
MOVW_COND(cNE, s4, 0);
@@ -2187,17 +2143,8 @@ void emit_neg16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
MOV_REG_LSL_IMM5(s3, s1, 0);
}
RSB_IMM8(s1, s1, 0);
IFX(X_ZF) {
BFI(s1, s1, 0, 16);
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cEQ, s4, 1);
MOVW_COND(cNE, s4, 0);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_OF) {
MOVW_COND(cVC, s4, 0);
MOVW_COND(cVS, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF) {
ORR_REG_LSL_IMM5(s3, s3, s1, 0); // bc = op1 | res
@@ -2211,7 +2158,14 @@ void emit_neg16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
}
}
}
IFX(X_ZF) {
UXTH(s1, s1, 0);
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cEQ, s4, 1);
MOVW_COND(cNE, s4, 0);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_SF) {
UBFX(s3, s1, 15, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_SF]));
@@ -2250,16 +2204,8 @@ void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
MOV_REG_LSL_IMM5(s3, s1, 0);
}
RSB_IMM8(s1, s1, 0);
IFX(X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
MOVW_COND(cEQ, s4, 1);
MOVW_COND(cNE, s4, 0);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_OF) {
MOVW_COND(cVC, s4, 0);
MOVW_COND(cVS, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_AF|X_OF) {
ORR_REG_LSL_IMM5(s3, s3, s1, 0); // bc = op1 | res
@@ -2273,7 +2219,13 @@ void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
}
}
}
IFX(X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
MOVW_COND(cEQ, s4, 1);
MOVW_COND(cNE, s4, 0);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
}
IFX(X_SF) {
UBFX(s3, s1, 7, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_SF]));
+4 -2
View File
@@ -48,8 +48,10 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
return;
}
IFX(X_CF) {
UBFX(s3, s1, c, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
if(c<31) {
UBFX(s3, s1, 32-c, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
}
IFX(X_ZF|X_OF) {
MOVS_REG_LSL_IMM5(s1, s1, c);
+827 -33
View File
@@ -24,13 +24,477 @@
uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = PK(0); // don't increment addr
int locked = 0;
switch(nextop) {
// generic case
uint8_t nextop, opcode = F8;
uint8_t wback, wb1, wb2, gb1, gb2;
uint8_t ed, gd, u8;
int fixedaddress;
int32_t i32, j32;
MAYUSE(i32);
MAYUSE(j32);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(wb1);
MAYUSE(wb2);
switch(opcode) {
case 0x00:
INST_NAME("LOCK ADD Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
emit_add8(dyn, ninst, x1, x2, x12, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x1, wback);
emit_add8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
case 0x01:
INST_NAME("LOCK ADD Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_add32(dyn, ninst, ed, gd, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_add32(dyn, ninst, x1, gd, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 0x08:
INST_NAME("LOCK OR Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
emit_or8(dyn, ninst, x1, x2, x12, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x1, wback);
emit_or8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
case 0x09:
INST_NAME("LOCK OR Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_or32(dyn, ninst, ed, gd, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_or32(dyn, ninst, x1, gd, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 0x10:
INST_NAME("LOCK ADC Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
emit_adc8(dyn, ninst, x1, x2, x12, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x1, wback);
emit_adc8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
case 0x11:
INST_NAME("LOCK ADC Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_adc32(dyn, ninst, ed, gd, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_adc32(dyn, ninst, x1, gd, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 0x18:
INST_NAME("LOCK SBB Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
emit_sbb8(dyn, ninst, x1, x2, x12, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x1, wback);
emit_sbb8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
case 0x19:
INST_NAME("LOCK SBB Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_sbb32(dyn, ninst, ed, gd, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_sbb32(dyn, ninst, x1, gd, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 0x20:
INST_NAME("LOCK AND Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
emit_and8(dyn, ninst, x1, x2, x12, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x1, wback);
emit_and8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
case 0x21:
INST_NAME("LOCK AND Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_and32(dyn, ninst, ed, gd, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_and32(dyn, ninst, x1, gd, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 0x28:
INST_NAME("LOCK SUB Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
emit_sub8(dyn, ninst, x1, x2, x12, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x1, wback);
emit_sub8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
case 0x29:
INST_NAME("LOCK SUB Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_sub32(dyn, ninst, ed, gd, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_sub32(dyn, ninst, x1, gd, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 0x38:
INST_NAME("LOCK XOR Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
emit_xor8(dyn, ninst, x1, x2, x12, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x1, wback);
emit_xor8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
case 0x39:
INST_NAME("LOCK XOR Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_xor32(dyn, ninst, ed, gd, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_xor32(dyn, ninst, x1, gd, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 0x81:
case 0x83:
nextop = F8;
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
INST_NAME("LOCK ADD Ed, Id");
} else {
INST_NAME("LOCK ADD Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET);
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_add32c(dyn, ninst, ed, i32, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
TSTS_IMM8(wback, 0x3);
B_MARK(cNE);
MARKLOCK;
LDREX(x1, wback);
emit_add32c(dyn, ninst, x1, i32, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
B_NEXT(c__);
MARK; // unaligned! also, not enough
LDR_IMM9(x1, wback, 0);
LDREXB(x12, wback);
BFI(x1, x12, 0, 8); // re-inject
emit_add32c(dyn, ninst, x1, i32, x3, x12);
STREXB(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STR_IMM9(x1, wback, 0); // put the whole value
}
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);
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_or32c(dyn, ninst, ed, i32, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
LDREX(x1, wback);
emit_or32c(dyn, ninst, x1, i32, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
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);
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_adc32c(dyn, ninst, ed, i32, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
LDREX(x1, wback);
emit_adc32c(dyn, ninst, x1, i32, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
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);
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_sbb32c(dyn, ninst, ed, i32, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
LDREX(x1, wback);
emit_sbb32c(dyn, ninst, x1, i32, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
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);
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_and32c(dyn, ninst, ed, i32, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
LDREX(x1, wback);
emit_and32c(dyn, ninst, x1, i32, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("LOCK SUB Ed, Id");} else {INST_NAME("LOCK SUB Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_sub32c(dyn, ninst, ed, i32, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
TSTS_IMM8(wback, 0x3);
B_MARK(cNE);
MARKLOCK;
LDREX(x1, wback);
emit_sub32c(dyn, ninst, x1, i32, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
B_NEXT(c__);
MARK; // unaligned! also, not enough
LDR_IMM9(x1, wback, 0);
LDREXB(x12, wback);
BFI(x1, x12, 0, 8); // re-inject
emit_sub32c(dyn, ninst, x1, i32, x3, x12);
STREXB(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STR_IMM9(x1, wback, 0); // put the whole value
}
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("LOCK XOR Ed, Id");} else {INST_NAME("LOCK XOR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_xor32c(dyn, ninst, ed, i32, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
LDREX(x1, wback);
emit_xor32c(dyn, ninst, x1, i32, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
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);
GETEDH(x1);
// No need to LOCK, this is readonly
if(opcode==0x81) i32 = F32S; else i32 = F8S;
if(i32) {
MOV32(x2, i32);
emit_cmp32(dyn, ninst, ed, x2, x3, x12);
} else {
emit_cmp32_0(dyn, ninst, ed, x3, x12);
}
break;
}
break;
// generic case, no lock needed, the value is only read (note that on x86 locked read is always followed wy a locked write)
#define GO(A) \
case A+0x00: \
case A+0x01: \
case A+0x02: \
case A+0x03: \
case A+0x04: \
@@ -43,62 +507,392 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GO(0x28);
GO(0x30);
#undef GO
case 0x81:
case 0x83:
MESSAGE(LOG_DUMP, "LOCK\n");
locked = 1;
LOCK;
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0x86: // for this two, the lock is already done by the opcode, so just ignoring it
case 0x87:
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog);
--addr;
break;
case 0x90: // This is xchg reg, reg, so let's ignore the LOCK prefix...
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
--addr;
break;
case 0x0F:
nextop = PK(1);
nextop = F8;
switch(nextop) {
case 0xB0:
INST_NAME("LOCK CMPXCHG Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x2, wback, wb2);
ed = x2;
wb1 = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x2, wback);
ed = x2;
wb1 = 1;
}
UXTB(x1, xEAX, 0);
CMPS_REG_LSL_IMM5(x1, ed, 0);
B_MARK(cNE);
// AL == Eb
GETGB(x1);
if(wb1) {
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
B_MARKLOCK(cNE); // write failed, try again
if(!(gb1==xEAX && gb2==0)) {
UXTB(x1, xEAX, 0); // readback AL if needed
}
} else {
BFI(wback, x1, wb2*8, 8);
}
// done
B_MARK3(c__);
MARK;
// AL != Eb
BFI(xEAX, ed, 0, 8);
MARK3;
// done, do the cmp now
emit_cmp8(dyn, ninst, x1, x2, x3, x12);
break;
case 0xB1:
INST_NAME("LOCK CMPXCHG Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
TSTS_IMM8(wback, 3); // can be unaligned it seems
LDREX_COND(cEQ, x1, wback);
LDR_IMM9_COND(cNE, x1, wback, 0);
LDREXB_COND(cNE, x3, wback); // dummy read, to arm the write...
ed = x1;
}
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
B_MARK(cNE);
// EAX == Ed
if(wback) {
TSTS_IMM8(wback, 3);
STREX_COND(cEQ, x12, gd, wback);
STREXB_COND(cNE, x12, gd, wback);
CMPS_IMM8(x12, 0);
B_MARKLOCK(cNE);
TSTS_IMM8(wback, 3); // anoying, all those test
STR_IMM9_COND(cNE, gd, wback, 0);
emit_cmp32(dyn, ninst, xEAX, ed, x1, x12);
} else {
emit_cmp32(dyn, ninst, xEAX, ed, x1, x12);
MOV_REG(ed, gd);
}
// done
B_MARK3(c__); // not next, in case its called with a LOCK prefix
MARK;
// EAX != Ed
emit_cmp32(dyn, ninst, xEAX, ed, x3, x12);
MOV_REG(xEAX, ed);
MARK3
break;
case 0xB3:
INST_NAME("LOCK BTR Ed, Gd");
SETFLAGS(X_CF, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
UBFX(x1, gd, 5, 3); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
wback = x3;
MARKLOCK;
LDREX(x1, wback);
ed = x1;
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x12, ed, x2);
ANDS_IMM8(x12, x12, 1);
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
B_MARK3(cEQ); // bit already clear, jump to end of instruction
MOVW(x12, 1);
XOR_REG_LSL_REG(ed, ed, x12, x2);
if(wback) {
STREX(x12, ed, wback);
CMPS_IMM8(x12, 0);
B_MARKLOCK(cNE);
}
MARK3;
break;
case 0xBA:
nextop = F8;
switch((nextop>>3)&7) {
case 4:
INST_NAME("(LOCK) BT Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
gd = x2;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
u8 = F8;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095-32, 0);
u8 = F8;
fixedaddress+=(u8>>5)*4;
LDR_IMM9(x1, ed, fixedaddress);
ed = x1;
}
u8&=0x1f;
if(u8) {
MOV_REG_LSR_IMM5(x1, ed, u8);
ed = x1;
}
AND_IMM8(x1, ed, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
break;
case 6:
INST_NAME("LOCK BTR Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
gd = x2;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
u8 = F8;
MOVW(gd, u8);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 0, 0);
u8 = F8;
MOVW(gd, u8);
UBFX(x1, gd, 5, 3); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, ed, x1, 2); //(&ed)+=r1*4;
MARKLOCK;
LDREX(x1, x3);
ed = x1;
wback = x3;
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x12, ed, x2);
ANDS_IMM8(x12, x12, 1);
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
B_MARK3(cEQ); // bit already clear, jump to next instruction
//MOVW(x12, 1); // already 0x01
XOR_REG_LSL_REG(ed, ed, x12, x2);
if(wback) {
STREX(x12, ed, wback);
CMPS_IMM8(x12, 0);
B_MARKLOCK(cNE);
}
MARK3;
break;
default:
DEFAULT;
}
break;
case 0xBB:
INST_NAME("LOCK BTC Ed, Gd");
SETFLAGS(X_CF, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
UBFX(x1, gd, 5, 3); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
MARKLOCK;
LDREX(x1, x3);
ed = x1;
wback = x3;
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x12, ed, x2);
AND_IMM8(x12, x12, 1);
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
MOVW(x12, 1);
XOR_REG_LSL_REG(ed, ed, x12, x2);
if(wback) {
STREX(x12, ed, wback);
CMPS_IMM8(x12, 0);
B_MARKLOCK(cNE);
}
break;
case 0xC0:
INST_NAME("LOCK XADD Gb, Eb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x1);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x2, wback, wb2);
wb1 = 0;
ed = x2;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x2, wback);
wb1 = 1;
ed = x2;
}
BFI(gb1, ed, gb2*8, 8); // gb <- eb
emit_add8(dyn, ninst, ed, gd, x12, x3, 1);
if(wb1) {
STREXB(x12, ed, wback);
CMPS_IMM8(x12, 0);
B_MARKLOCK(cNE);
} else {
BFI(wback, ed, wb2*8, 8);
}
break;
case 0xC1:
INST_NAME("LOCK XADD Gd, Ed");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
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);
}
emit_add32(dyn, ninst, ed, gd, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
TSTS_IMM8(wback, 3);
B_MARK(cNE); // unaligned
MARKLOCK;
LDREX(x1, wback);
ADD_REG_LSL_IMM5(x12, x1, gd, 0);
STREX(x3, x12, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
IFX(X_ALL|X_PEND) {
MOV_REG(x2, x1);
emit_add32(dyn, ninst, x2, gd, x3, x12);
}
MOV_REG(gd, x1);
B_NEXT(c__);
MARK;
LDR_IMM9(x1, wback, 0);
LDREXB(x12, wback);
BFI(x1, x12, 0, 8);
ADD_REG_LSL_IMM5(x12, x1, gd, 0);
STREXB(x3, x12, wback);
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STR_IMM9(x12, wback, 0);
IFX(X_ALL|X_PEND) {
MOV_REG(x2, x1);
emit_add32(dyn, ninst, x2, gd, x3, x12);
}
MOV_REG(gd, x1);
}
break;
case 0xC7:
MESSAGE(LOG_DUMP, "LOCK\n");
locked = 1;
LOCK;
addr = dynarec0F(dyn, addr+1, ip, ninst, ok, need_epilog);
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SET);
nextop = F8;
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0);
MARKLOCK;
TSTS_IMM8(wback, 7);
LDREXD_COND(cEQ, x2, wback);
LDREX_COND(cNE, x2, wback);
LDR_IMM9_COND(cNE, x3, wback, 4);
CMPS_REG_LSL_IMM5(xEAX, x2, 0);
B_MARK(cNE); // EAX != Ed[0]
CMPS_REG_LSL_IMM5(xEDX, x3, 0);
B_MARK(cNE); // EDX != Ed[1]
MOV_REG(x2, xEBX);
MOV_REG(x3, xECX);
TSTS_IMM8(wback, 7);
STREXD_COND(cEQ, x12, x2, wback);
STREX_COND(cNE, x12, x2, wback);
CMPS_IMM8(x12, 0);
B_MARKLOCK(cNE);
TSTS_IMM8(wback, 7);
STR_IMM9_COND(cNE, x3, wback, 4);
MOVW(x1, 1);
B_MARK3(c__);
MARK;
MOV_REG(xEAX, x2);
MOV_REG(xEDX, x3);
MOVW(x1, 0);
MARK3;
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
break;
default:
addr = dynarec0F(dyn, addr+1, ip, ninst, ok, need_epilog); // no lock, regular instruction...
// dafault to NO LOCK
addr-=2;
}
break;
case 0xFF:
nextop = PK(1);
nextop = F8;
switch((nextop>>3)&7)
{
case 0:
case 1:
MESSAGE(LOG_DUMP, "LOCK\n");
locked = 1;
LOCK;
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog);
case 0: // INC Ed
INST_NAME("INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_inc32(dyn, ninst, ed, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_inc32(dyn, ninst, x1, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 1: //DEC Ed
INST_NAME("DEC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_dec32(dyn, ninst, ed, x3, x12);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_dec32(dyn, ninst, x1, x3, x12);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
default:
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog); // no lock, regular instruction...
// dafault to NO LOCK
addr-=2;
}
break;
default:
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog); // no lock, regular instruction...
// dafault to NO LOCK
--addr;
}
if(locked) {UNLOCK;}
return addr;
}
+26 -5
View File
@@ -58,16 +58,17 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
MAYUSE(d0);
switch(nextop) {
case 0x10:
INST_NAME("MOVSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
v0 = sse_get_reg(dyn, ninst, x1, gd);
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
VMOVD(v0, d0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
@@ -94,18 +95,18 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVDDUP Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVD(v0, d0);
VMOVD(v0+1, d0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
VMOVD(v0+1, v0);
}
VMOVD(v0+1, v0);
break;
case 0x2A:
@@ -308,6 +309,26 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVtoV_D(v0, x2, x2);
break;
case 0xF0:
INST_NAME("LDDQ Gx,Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
LDR_IMM9(x2, ed, fixedaddress+8);
LDR_IMM9(x3, ed, fixedaddress+12);
VMOVtoV_D(v0+1, x2, x3);
}
break;
default:
DEFAULT;
}
+86 -8
View File
@@ -55,7 +55,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
{
uint8_t opcode = F8;
uint8_t nextop, u8;
int32_t i32;
int32_t j32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback;
@@ -63,12 +63,13 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
int v0, v1;
int s0, s1, s2;
int d0, d1;
int q0;
int q0, q1;
int parity;
MAYUSE(q1);
MAYUSE(s1);
MAYUSE(s2);
MAYUSE(i32);
MAYUSE(j32);
switch(opcode) {
@@ -132,6 +133,38 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
STR_IMM9(x2, ed, fixedaddress);
}
break;
case 0x12:
INST_NAME("MOVSLDUP Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
q1 = sse_get_reg(dyn, ninst, x1, nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
q1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q1, ed);
}
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VDUP_32(q0+0, q1+0, 0);
VDUP_32(q0+1, q1+1, 0);
break;
case 0x16:
INST_NAME("MOVSHDUP Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
q1 = sse_get_reg(dyn, ninst, x1, nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
q1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q1, ed);
}
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VDUP_32(q0+0, q1+0, 1);
VDUP_32(q0+1, q1+1, 1);
break;
case 0x1E:
INST_NAME("NOP / ENDBR32 / ENDBR64");
@@ -179,8 +212,15 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
VMOV_32(s0, d0*2);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_32(s0, ed, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
LDR_IMM9(x2, ed, fixedaddress);
VMOVtoV(s0, x2);
}
}
VCVT_S32_F32(s0, s0);
VMOVfrV(gd, s0);
@@ -201,8 +241,15 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
VMOV_32(s0, d0*2);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_32(s0, ed, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
LDR_IMM9(x2, ed, fixedaddress);
VMOVtoV(s0, x2);
}
}
VCVTR_S32_F32(s0, s0);
VMOVfrV(gd, s0);
@@ -502,8 +549,8 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg(dyn, ninst, x1, gd);
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
v0 = sse_get_reg(dyn, ninst, x1, gd);
@@ -566,6 +613,37 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
VMOVtoDx_32(v0, 0, x2);
break;
case 0xE6:
INST_NAME("CVTDQ2PD Gx, Ex");
nextop = F8;
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
if(v1<16)
v0 = v1;
else {
v0 = fpu_get_scratch_double(dyn);
VMOV_64(v0, v1); // vfpu opcode here
}
} else {
v0 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_64(v0, ed, fixedaddress); // vfpu opcode here
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
}
}
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
//v0 is a low reg now
VCVT_F64_S32(q0+1, v0*2+1);
VCVT_F64_S32(q0+0, v0*2+0);
break;
default:
DEFAULT;
+67 -41
View File
@@ -32,6 +32,14 @@ void arm_popf(x86emu_t* emu, uint32_t f)
RESET_FLAGS(emu);
}
void arm_popf16(x86emu_t* emu, uint32_t f)
{
emu->packed_eflags.x32 &= 0xffff0000;
emu->packed_eflags.x32 |= (f & 0x7FD7) | 0x2; // mask off res2 and res3 and on res1
UnpackFlags(emu);
RESET_FLAGS(emu);
}
void arm_fstp(x86emu_t* emu, void* p)
{
if(ST0.ll!=STld(0).ref)
@@ -109,8 +117,10 @@ void arm_fbld(x86emu_t* emu, uint8_t* ed)
void arm_fild64(x86emu_t* emu, int64_t* ed)
{
ST0.d = *ed;
STll(0).ll = *ed;
int64_t tmp;
memcpy(&tmp, ed, sizeof(tmp));
ST0.d = tmp;
STll(0).ll = tmp;
STll(0).ref = ST0.ll;
}
@@ -121,13 +131,16 @@ void arm_fbstp(x86emu_t* emu, uint8_t* ed)
void arm_fistp64(x86emu_t* emu, int64_t* ed)
{
// used of memcpy to avoid aligments issues
if(STll(0).ref==ST(0).ll) {
*ed = STll(0).ll;
memcpy(ed, &STll(0).ll, sizeof(int64_t));
} else {
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL))
*ed = 0x8000000000000000LL;
int64_t tmp;
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL) || !isfinite(ST0.d))
tmp = 0x8000000000000000LL;
else
*ed = (int64_t)ST0.d;
tmp = fpu_round(emu, ST0.d);
memcpy(ed, &tmp, sizeof(tmp));
}
}
@@ -143,31 +156,6 @@ void arm_ud(x86emu_t* emu)
kill(getpid(), SIGILL);
}
void arm_fxsave(x86emu_t* emu, uint8_t* ed)
{
// should save flags & all
// copy MMX regs...
for(int i=0; i<8; ++i)
memcpy(ed+32+i*16, &emu->mmx[0], sizeof(emu->mmx[0]));
// copy SSE regs
memcpy(ed+160, &emu->xmm[0], sizeof(emu->xmm));
// put also FPU regs in a reserved area...
for(int i=0; i<8; ++i)
memcpy(ed+416+i*8, &emu->fpu[0], sizeof(emu->fpu[0]));
}
void arm_fxrstor(x86emu_t* emu, uint8_t* ed)
{
// should restore flags & all
// copy back MMX regs...
for(int i=0; i<8; ++i)
memcpy(&emu->mmx[i], ed+32+i*16, sizeof(emu->mmx[0]));
// copy SSE regs
memcpy(&emu->xmm[0], ed+160/4, sizeof(emu->xmm));
for(int i=0; i<8; ++i)
memcpy(&emu->fpu[0], ed+416+i*8, sizeof(emu->fpu[0]));
}
void arm_fsave(x86emu_t* emu, uint8_t* ed)
{
fpu_savenv(emu, (char*)ed, 0);
@@ -175,12 +163,7 @@ void arm_fsave(x86emu_t* emu, uint8_t* ed)
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
#ifdef USE_FLOAT
d = ST(i).f;
LD2D(p, &d);
#else
LD2D(p, &ST(i).d);
#endif
p+=10;
}
}
@@ -191,17 +174,23 @@ void arm_frstor(x86emu_t* emu, uint8_t* ed)
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
#ifdef USE_FLOAT
D2LD(&d, p);
ST(i).f = d;
#else
D2LD(&ST(i).d, p);
#endif
p+=10;
}
}
void arm_fprem1(x86emu_t* emu)
{
// simplified version
int32_t tmp32s = round(ST0.d / ST1.d);
ST0.d -= ST1.d*tmp32s;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = (tmp32s&1);
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
emu->sw.f.F87_C1 = ((tmp32s>>2)&1);
}
// Get a FPU single scratch reg
int fpu_get_scratch_single(dynarec_arm_t* dyn)
@@ -218,6 +207,13 @@ int fpu_get_scratch_double(dynarec_arm_t* dyn)
// Get a FPU quad scratch reg
int fpu_get_scratch_quad(dynarec_arm_t* dyn)
{
if(dyn->fpu_scratch>4) {
if(dyn->fpu_extra_qscratch) {
dynarec_log(LOG_NONE, "Warning, Extra QScratch slot taken and need another one!\n");
} else
dyn->fpu_extra_qscratch = fpu_get_reg_quad(dyn);
return dyn->fpu_extra_qscratch;
}
int i = (dyn->fpu_scratch+3)&(~3);
dyn->fpu_scratch = i+4;
return i/2; // Return a Dx, not a Qx
@@ -226,6 +222,10 @@ int fpu_get_scratch_quad(dynarec_arm_t* dyn)
void fpu_reset_scratch(dynarec_arm_t* dyn)
{
dyn->fpu_scratch = 0;
if(dyn->fpu_extra_qscratch) {
fpu_free_reg_quad(dyn, dyn->fpu_extra_qscratch);
dyn->fpu_extra_qscratch = 0;
}
}
#define FPUFIRST 8
// Get a FPU double reg
@@ -306,3 +306,29 @@ int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, i
#undef F8
#undef F32
}
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn)
{
#define PK(a) *(uint8_t*)(addr+a)
#define PK32(a) *(uint32_t*)(addr+a)
if(!addr)
return 0;
if(PK(0)==0xff && PK(1)==0x25) { // absolute jump, maybe the GOT
uintptr_t a1 = (PK32(2)); // need to add a check to see if the address is from the GOT !
addr = *(uint32_t*)a1;
}
if(addr<0x10000) // too low, that is suspicious
return 0;
onebridge_t *b = (onebridge_t*)(addr);
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver) {
// found !
if(retn) *retn = (b->C3==0xC2)?b->N:0;
if(calladdress) *calladdress = addr+1;
return 1;
}
return 0;
#undef PK32
#undef PK
}
+5 -2
View File
@@ -4,6 +4,7 @@
typedef struct x86emu_s x86emu_t;
void arm_popf(x86emu_t* emu, uint32_t f);
void arm_popf16(x86emu_t* emu, uint32_t f);
void arm_fstp(x86emu_t* emu, void* p);
void arm_print_armreg(x86emu_t* emu, uintptr_t reg, uintptr_t n);
@@ -25,10 +26,9 @@ void arm_fild64(x86emu_t* emu, int64_t* ed);
void arm_fbstp(x86emu_t* emu, uint8_t* ed);
void arm_fistp64(x86emu_t* emu, int64_t* ed);
void arm_fld(x86emu_t* emu, uint8_t* ed);
void arm_fxsave(x86emu_t* emu, uint8_t* ed);
void arm_fxrstor(x86emu_t* emu, uint8_t* ed);
void arm_fsave(x86emu_t* emu, uint8_t* ed);
void arm_frstor(x86emu_t* emu, uint8_t* ed);
void arm_fprem1(x86emu_t* emu);
void arm_ud(x86emu_t* emu);
@@ -54,4 +54,7 @@ void fpu_reset_reg(dynarec_arm_t* dyn);
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity);
// Is what pointed at addr a native call? And if yes, to what function?
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
#endif //__DYNAREC_ARM_FUNCTIONS_H__
+173 -80
View File
@@ -17,6 +17,7 @@
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "dynablock_private.h"
#include "arm_printer.h"
#include "../tools/bridge_private.h"
@@ -177,6 +178,81 @@ uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
return addr;
}
/* setup r2 to address pointed by ED, r3 as scratch also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, uint32_t absmax, uint32_t mask)
{
uint8_t ret = x2;
uint8_t scratch = x3;
*fixaddress = 0;
if(hint>0) ret = hint;
if(scratch==ret) scratch = x2;
MAYUSE(scratch);
uint32_t m = nextop&0xC7;
uint32_t n = (m>>6)&3;
int32_t offset = 0;
if(!n && m==6) {
offset = F16;
MOVW(ret, offset);
} else {
switch(n) {
case 0: offset = 0; break;
case 1: offset = F8S; break;
case 2: offset = F16S; break;
}
if(offset && (abs(offset)>absmax || (offset&mask))) {
*fixaddress = offset;
offset = 0;
}
switch(m&7) {
case 0: //R_BX + R_SI
UBFX(ret, xEBX, 0, 16);
UBFX(scratch, xESI, 0, 16);
ADD_REG_LSL_IMM5(ret, ret, scratch, 0);
break;
case 1: //R_BX + R_DI
UBFX(ret, xEBX, 0, 16);
UBFX(scratch, xEDI, 0, 16);
ADD_REG_LSL_IMM5(ret, ret, scratch, 0);
break;
case 2: //R_BP + R_SI
UBFX(ret, xEBP, 0, 16);
UBFX(scratch, xESI, 0, 16);
ADD_REG_LSL_IMM5(ret, ret, scratch, 0);
break;
case 3: //R_BP + R_DI
UBFX(ret, xEBP, 0, 16);
UBFX(scratch, xEDI, 0, 16);
ADD_REG_LSL_IMM5(ret, ret, scratch, 0);
break;
case 4: //R_SI
UBFX(ret, xESI, 0, 16);
break;
case 5: //R_DI
UBFX(ret, xEDI, 0, 16);
break;
case 6: //R_BP
UBFX(ret, xEBP, 0, 16);
break;
case 7: //R_BX
UBFX(ret, xEBX, 0, 16);
break;
}
if(offset) {
if(offset<0 && offset>-256) {
SUB_IMM8(ret, ret, -offset);
} else if(offset>0 && offset<256) {
ADD_IMM8(ret, ret, offset);
} else {
MOVW(scratch, offset);
ADD_REG_LSL_IMM5(ret, ret, scratch, 0);
}
}
}
*ed = ret;
return addr;
}
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
{
MESSAGE(LOG_DUMP, "Jump to epilog\n");
@@ -195,8 +271,8 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
void jump_to_linker(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
{
MESSAGE(LOG_DUMP, "Jump to linker (#%d) nolinker=%d\n", dyn->tablei, dyn->nolinker);
int i32;
MAYUSE(i32);
int j32;
MAYUSE(j32);
if(dyn->nolinker==2) {
jump_to_epilog(dyn, ip, reg, ninst);
} else {
@@ -217,18 +293,30 @@ void jump_to_linker(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
MOV32_(x1, (uintptr_t)table);
// TODO: This is not thread safe.
if(!ip) { // no IP, jump address in a reg, so need smart linker
#if 0
//version thread safe
MARK;
LDREXD(x1, x2); // load dest address in x2 and planned ip in x3
LDREXD(x2, x1); // load dest address in x2 and planned ip in x3
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
BXcond(cEQ, x2);
MOV32_(x2, (uintptr_t)arm_linker);
MOV_REG(x3, x12);
STREXD(x12, x1, x2); // nope, putting back linker & IP in place
STREXD(x12, x2, x1); // nope, putting back linker & IP in place
// x12 now contain success / falure for write
CMPS_IMM8(x12, 1);
MOV_REG(x12, x3); // put back IP in place...
B_MARK(cEQ);
BX(x2); // go to linker
#else
// not thread safe, is that still ok?
LDRD_IMM8(x2, x1, 0);
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
BXcond(cEQ, x2);
MOV32_(x2, (uintptr_t)arm_linker);
MOV_REG(x3, x12);
STRD_IMM8(x2, x1, 0);
BX(x2);
#endif
} else {
LDR_IMM9(x2, x1, 0);
BX(x2); // jump
@@ -263,12 +351,12 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
dyn->tablei+=4; // smart linker
MOV32_(x1, (uintptr_t)table);
MARK;
LDREXD(x1, x2); // load dest address in x2 and planned ip in x3
LDREXD(x2, x1); // load dest address in x2 and planned ip in x3
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
BXcond(cEQ, x2);
MOV32_(x2, (uintptr_t)arm_linker);
MOV_REG(x3, x12);
STREXD(x12, x1, x2); // nope, putting back linker & IP in place
STREXD(x12, x2, x1); // nope, putting back linker & IP in place
// x12 now contain success / falure for write
CMPS_IMM8(x12, 1);
MOV_REG(x12, x3); // put back IP in place...
@@ -287,7 +375,12 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
#endif
MESSAGE(LOG_DUMP, "Retn epilog\n");
POP(xESP, 1<<xEIP);
ADD_IMM8(xESP, xESP, n);
if(n>0xff) {
MOVW(x1, n);
ADD_REG_LSL_IMM5(xESP, xESP, x1, 0);
} else {
ADD_IMM8(xESP, xESP, n);
}
cstack_pop(dyn, ninst, xEIP, x1, x2);
PASS3(void* epilog = arm_epilog);
MOV32_(x2, (uintptr_t)epilog);
@@ -306,12 +399,12 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
dyn->tablei+=4; // smart linker
MOV32_(x1, (uintptr_t)table);
MARK;
LDREXD(x1, x2); // load dest address in x2 and planned ip in x3
LDREXD(x2, x1); // load dest address in x2 and planned ip in x3
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
BXcond(cEQ, x2);
MOV32_(x2, (uintptr_t)arm_linker);
MOV_REG(x3, x12);
STREXD(x12, x1, x2); // nope, putting back linker & IP in place
STREXD(x12, x2, x1); // nope, putting back linker & IP in place
// x12 now contain success / falure for write
CMPS_IMM8(x12, 1);
MOV_REG(x12, x3); // put back IP in place...
@@ -331,7 +424,7 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
POP(xESP, 1<<x2);
STRH_REG(x2, xEmu, x1);
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[_CS]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_serial[_CS]));
// POP EFLAGS
POP(xESP, (1<<x1));
CALL(arm_popf, -1, (1<<xEIP));
@@ -364,12 +457,14 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t
void grab_tlsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg)
{
MESSAGE(LOG_DUMP, "Get TLSData\n");
//int32_t i32;
//MAYUSE(i32);
//LDR_IMM9(x12, xEmu, offsetof(x86emu_t, segs_clean[_GS]));
//CMPS_IMM8(x12, 1);
//LDR_IMM9_COND(cEQ, reg, xEmu, offsetof(x86emu_t, segs_offs[_GS]));
//B_MARKSEG(cEQ);
int32_t j32;
MAYUSE(j32);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, context));
LDR_IMM9(x12, xEmu, offsetof(x86emu_t, segs_serial[_GS])); // complete check here
LDR_IMM9(x1, x1, offsetof(box86context_t, sel_serial));
CMPS_REG_LSL_IMM5(x12, x1, 0);
LDR_IMM9_COND(cEQ, reg, xEmu, offsetof(x86emu_t, segs_offs[_GS]));
B_MARKSEG(cEQ);
MOVW(x1, _GS);
call_c(dyn, ninst, GetSegmentBaseEmu, 12, reg, 0);
MARKSEG;
@@ -378,61 +473,19 @@ void grab_tlsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg)
void grab_fsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg)
{
int32_t i32;
MAYUSE(i32);
int32_t j32;
MAYUSE(j32);
MESSAGE(LOG_DUMP, "Get FS: Offset\n");
LDR_IMM9(x12, xEmu, offsetof(x86emu_t, segs_clean[_FS]));
CMPS_IMM8(x12, 1);
LDR_IMM9_COND(cEQ, reg, xEmu, offsetof(x86emu_t, segs_offs[_FS]));
B_MARKSEG(cEQ);
LDR_IMM9(x12, xEmu, offsetof(x86emu_t, segs_serial[_FS]));// fast check here
CMPS_IMM8(x12, 0);
LDR_IMM9_COND(cNE, reg, xEmu, offsetof(x86emu_t, segs_offs[_FS]));
B_MARKSEG(cNE);
MOVW(x1, _FS);
call_c(dyn, ninst, GetSegmentBaseEmu, 12, reg, 0);
MARKSEG;
MESSAGE(LOG_DUMP, "----FS: Offset\n");
}
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn)
{
if(!addr)
return 0;
if(PK(0)==0xff && PK(1)==0x25) { // absolute jump, maybe the GOT
uintptr_t a1 = (PK32(2)); // need to add a check to see if the address is from the GOT !
addr = *(uint32_t*)a1;
}
if(addr<0x10000) // too low, that is suspicious
return 0;
onebridge_t *b = (onebridge_t*)(addr);
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0) {
// found !
if(retn) *retn = (b->C3==0xC2)?b->N:0;
if(calladdress) *calladdress = addr+1;
return 1;
}
return 0;
}
// emit "lock", x1, x2 and x3 are lost
void emit_lock(dynarec_arm_t* dyn, uintptr_t addr, int ninst)
{
PUSH(xSP, (1<<xEmu)); // save Emu
LDR_IMM9(xEmu, xEmu, offsetof(x86emu_t, context));
MOV32(x1, offsetof(box86context_t, mutex_lock)); // offset is way to big for imm8
ADD_REG_LSL_IMM5(xEmu, xEmu, x1, 0);
CALL(pthread_mutex_lock, -2, 0);
POP(xSP, (1<<xEmu));
}
// emit "unlock", x1, x2 and x3 are lost
void emit_unlock(dynarec_arm_t* dyn, uintptr_t addr, int ninst)
{
PUSH(xSP, (1<<xEmu)); // save Emu
LDR_IMM9(xEmu, xEmu, offsetof(x86emu_t, context));
MOV32(x1, offsetof(box86context_t, mutex_lock)); // offset is way to big for imm8
ADD_REG_LSL_IMM5(xEmu, xEmu, x1, 0);
CALL(pthread_mutex_unlock, -2, 0);
POP(xSP, (1<<xEmu));
}
// x87 stuffs
static void x87_reset(dynarec_arm_t* dyn, int ninst)
{
@@ -547,8 +600,13 @@ static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3
if(a>0) {
// new tag to fulls
MOVW(s3, 0);
MOVW(s1, offsetof(x86emu_t, p_regs));
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
int offs = offsetof(x86emu_t, p_regs);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
MOVW(s1, offs);
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
for (int i=0; i<a; ++i) {
SUB_IMM8(s2, s2, 1);
AND_IMM8(s2, s2, 7); // (emu->top + st)&7
@@ -557,8 +615,13 @@ static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3
} else {
// empty tags
MOVW(s3, 0b11);
MOVW(s1, offsetof(x86emu_t, p_regs));
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
int offs = offsetof(x86emu_t, p_regs);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
MOVW(s1, offsetof(x86emu_t, p_regs));
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
for (int i=0; i<-a; ++i) {
STR_REG_LSL_IMM5(s3, s1, s2, 2); // empty slot before leaving it
ADD_IMM8(s2, s2, 1);
@@ -839,8 +902,13 @@ int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
if(dyn->mmxcache[a]!=-1)
return dyn->mmxcache[a];
int ret = dyn->mmxcache[a] = fpu_get_reg_double(dyn);
MOV32(s1, offsetof(x86emu_t, mmx[a]));
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
int offs = offsetof(x86emu_t, mmx[a]);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
MOV32(s1, offs);
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
VLD1_32(ret, s1);
return ret;
#else
@@ -868,8 +936,13 @@ static void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
if(dyn->mmxcache[i]!=-1) {
if (old==-1) {
MESSAGE(LOG_DUMP, "\tPurge MMX Cache ------\n");
MOV32(s1, offsetof(x86emu_t, mmx[i]));
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
int offs = offsetof(x86emu_t, mmx[i]);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
MOV32(s1, offs);
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
old = i+1; //+1 because VST1 with write back
} else {
if(old!=i) {
@@ -894,8 +967,13 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
for (int i=0; i<8; ++i)
if(dyn->mmxcache[i]!=-1) {
if (old==-1) {
MOV32(s1, offsetof(x86emu_t, mmx[i]));
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
int offs = offsetof(x86emu_t, mmx[i]);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
MOV32(s1, offs);
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
old = i+1;
} else {
if(old!=i) {
@@ -925,8 +1003,13 @@ int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
if(dyn->ssecache[a]!=-1)
return dyn->ssecache[a];
int ret = dyn->ssecache[a] = fpu_get_reg_quad(dyn);
MOV32(s1, offsetof(x86emu_t, xmm[a]));
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
int offs = offsetof(x86emu_t, xmm[a]);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, (offs>>2), 0xf);
} else {
MOV32(s1, offs);
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
VLD1Q_32(ret, s1);
return ret;
#else
@@ -954,8 +1037,13 @@ static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
if(dyn->ssecache[i]!=-1) {
if (old==-1) {
MESSAGE(LOG_DUMP, "\tPurge SSE Cache ------\n");
MOV32(s1, offsetof(x86emu_t, xmm[i]));
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
int offs = offsetof(x86emu_t, xmm[i]);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
MOV32(s1, offs);
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
old = i+1; //+1 because VST1Q with write back
} else {
if(old!=i) {
@@ -980,8 +1068,13 @@ static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
for (int i=0; i<8; ++i)
if(dyn->ssecache[i]!=-1) {
if (old==-1) {
MOV32(s1, offsetof(x86emu_t, xmm[i]));
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
int offs = offsetof(x86emu_t, xmm[i]);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
MOV32(s1, offs);
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
old = i+1;
} else {
if(old!=i) {
+52 -27
View File
@@ -132,6 +132,21 @@
wb1 = 1; \
ed = i; \
}
//GETEBO will use i for ed, i is also Offset, and can use r3 for wback.
#define GETEBO(i) if((nextop&0xC0)==0xC0) { \
wback = (nextop&7); \
wb2 = (wback>>2); \
wback = xEAX+(wback&3); \
UXTB(i, wback, wb2); \
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0); \
ADD_REG_LSL_IMM5(wback, wback, i, 0); \
LDRB_IMM9(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
}
//GETSEB sign extend EB, will use i for ed, and can use r3 for wback.
#define GETSEB(i) if((nextop&0xC0)==0xC0) { \
wback = (nextop&7); \
@@ -186,31 +201,38 @@
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = (uintptr_t)dyn->arm_size;}
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = (uintptr_t)dyn->arm_size;}
#define GETMARKLOCK ((dyn->insts)?dyn->insts[ninst].marklock:(dyn->arm_size+4))
// Branch to MARK if cond (use i32)
// Branch to MARK if cond (use j32)
#define B_MARK(cond) \
i32 = GETMARK-(dyn->arm_size+8); \
Bcond(cond, i32)
// Branch to MARK2 if cond (use i32)
j32 = GETMARK-(dyn->arm_size+8); \
Bcond(cond, j32)
// Branch to MARK2 if cond (use j32)
#define B_MARK2(cond) \
i32 = GETMARK2-(dyn->arm_size+8); \
Bcond(cond, i32)
// Branch to MARK3 if cond (use i32)
j32 = GETMARK2-(dyn->arm_size+8); \
Bcond(cond, j32)
// Branch to MARK3 if cond (use j32)
#define B_MARK3(cond) \
i32 = GETMARK3-(dyn->arm_size+8); \
Bcond(cond, i32)
// Branch to next instruction if cond (use i32)
j32 = GETMARK3-(dyn->arm_size+8); \
Bcond(cond, j32)
// Branch to next instruction if cond (use j32)
#define B_NEXT(cond) \
i32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size+8)):0; \
Bcond(cond, i32)
// Branch to MARKSEG if cond (use i32)
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size+8)):0; \
Bcond(cond, j32)
// Branch to MARKSEG if cond (use j32)
#define B_MARKSEG(cond) \
i32 = GETMARKSEG-(dyn->arm_size+8); \
Bcond(cond, i32)
j32 = GETMARKSEG-(dyn->arm_size+8); \
Bcond(cond, j32)
// Branch to MARKLOCK if cond (use j32)
#define B_MARKLOCK(cond) \
j32 = GETMARKLOCK-(dyn->arm_size+8); \
Bcond(cond, j32)
#define IFX(A) if(dyn->insts && (dyn->insts[ninst].x86.need_flags&(A)))
#define IFXX(A) if(dyn->insts && (dyn->insts[ninst].x86.need_flags==(A)))
#define IFX2X(A, B) if(dyn->insts && (dyn->insts[ninst].x86.need_flags==(A) || dyn->insts[ninst].x86.need_flags==(B) || dyn->insts[ninst].x86.need_flags==((A)|(B))))
#define IFXN(A, B) if(dyn->insts && (dyn->insts[ninst].x86.need_flags&(A) && !(dyn->insts[ninst].x86.need_flags&(B))))
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
#define FCOM(s1, s2) \
@@ -261,12 +283,12 @@
#ifndef READFLAGS
#define READFLAGS(A) \
if(dyn->state_flags!=SF_SET) { \
if(((A)!=X_PEND) && dyn->state_flags!=SF_SET) { \
if(dyn->state_flags!=SF_PENDING) { \
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, df)); \
TSTS_REG_LSL_IMM5(x3, x3, 0); \
i32 = (GETMARKF)-(dyn->arm_size+8); \
Bcond(cEQ, i32); \
j32 = (GETMARKF)-(dyn->arm_size+8); \
Bcond(cEQ, j32); \
} \
CALL_(UpdateFlags, -1, 0); \
MARKF; \
@@ -301,11 +323,13 @@
#define NEW_BARRIER_INST
#endif
// Emit the LOCK mutex (x1, x2 and x3 are lost)
#define LOCK emit_lock(dyn, addr, ninst)
// Emit the UNLOCK mutex (x1, x2 and x3 are lost)
#define UNLOCK emit_unlock(dyn, addr, ninst)
#if STEP < 2
#define PASS2IF(A, B) if(A)
#elif STEP == 2
#define PASS2IF(A, B) if(A) dyn->insts[ninst].pass2choice = B; if(dyn->insts[ninst].pass2choice == B)
#else
#define PASS2IF(A, B) if(dyn->insts[ninst].pass2choice == B)
#endif
void arm_epilog();
void* arm_linker(x86emu_t* emu, void** table, uintptr_t addr);
@@ -339,6 +363,7 @@ void* arm_linker(x86emu_t* emu, void** table, uintptr_t addr);
#define geted STEPNAME(geted_)
#define fakeed STEPNAME(fakeed_)
#define geted16 STEPNAME(geted16_)
#define jump_to_epilog STEPNAME(jump_to_epilog_)
#define jump_to_linker STEPNAME(jump_to_linker_)
#define ret_to_epilog STEPNAME(ret_to_epilog_)
@@ -347,9 +372,6 @@ void* arm_linker(x86emu_t* emu, void** table, uintptr_t addr);
#define call_c STEPNAME(call_c_)
#define grab_fsdata STEPNAME(grab_fsdata_)
#define grab_tlsdata STEPNAME(grab_tlsdata_)
#define isNativeCall STEPNAME(isNativeCall_)
#define emit_lock STEPNAME(emit_lock)
#define emit_unlock STEPNAME(emit_unlock)
#define emit_cmp8 STEPNAME(emit_cmp8)
#define emit_cmp16 STEPNAME(emit_cmp16)
#define emit_cmp32 STEPNAME(emit_cmp32)
@@ -454,6 +476,10 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
/* setup r2 to address pointed by */
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixedaddress, uint32_t absmax, uint32_t mask);
// generic x86 helper
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
void jump_to_linker(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
@@ -463,7 +489,6 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst);
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t mask);
void grab_fsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
void grab_tlsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
void emit_lock(dynarec_arm_t* dyn, uintptr_t addr, int ninst);
void emit_unlock(dynarec_arm_t* dyn, uintptr_t addr, int ninst);
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
+5 -5
View File
@@ -48,13 +48,13 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
#ifdef HAVE_TRACE
if(my_context->dec && box86_dynarec_trace) {
if((trace_end == 0)
|| ((ip >= trace_start) && (ip <= trace_end))) {
|| ((ip >= trace_start) && (ip < trace_end))) {
MESSAGE(LOG_DUMP, "TRACE ----\n");
fpu_reflectcache(dyn, ninst, x1, x2, x3);
MOV32(1, ip);
STM(0, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11));
STR_IMM9(1, 0, offsetof(x86emu_t, ip));
MOV32(2, 1);
MOV32(x1, ip);
STM(xEmu, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, ip));
MOVW(x2, 1);
CALL(PrintTrace, -1, 0);
MESSAGE(LOG_DUMP, "----------\n");
}
+6 -3
View File
@@ -12,11 +12,14 @@
#define DEFAULT \
--dyn->size; \
*ok = -1; \
dynarec_log(LOG_INFO, "%p: Dynarec stopped because of Opcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X (%s)\n", \
if(box86_dynarec_log>=LOG_INFO) {\
dynarec_log(LOG_NONE, "%p: Dynarec stopped because of Opcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
(void*)ip, PKip(0), \
PKip(1), PKip(2), PKip(3), \
PKip(4), PKip(5), PKip(6), \
PKip(7), PKip(8), PKip(9), \
PKip(10),PKip(11),PKip(12), \
PKip(13),PKip(14), \
GetNativeName((void*)addr))
PKip(13),PKip(14)); \
printFunctionAddr(ip, " => "); \
dynarec_log(LOG_NONE, "\n"); \
}
+1 -1
View File
@@ -8,7 +8,7 @@
#define SETFLAGS(A,B) {dyn->insts[ninst].x86.set_flags = A; dyn->insts[ninst].x86.state_flags = B;}
#define JUMP(A) dyn->insts[ninst].x86.jmp = A
#define BARRIER(A) dyn->insts[ninst].x86.barrier = A
#define BARRIER_NEXT(A) if(ninst+1<dyn->size) dyn->insts[ninst+1].x86.barrier = A
#define BARRIER_NEXT(A) if(ninst<dyn->size) dyn->insts[ninst+1].x86.barrier = A
#define NEW_INST \
dyn->insts[ninst].x86.addr = ip; \
+3 -2
View File
@@ -2,8 +2,9 @@
#define FINI
#define EMIT(A) \
if(box86_dynarec_dump) {dynarec_log(LOG_NONE, "\t%08x\t%s\n", (A), arm_print(A));} \
*(uint32_t*)(dyn->block) = A; \
dyn->block += 4; dyn->arm_size += 4
*(uint32_t*)(dyn->block) = A; \
dyn->block += 4; dyn->arm_size += 4;\
dyn->insts[ninst].size2 += 4
#define MESSAGE(A, ...) if(box86_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
#define NEW_INST
+6
View File
@@ -10,9 +10,14 @@ typedef struct instruction_arm_s {
uintptr_t address; // (start) address of the arm emited instruction
uintptr_t epilog; // epilog of current instruction (can be start of next, of barrier stuff)
int size; // size of the arm emited instruction
int size2; // size of the arm emited instrucion after pass2
uintptr_t mark, mark2, mark3;
uintptr_t markf;
uintptr_t markseg;
uintptr_t marklock;
int pass2choice;// value for choices that are fixed on pass2 for pass3
uintptr_t natcall;
int retn;
} instruction_arm_t;
typedef struct dynarec_arm_s {
@@ -35,6 +40,7 @@ typedef struct dynarec_arm_s {
int fpuused[24];// all 8..31 double reg from fpu, used by x87, sse and mmx
int x87stack; // cache stack counter
int fpu_scratch;// scratch counter
int fpu_extra_qscratch; // some opcode need an extra quad scratch register
int fpu_reg; // x87/sse/mmx reg counter
int nolinker; // disable use of (smart) linker in the block
uintptr_t* next; // variable array of "next" jump address
+13 -13
View File
@@ -8,10 +8,10 @@ NEON 1 1 1 1 0 0 1 0 0 D 1 1 Vn Vd 0 0 0 1 N Q M 1 Vm VORN<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D @<2> Vn Vd 0 0 0 1 N Q M 1 Vm @ param=0b00=0b01=0b10 const char* op op,"EOR","BSL","BIT","BIF"@ @ V\op\<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 0 N Q M 1 Vm VQSUB<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 1 N Q M op Vm @ op=0 const char* strict strict,"T","E"@ @ VCG\strict\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 0 Vm VSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 1 Vm VQSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 0 Vm VRSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 1 Vm VQRSHL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 0 Vm VSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 1 Vm VQSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 0 Vm VRSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 1 Vm VQRSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 0 N Q M op Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ V\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 0 Vm VABD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 1 Vm VABA<c>.<dt> <Qd>, <Qn>, <Qm>
@@ -50,12 +50,12 @@ NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x1 0 Q op/=1 1 imm4 BIC<c>.<dt>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=110x 0 Q op/=1 1 imm4 VMVN<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=1110 0 Q op/=1 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 0 0 0 <11> 0 <2> 1 <4>
NEON 1 1 1 1 0 0 1 0 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S8 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 0 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S16 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 0 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U8 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U16 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 0 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S8 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S16 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S32 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U8 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U16 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U32 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 0 L Q M 1 Vm VSHR<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 1 L Q M 1 Vm VSRA<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 1 0 L Q M 1 Vm VRSHR<c>.<dt> <Qd>, <Qm>, #<imm>
@@ -64,7 +64,7 @@ NEON 1 1 1 1 0 0 1 1 1 D imm6 Vd 0 1 0 0 L Q M 1 Vm VSRI<c>.<size> <Qd>, <Qm>, #
NEON 1 1 1 1 0 0 1 0 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSHL<c>.I<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 1 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSLI<c>.<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D Imm6 Vd 0 1 1 op L Q M 1 Vm VQSHL\((u & op) ? "U" : "")\<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 0 M 1 Vm VSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 0 M 1 Vm @ set ++size@ @ VSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 1 M 1 Vm VRSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 0 M 1 Vm VQSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 1 M 1 Vm VQRSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
@@ -104,7 +104,7 @@ NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 0 Q M 0 Vm VUZP<c>.\%d8 &l&l si
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 1 Q M 0 Vm VZIP<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 0 M 0 Vm VMOVN<c>.<dt> <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 1 M 0 Vm VQMOVUN<c>.S\%d16 &l&l size\ <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 1 U M 0 Vm @ set u = 1 - u@ set ++size@ @ VQMOVN<c>.<dt> <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 1 U M 0 Vm @ set ++size@ @ VQMOVN<c>.<dt> <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 1 0 0 M 0 Vm VSHLL<c>.I\%d8 &l&l size\ <Qd>, <Dm>, #\%d8 &l&l size\
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 0 0 0 M 0 Vm VCVT<c>.F16.F32 <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 1 0 0 M 0 Vm VCVT<c>.F32.F16 <Qd>, <Dm>
@@ -445,7 +445,7 @@ VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 1 1 (0) (0) (0) (0) VDUP<c>.16 <Qd>,
VFPU cond 1 1 1 0 1 1 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.8 <Qd>, <Rt>
VFPU cond 1 1 1 0 0 0 0 1 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Rt>, <Sn>
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> <Rt>, FPSCR
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 3) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 4) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 1 <4>
VFPU cond 1 1 1 0 0 D 0 0 Vn Vd 1 0 1 sz N op M 0 Vm VML\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 0 1 Vn Vd 1 0 1 sz N op M 0 Vm VNML\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
+6
View File
@@ -40,6 +40,7 @@ const char* DumpSection(Elf32_Shdr *s, char* SST) {
GO(SHT_HIPROC);
GO(SHT_LOUSER);
GO(SHT_HIUSER);
#ifdef SHT_GNU_versym
GO(SHT_GNU_versym);
GO(SHT_GNU_ATTRIBUTES);
GO(SHT_GNU_HASH);
@@ -51,6 +52,7 @@ const char* DumpSection(Elf32_Shdr *s, char* SST) {
GO(SHT_SUNW_syminfo);
GO(SHT_GNU_verdef);
GO(SHT_GNU_verneed);
#endif
#undef GO
default:
sprintf(buff, "0x%X unknown type", s->sh_type);
@@ -98,6 +100,7 @@ const char* DumpDynamic(Elf32_Dyn *s) {
GO(DT_RUNPATH, 0);
GO(DT_FLAGS, 0);
GO(DT_ENCODING, 0);
#ifdef DT_NUM
GO(DT_NUM, 0);
GO(DT_VALRNGLO, 0);
GO(DT_GNU_PRELINKED, 0);
@@ -133,6 +136,7 @@ const char* DumpDynamic(Elf32_Dyn *s) {
GO(DT_VERNEEDNUM, 0);
GO(DT_AUXILIARY, 0);
GO(DT_FILTER, 0);
#endif
#undef GO
default:
sprintf(buff, "0x%X unknown type", s->d_tag);
@@ -154,11 +158,13 @@ const char* DumpPHEntry(Elf32_Phdr *e)
GO(PT_SHLIB);
GO(PT_PHDR);
GO(PT_TLS);
#ifdef PT_NUM
GO(PT_NUM);
GO(PT_LOOS);
GO(PT_GNU_EH_FRAME);
GO(PT_GNU_STACK);
GO(PT_GNU_RELRO);
#endif
#undef GO
default: sprintf(buff, "type: %x, Off=%x vaddr=%p paddr=%p filesz=%u memsz=%u flags=%x align=%u", e->p_type, e->p_offset, (void*)e->p_vaddr, (void*)e->p_paddr, e->p_filesz, e->p_memsz, e->p_flags, e->p_align); break;
}
+122 -82
View File
@@ -64,8 +64,10 @@ void FreeElfHeader(elfheader_t** head)
return;
elfheader_t *h = *head;
#ifdef DYNAREC
dynarec_log(LOG_INFO, "Free Dynarec block for %s\n", h->path);
FreeDynablockList(&h->blocks);
if(h->text) {
dynarec_log(LOG_INFO, "Free Dynarec block for %s\n", h->path);
cleanDBFromAddressRange(my_context, h->text, h->textsz, 1);
}
#endif
free(h->name);
free(h->path);
@@ -155,7 +157,7 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
if(head->vaddr) {
head->multiblock_n = 0; // count PHEntrie with LOAD
for (int i=0; i<head->numPHEntries; ++i)
if(head->PHEntries[i].p_type == PT_LOAD)
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags)
++head->multiblock_n;
head->multiblock_size = (uint32_t*)calloc(head->multiblock_n, sizeof(uint32_t));
head->multiblock_offs = (uintptr_t*)calloc(head->multiblock_n, sizeof(uintptr_t));
@@ -164,7 +166,7 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
head->memory = (char*)0xffffffff;
int n = 0;
for (int i=0; i<head->numPHEntries; ++i)
if(head->PHEntries[i].p_type == PT_LOAD) {
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) {
Elf32_Phdr * e = &head->PHEntries[i];
uintptr_t bstart = e->p_vaddr;
uint32_t bsize = e->p_memsz;
@@ -235,10 +237,6 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
head->tlsbase = AddTLSPartition(context, head->tlssize);
#ifdef DYNAREC
head->blocks = NewDynablockList((uintptr_t)GetBaseAddress(head), head->text + head->delta, head->textsz, 0, mainbin);
#endif
return 0;
}
@@ -266,7 +264,13 @@ int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
printf_log(LOG_NONE, "Fail to read PT_LOAD part #%d (size=%d)\n", i, e->p_filesz);
return 1;
}
}
#ifdef DYNAREC
if(e->p_flags & PF_X) {
dynarec_log(LOG_DEBUG, "Add ELF eXecutable Memory %p:%p\n", dest, (void*)e->p_memsz);
addDBFromAddressRange(context, (uintptr_t)dest, e->p_memsz, 0);
}
#endif
}
// zero'd difference between filesz and memsz
/*if(e->p_filesz != e->p_memsz)
memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz);*/ //block is already 0'd at creation
@@ -302,7 +306,7 @@ int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
if(e->p_filesz) {
ssize_t r = -1;
#ifdef DYNAREC
unprotectDB((uintptr_t)dest, e->p_filesz);
unprotectDB((uintptr_t)dest, e->p_memsz);
#endif
if((r=fread(dest, e->p_filesz, 1, f))!=1) {
printf_log(LOG_NONE, "Fail to (re)read PT_LOAD part #%d (dest=%p, size=%d, return=%d, feof=%d/ferror=%d/%s)\n", i, dest, e->p_filesz, r, feof(f), ferror(f), strerror(ferror(f)));
@@ -329,6 +333,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
uint32_t *p = (uint32_t*)(rel[i].r_offset + head->delta);
uintptr_t offs = 0;
uintptr_t end = 0;
uintptr_t tmp = 0;
elfheader_t* h_tls = head;
if(bind==STB_LOCAL) {
offs = sym->st_value + head->delta;
@@ -354,7 +359,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
switch(t) {
case R_386_NONE:
// can be ignored
printf_log(LOG_DEBUG, "Ignoring %s @%p (%p)\n", DumpRelType(t), p, (void*)(p?(*p):0));
printf_log(LOG_DUMP, "Ignoring %s @%p (%p)\n", DumpRelType(t), p, (void*)(p?(*p):0));
break;
case R_386_TLS_TPOFF:
// Negated offset in static TLS block
@@ -369,7 +374,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
}
if(h_tls) {
delta = *(int*)p;
printf_log(LOG_DEBUG, "Applying %s %s on %s @%p (%d -> %d)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, (int32_t)offs + h_tls->tlsbase);
printf_log(LOG_DUMP, "Applying %s %s on %s @%p (%d -> %d)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, (int32_t)offs + h_tls->tlsbase);
*p = (uint32_t)((int32_t)offs + h_tls->tlsbase);
} else {
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, (int32_t)offs);
@@ -382,7 +387,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
}
offs = (offs - (uintptr_t)p);
if(!offs)
printf_log(LOG_DEBUG, "Apply %s R_386_PC32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(*(uintptr_t*)p+offs));
printf_log(LOG_DUMP, "Apply %s R_386_PC32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(*(uintptr_t*)p+offs));
*p += offs;
break;
case R_386_GLOB_DAT:
@@ -396,12 +401,12 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
// return -1;
} else {
printf_log(LOG_DEBUG, "Apply %s R_386_GLOB_DAT @%p (%p -> %p) on sym=%s\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname);
printf_log(LOG_DUMP, "Apply %s R_386_GLOB_DAT @%p (%p -> %p) on sym=%s\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname);
*p = offs;
}
break;
case R_386_RELATIVE:
printf_log(LOG_DEBUG, "Apply %s R_386_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)((*p)+head->delta));
printf_log(LOG_DUMP, "Apply %s R_386_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)((*p)+head->delta));
*p += head->delta;
break;
case R_386_32:
@@ -409,7 +414,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_32 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
// return -1;
} else {
printf_log(LOG_DEBUG, "Apply %s R_386_32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+*(uint32_t*)p));
printf_log(LOG_DUMP, "Apply %s R_386_32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+*(uint32_t*)p));
*p += offs;
}
break;
@@ -427,7 +432,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
offs = getElfIndex(my_context, h_tls);
}
if(p) {
printf_log(LOG_DEBUG, "Apply %s %s @%p with sym=%s (%p -> %p)\n", "R_386_TLS_DTPMOD32", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
printf_log(LOG_DUMP, "Apply %s %s @%p with sym=%s (%p -> %p)\n", "R_386_TLS_DTPMOD32", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
*p = offs;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s or Elf not found, but R_386_TLS_DTPMOD32 Slot Offset is NULL \n", symname);
@@ -447,7 +452,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
offs = sym->st_value;
if(p) {
int tlsoffset = offs; // it's not an offset in elf memory
printf_log(LOG_DEBUG, "Apply %s R_386_TLS_DTPOFF32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)tlsoffset, (void*)offs);
printf_log(LOG_DUMP, "Apply %s R_386_TLS_DTPOFF32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)tlsoffset, (void*)offs);
*p = tlsoffset;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s found, but R_386_TLS_DTPOFF32 Slot Offset is NULL \n", symname);
@@ -455,7 +460,13 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
}
break;
case R_386_JMP_SLOT:
if(bind==STB_LOCAL) {
// apply immediatly for gobject closure marshal or for LOCAL binding. Also, apply immediatly if it doesn't jump in the got
tmp = (uintptr_t)(*p);
if (bind==STB_LOCAL
|| ((symname && strstr(symname, "g_cclosure_marshal_")==symname))
|| !tmp
|| !((tmp>=head->plt && tmp<head->plt_end) || (tmp>=head->gotplt && tmp<head->gotplt_end))
) {
if (!offs) {
if(bind==STB_WEAK) {
printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_386_JMP_SLOT @%p (%p)\n", symname, p, *(void**)p);
@@ -465,14 +476,14 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
// return -1;
} else {
if(p) {
printf_log(LOG_DEBUG, "Apply %s R_386_JMP_SLOT @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
printf_log(LOG_DUMP, "Apply %s R_386_JMP_SLOT @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
*p = offs;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname);
}
}
} else {
printf_log(LOG_DEBUG, "Preparing (if needed) %s R_386_JMP_SLOT @%p (0x%x->0x%0x) with sym=%s to be apply later\n", (bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname);
printf_log(LOG_DUMP, "Preparing (if needed) %s R_386_JMP_SLOT @%p (0x%x->0x%0x) with sym=%s to be apply later\n", (bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname);
*p += head->delta;
}
break;
@@ -483,13 +494,13 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head);
if(!offs)
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head); // get original copy if any
printf_log(LOG_DEBUG, "Apply %s R_386_COPY @%p with sym=%s, @%p size=%d (", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)offs, sym->st_size);
printf_log(LOG_DUMP, "Apply %s R_386_COPY @%p with sym=%s, @%p size=%d (", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)offs, sym->st_size);
memmove(p, (void*)offs, sym->st_size);
if(LOG_DEBUG<=box86_log) {
if(LOG_DUMP<=box86_log) {
uint32_t*k = (uint32_t*)p;
for (int i=0; i<((sym->st_size>128)?128:sym->st_size); i+=4, ++k)
printf_log(LOG_DEBUG, "%s0x%08X", i?" ":"", *k);
printf_log(LOG_DEBUG, "%s)\n", (sym->st_size>128)?" ...":"");
printf_log(LOG_DUMP, "%s0x%08X", i?" ":"", *k);
printf_log(LOG_DUMP, "%s)\n", (sym->st_size>128)?" ...":"");
}
} else {
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
@@ -522,7 +533,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head);
if(offs) {
// add r_addend to p?
printf_log(LOG_DEBUG, "Apply R_386_COPY @%p with sym=%s, @%p size=%d\n", p, symname, (void*)offs, sym->st_size);
printf_log(LOG_DUMP, "Apply R_386_COPY @%p with sym=%s, @%p size=%d\n", p, symname, (void*)offs, sym->st_size);
memcpy(p, (void*)(offs+rela[i].r_addend), sym->st_size);
} else {
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply RELA R_386_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
@@ -556,18 +567,6 @@ int RelocateElf(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
{
if(pltResolver==~0) {
pltResolver = AddBridge(my_context->system, vFE, PltResolver, 0);
}
if(head->pltgot) {
*(uintptr_t*)(head->pltgot+head->delta+8) = pltResolver;
*(uintptr_t*)(head->pltgot+head->delta+4) = (uintptr_t)head;
printf_log(LOG_DEBUG, "PLT Resolver injected in plt.got at %p\n", (void*)(head->pltgot+head->delta+8));
} else if(head->got) {
*(uintptr_t*)(head->got+head->delta+8) = pltResolver;
*(uintptr_t*)(head->got+head->delta+4) = (uintptr_t)head;
printf_log(LOG_DEBUG, "PLT Resolver injected in got at %p\n", (void*)(head->got+head->delta+8));
}
if(head->pltrel) {
int cnt = head->pltsz / head->pltent;
if(head->pltrel==DT_REL) {
@@ -581,6 +580,18 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
if(RelocateElfRELA(maplib, local_maplib, head, cnt, (Elf32_Rela *)(head->jmprel + head->delta)))
return -1;
}
if(pltResolver==~0) {
pltResolver = AddBridge(my_context->system, my_context, vFE, PltResolver, 0);
}
if(head->pltgot) {
*(uintptr_t*)(head->pltgot+head->delta+8) = pltResolver;
*(uintptr_t*)(head->pltgot+head->delta+4) = (uintptr_t)head;
printf_log(LOG_DEBUG, "PLT Resolver injected in plt.got at %p\n", (void*)(head->pltgot+head->delta+8));
} else if(head->got) {
*(uintptr_t*)(head->got+head->delta+8) = pltResolver;
*(uintptr_t*)(head->got+head->delta+4) = (uintptr_t)head;
printf_log(LOG_DEBUG, "PLT Resolver injected in got at %p\n", (void*)(head->got+head->delta+8));
}
}
return 0;
@@ -598,7 +609,8 @@ 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) {
if(h->SymTab[i].st_info == 18) { // TODO: this "18" is probably defined somewhere
int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
if(/*h->SymTab[i].st_info == 18*/type==STT_FUNC) { // TODO: this "18" is probably defined somewhere
const char * symname = h->StrTab+h->SymTab[i].st_name;
if(strcmp(symname, name)==0) {
return h->SymTab+i;
@@ -611,7 +623,8 @@ 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) {
if(h->SymTab[i].st_info == 16) {
int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
if(/*h->SymTab[i].st_info == 16*/type==STT_OBJECT) {
const char * symname = h->StrTab+h->SymTab[i].st_name;
if(strcmp(symname, name)==0) {
return h->SymTab+i;
@@ -672,8 +685,9 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
const char * symname = h->StrTab+h->SymTab[i].st_name;
int bind = ELF32_ST_BIND(h->SymTab[i].st_info);
int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
int vis = h->SymTab[i].st_other&0x3;
if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE)
&& (h->SymTab[i].st_other==0) && (h->SymTab[i].st_shndx!=0)) {
&& (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->SymTab[i].st_shndx!=0)) {
if(bind==10/*STB_GNU_UNIQUE*/ && FindGlobalSymbol(maplib, symname))
continue;
uintptr_t offs = (type==STT_TLS)?h->SymTab[i].st_value:(h->SymTab[i].st_value + h->delta);
@@ -695,9 +709,10 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
const char * symname = h->DynStr+h->DynSym[i].st_name;
int bind = ELF32_ST_BIND(h->DynSym[i].st_info);
int type = ELF32_ST_TYPE(h->DynSym[i].st_info);
int vis = h->DynSym[i].st_other&0x3;
//st_shndx==65521 means ABS value
if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE)
&& (h->DynSym[i].st_other==0) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) {
&& (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) {
if(bind==10/*STB_GNU_UNIQUE*/ && FindGlobalSymbol(maplib, symname))
continue;
uintptr_t offs = (type==STT_TLS)?h->DynSym[i].st_value:(h->DynSym[i].st_value + h->delta);
@@ -755,7 +770,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int
printf_log(LOG_INFO, "BOX86: Warning, RPATH with $ variable not supported yet (%s)\n", rpath);
} else {
printf_log(LOG_DEBUG, "Prepending path \"%s\" to BOX86_LD_LIBRARY_PATH\n", rpath);
PrependPath(rpath, &box86->box86_ld_lib, 1);
PrependList(&box86->box86_ld_lib, rpath, 1);
}
if(rpath!=rpathref)
free(rpath);
@@ -778,12 +793,27 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int
return 0;
}
int ElfCheckIfUseTCMallocMinimal(elfheader_t* h)
{
if(!h)
return 0;
for (int 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
return 1;
else
return 0;
}
return 0;
}
void RunElfInit(elfheader_t* h, x86emu_t *emu)
{
if(!h || h->init_done)
return;
// reset Segs Cache
memset(emu->segs_clean, 0, sizeof(emu->segs_clean));
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
uintptr_t p = h->initentry + h->delta;
box86context_t* context = GetEmuContext(emu);
if(context->deferedInit) {
@@ -971,30 +1001,23 @@ void* GetTLSPointer(box86context_t* context, elfheader_t* h)
#ifdef DYNAREC
dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr)
{
// this is one is fast, so start with that
dynablocklist_t* ret = getDBFromAddress(addr);
// if we are here, the there is not block in standard "space"
/*dynablocklist_t* ret = getDBFromAddress(addr);
if(ret) {
return ret;
}*/
if(box86_dynarec_forced) {
addDBFromAddressRange(my_context, addr, 1, 1);
return my_context->dynmap[addr>>DYNAMAP_SHIFT];
}
// nope, then find in elfs
elfheader_t* elf = FindElfAddress(context, addr);
if(!elf) {
// still nope
if(addr>0x100)
if((*(uint8_t*)addr)==0xCC || (((*(uint8_t*)addr)==0xC3 || (*(uint8_t*)addr)==0xC2) && (*(uint8_t*)(addr-11))==0xCC) )
return context->dynablocks;
if(box86_dynarec_forced)
return context->dynablocks;
dynarec_log(LOG_INFO, "Address %p not found in Elf memory and is not a native call wrapper\n", (void*)addr);
//check if address is in an elf... if yes, grant a block (should I warn)
Dl_info info;
if(dladdr((void*)addr, &info)) {
dynarec_log(LOG_INFO, "Address %p is in a native Elf memory space (function \"%s\" in %s)\n", (void*)addr, info.dli_sname, info.dli_fname);
return NULL;
}
return elf->blocks;
}
dynablocklist_t* GetDynablocksFromElf(elfheader_t* h)
{
if(!h)
return NULL;
return h->blocks;
dynarec_log(LOG_INFO, "Address %p not found in Elf memory and is not a native call wrapper\n", (void*)addr);
return NULL;
}
#endif
@@ -1005,29 +1028,49 @@ typedef struct my_dl_phdr_info_s {
int dlpi_phnum;
} my_dl_phdr_info_t;
static int dl_iterate_phdr_callback(x86emu_t *emu, my_dl_phdr_info_t *info, size_t size, void* data)
static int dl_iterate_phdr_callback(x86emu_t *emu, void* F, my_dl_phdr_info_t *info, size_t size, void* data)
{
SetCallbackArgs(emu, 2, info, size);
int ret = RunCallback(emu);
int ret = RunFunctionWithEmu(emu, 0, (uintptr_t)F, 3, info, size, data);
return ret;
}
static int dl_iterate_phdr_native(struct dl_phdr_info* info, size_t size, void* data)
{
if(!info->dlpi_name)
return 0;
if(!info->dlpi_name[0]) // don't send informations about box86 itself
return 0;
#define SUPER() \
GO(0) \
GO(1) \
GO(2) \
GO(3) \
GO(4)
x86emu_t* emu = (x86emu_t*)data;
SetCallbackArgs(emu, 2, info, size);
int ret = RunCallback(emu);
return ret;
// dl_iterate_phdr ...
#define GO(A) \
static uintptr_t my_dl_iterate_phdr_fct_##A = 0; \
static int my_dl_iterate_phdr_##A(struct dl_phdr_info* a, size_t b, void* c)\
{ \
if(!a->dlpi_name) \
return 0; \
if(!a->dlpi_name[0]) /*don't send informations about box86 itself*/ \
return 0; \
return RunFunction(my_context, my_dl_iterate_phdr_fct_##A, 3, a, b, c); \
}
SUPER()
#undef GO
static void* find_dl_iterate_phdr_Fct(void* fct)
{
if(!fct) return fct;
if(GetNativeFnc((uintptr_t)fct)) return GetNativeFnc((uintptr_t)fct);
#define GO(A) if(my_dl_iterate_phdr_fct_##A == (uintptr_t)fct) return my_dl_iterate_phdr_##A;
SUPER()
#undef GO
#define GO(A) if(my_dl_iterate_phdr_fct_##A == 0) {my_dl_iterate_phdr_fct_##A = (uintptr_t)fct; return my_dl_iterate_phdr_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for elfloader dl_iterate_phdr callback\n");
return NULL;
}
#undef SUPER
EXPORT int my_dl_iterate_phdr(x86emu_t *emu, void* F, void *data) {
printf_log(LOG_INFO, "Warning: call to partially implemented dl_iterate_phdr(%p, %p)\n", F, data);
x86emu_t* cbemu = AddSharedCallback(emu, (uintptr_t)F, 3, NULL, NULL, data, NULL);
box86context_t *context = GetEmuContext(emu);
const char* empty = "";
int ret = 0;
@@ -1037,15 +1080,12 @@ EXPORT int my_dl_iterate_phdr(x86emu_t *emu, void* F, void *data) {
info.dlpi_name = idx?context->elfs[idx]->name:empty; //1st elf is program, and this one doesn't get a name
info.dlpi_phdr = context->elfs[idx]->PHEntries;
info.dlpi_phnum = context->elfs[idx]->numPHEntries;
if((ret = dl_iterate_phdr_callback(cbemu, &info, sizeof(info), data))) {
FreeCallback(cbemu);
if((ret = dl_iterate_phdr_callback(emu, F, &info, sizeof(info), data))) {
return ret;
}
}
// and now, go on native version
ret = dl_iterate_phdr(dl_iterate_phdr_native, cbemu);
// all done
FreeCallback(cbemu);
ret = dl_iterate_phdr(find_dl_iterate_phdr_Fct(F), data);
return ret;
}
+5 -3
View File
@@ -52,8 +52,12 @@ struct elfheader_s {
int pltent;
uint32_t pltrel;
uintptr_t gotplt;
uintptr_t gotplt_end;
uintptr_t pltgot;
uintptr_t got;
uintptr_t got_end;
uintptr_t plt;
uintptr_t plt_end;
uintptr_t text;
int textsz;
@@ -76,9 +80,7 @@ struct elfheader_s {
uintptr_t* multiblock_offs;
uint32_t* multiblock_size;
int multiblock_n;
#ifdef DYNAREC
dynablocklist_t *blocks;
#endif
library_t *lib;
needed_libs_t *neededlibs;
};
+14 -5
View File
@@ -61,8 +61,9 @@ void LoadNamedSection(FILE *f, Elf32_Shdr *s, int size, char* SHStrTab, const ch
elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
{
Elf32_Ehdr header;
int level = (exec)?LOG_INFO:LOG_DEBUG;
if(fread(&header, sizeof(Elf32_Ehdr), 1, f)!=1) {
printf_log(LOG_INFO, "Cannot read ELF Header\n");
printf_log(level, "Cannot read ELF Header\n");
return NULL;
}
if(memcmp(header.e_ident, ELFMAG, SELFMAG)!=0) {
@@ -96,7 +97,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
}
if(header.e_machine != EM_386) {
printf_log(LOG_INFO, "Not an i386 ELF (%d)\n", header.e_machine);
printf_log(level, "Not an i386 ELF (%d)\n", header.e_machine);
return NULL;
}
@@ -119,7 +120,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->numPHEntries = header.e_phnum;
h->numSHEntries = header.e_shnum;
h->SHIdx = header.e_shstrndx;
if(header.e_shentsize!=0) {
if(header.e_shentsize && header.e_shnum) {
// special cases for nums
if(h->numSHEntries == 0) {
printf_log(LOG_DEBUG, "Read number of Sections in 1st Section\n");
@@ -159,7 +160,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
return NULL;
}
if(header.e_shentsize!=0) {
if(header.e_shentsize && header.e_shnum) {
if(h->SHIdx == SHN_XINDEX) {
printf_log(LOG_DEBUG, "Read number of String Table in 1st Section\n");
h->SHIdx = h->SHEntries[0].sh_link;
@@ -253,12 +254,20 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
int ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".got.plt");
if(ii) {
h->gotplt = h->SHEntries[ii].sh_addr;
h->gotplt_end = h->gotplt + h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The GOT.PLT Table is at address %p\n", (void*)h->gotplt);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".got");
if(ii) {
h->got = h->SHEntries[ii].sh_addr;
printf_log(LOG_DEBUG, "The GOT Table is at address %p\n", (void*)h->got);
h->got_end = h->got + h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The GOT Table is at address %p..%p\n", (void*)h->got, (void*)h->got_end);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".plt");
if(ii) {
h->plt = h->SHEntries[ii].sh_addr;
h->plt_end = h->plt + h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The PLT Table is at address %p..%p\n", (void*)h->plt, (void*)h->plt_end);
}
// look for .init entry point
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".init");
+57
View File
@@ -47,6 +47,52 @@
base+=(nextop&0x80)?(F32S):(F8S); \
A = (T*)(base+O); \
}
#define getecommon16(A, T) \
{ \
uint32_t m = nextop&0xC7; \
uint32_t base = 0; \
switch(m&7) { \
case 0: base = R_BX+R_SI; break; \
case 1: base = R_BX+R_DI; break; \
case 2: base = R_BP+R_SI; break; \
case 3: base = R_BP+R_DI; break; \
case 4: base = R_SI; break; \
case 5: base = R_DI; break; \
case 6: base = R_BP; break; \
case 7: base = R_BX; break; \
} \
switch((m>>6)&3) { \
case 0: if(m==6) base = F16; break; \
case 1: base += F8S; break; \
case 2: base += F16S; break; \
} \
A = (T*)base; \
}
#define getecommon16o(A, T, O) \
{ \
uint32_t m = nextop&0xC7; \
uint32_t base = 0; \
switch(m&7) { \
case 0: base = R_BX+R_SI; break; \
case 1: base = R_BX+R_DI; break; \
case 2: base = R_BP+R_SI; break; \
case 3: base = R_BP+R_DI; break; \
case 4: base = R_SI; break; \
case 5: base = R_DI; break; \
case 6: base = R_BP; break; \
case 7: base = R_BX; break; \
} \
switch((m>>6)&3) { \
case 0: if(m==6) base = F16; break; \
case 1: base += F8S; break; \
case 2: base += F16S; break; \
} \
A = (T*)(base+O); \
}
#define geteb(A) \
if((nextop&0xC0)==0xC0) { \
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
@@ -71,6 +117,15 @@
if((nextop&0xC0)==0xC0) { \
A = &emu->xmm[(nextop&7)]; \
} else getecommon(A, sse_regs_t)
#define getew16(A) \
if((nextop&0xC0)==0xC0) { \
A = &emu->regs[(nextop&7)]; \
} else getecommon16(A, reg32_t)
#define getew16o(A, O) \
if((nextop&0xC0)==0xC0) { \
A = &emu->regs[(nextop&7)]; \
} else getecommon16o(A, reg32_t, O)
// Macros for ModR/M gets
#define GET_EB geteb(oped)
#define GET_ED geted(oped)
@@ -78,6 +133,8 @@
#define GET_EB_OFFS(o) getebo(oped, o)
#define GET_EM getem(opem)
#define GET_EX getex(opex)
#define GET_EW16 getew16(oped)
#define GET_EW16_OFFS(o) getew16o(oped, o)
#define EB oped
#define ED oped
#define EM opem
+101 -20
View File
@@ -15,6 +15,18 @@
goto _default;
}
NEXT;
_0f_0x01:
nextop = F8;
switch((nextop>>3)&7) {
case 4: /* SMSW Ew */
GET_ED;
// dummy for now... Do I need to track CR0 state?
ED->word[0] = (1<<0) | (1<<4); // only PE and ET set...
break;
default:
goto _default;
}
NEXT;
_0f_0x0B: /* UD2 */
kill(getpid(), SIGILL); // this is undefined instruction
@@ -84,6 +96,15 @@
}
NEXT;
_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_0x1F: /* NOP (multi-byte) */
nextop = F8;
GET_ED;
@@ -169,14 +190,56 @@
_0f_0x38: // these are some SSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x00: /* PSHUFB */
nextop = F8;
GET_EM;
eam1 = GM;
for (int i=0; i<8; ++i) {
if(EM->ub[i]&128)
GM.ub[i] = 0;
else
GM.ub[i] = eax1.ub[EM->ub[i]&7];
}
break;
case 0x04: /* PMADDUBSW Gm,Em */
nextop = F8;
GET_EM;
for (int i=0; i<4; ++i) {
tmp32s = (int32_t)(GM.ub[i*2+0])*EM->ub[i*2+0] + (int32_t)(GM.ub[i*2+1])*EM->ub[i*2+1];
GM.sw[i] = (tmp32s>32767)?32767:tmp32s; // no negative value to test
tmp32s = (int32_t)(GM.ub[i*2+0])*EM->sb[i*2+0] + (int32_t)(GM.ub[i*2+1])*EM->sb[i*2+1];
GM.sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
}
break;
case 0x0B: /* PMULHRSW Gm, Em */
nextop = F8;
GET_EM;
for (int i=0; i<4; ++i) {
tmp32s = ((((int32_t)(GM.sw[i])*(int32_t)(EM->sw[i]))>>14) + 1)>>1;
GM.uw[i] = tmp32s&0xffff;
}
break;
case 0x1C: /* PABSB Gm, Em */
nextop = F8;
GET_EM;
for (int i=0; i<8; ++i) {
GM.sb[i] = abs(EM->sb[i]);
}
break;
case 0x1D: /* PABSW Gm, Em */
nextop = F8;
GET_EM;
for (int i=0; i<4; ++i) {
GM.sw[i] = abs(EM->sw[i]);
}
break;
case 0x1E: /* PABSD Gm, Em */
nextop = F8;
GET_EM;
for (int i=0; i<2; ++i) {
GM.sd[i] = abs(EM->sd[i]);
}
break;
default:
goto _default;
}
@@ -619,7 +682,7 @@
NEXT;
_0f_0xA1: /* POP FS */
emu->segs[_FS] = Pop(emu); // no check, no use....
emu->segs_clean[_FS] = 0;
emu->segs_serial[_FS] = 0;
NEXT;
_0f_0xA2: /* CPUID */
tmp32u = R_EAX;
@@ -653,7 +716,7 @@
NEXT;
_0f_0xA9: /* POP GS */
emu->segs[_GS] = Pop(emu);
emu->segs_clean[_GS] = 0;
emu->segs_serial[_GS] = 0;
NEXT;
@@ -699,22 +762,22 @@
// should save flags & all
// copy MMX regs...
for(int i=0; i<8; ++i)
memcpy(ED->dword+32+i*16, &emu->mmx[0], sizeof(emu->mmx[0]));
memcpy(((void*)(ED))+32+i*16, &emu->mmx[0], sizeof(emu->mmx[0]));
// copy SSE regs
memcpy(ED->dword+160, &emu->xmm[0], sizeof(emu->xmm));
memcpy(((void*)(ED))+160, &emu->xmm[0], sizeof(emu->xmm));
// put also FPU regs in a reserved area...
for(int i=0; i<8; ++i)
memcpy(ED->dword+416+i*8, &emu->fpu[0], sizeof(emu->fpu[0]));
memcpy(((void*)(ED))+416+i*8, &emu->fpu[0], sizeof(emu->fpu[0]));
break;
case 1: /* FXRSTOR m512byte */
// should restore flags & all
// copy back MMX regs...
for(int i=0; i<8; ++i)
memcpy(&emu->mmx[i], ED->dword+32+i*16, sizeof(emu->mmx[0]));
memcpy(&emu->mmx[i], ((void*)(ED))+32+i*16, sizeof(emu->mmx[0]));
// copy SSE regs
memcpy(&emu->xmm[0], ED->dword+160/4, sizeof(emu->xmm));
memcpy(&emu->xmm[0], ((void*)(ED))+160/4, sizeof(emu->xmm));
for(int i=0; i<8; ++i)
memcpy(&emu->fpu[0], ED->dword+416+i*8, sizeof(emu->fpu[0]));
memcpy(&emu->fpu[0], ((void*)(ED))+416+i*8, sizeof(emu->fpu[0]));
break;
case 2: /* LDMXCSR Md */
emu->mxcsr = ED->dword[0];
@@ -809,9 +872,10 @@
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
} else
} else {
ED->dword[0] ^= (1<<tmp8u);
CLEAR_FLAG(F_CF);
}
break;
case 6: /* BTR Ed, Ib */
CHECK_FLAGS(emu);
@@ -936,7 +1000,11 @@
GX.ud[i]=(tmp8s)?0xffffffff:0;
}
NEXT;
_0f_0xC3: /* MOVNTI Ed,Gd */
nextop = F8;
GET_ED;
ED->dword[0] = GD.dword[0];
NEXT;
_0f_0xC4: /* PINSRW Gm,Ew,Ib */
nextop = F8;
GET_ED;
@@ -1033,12 +1101,15 @@
_0f_0xD7: /* PMOVMSKB Gd,Em */
nextop = F8;
GET_EM;
GD.dword[0] = 0;
for (int i=0; i<8; ++i)
if(EM->ub[i]&0x80)
GD.dword[0] |= (1<<i);
NEXT;
if((nextop&0xC0)==0xC0) {
GET_EM;
GD.dword[0] = 0;
for (int i=0; i<8; ++i)
if(EM->ub[i]&0x80)
GD.dword[0] |= (1<<i);
NEXT;
} else
goto _default;
_0f_0xD8: /* PSUBUSB Gm,Em */
nextop = F8;
GET_EM;
@@ -1055,7 +1126,12 @@
GM.uw[i] = (tmp32s < 0) ? 0 : tmp32s;
}
NEXT;
_0f_0xDA: /* PMINUB Gm,Em */
nextop = F8;
GET_EM;
for (int i=0; i<8; ++i)
GM.ub[i] = (GM.ub[i]<EM->ub[i])?GM.ub[i]:EM->ub[i];
NEXT;
_0f_0xDB: /* PAND Gm,Em */
nextop = F8;
GET_EM;
@@ -1077,7 +1153,12 @@
GM.uw[i] = (tmp32u>65535) ? 65535 : tmp32u;
}
NEXT;
_0f_0xDE: /* PMAXUB Gm,Em */
nextop = F8;
GET_EM;
for (int i=0; i<8; ++i)
GM.ub[i] = (GM.ub[i]>EM->ub[i])?GM.ub[i]:EM->ub[i];
NEXT;
_0f_0xDF: /* PANDN Gm,Em */
nextop = F8;
GET_EM;
+20 -4
View File
@@ -30,11 +30,17 @@
NEXT;
_66_0x07: /* POP ES */
emu->segs[_ES] = Pop16(emu); // no check, no use....
emu->segs_clean[_ES] = 0;
emu->segs_serial[_ES] = 0;
NEXT;
_66_0x0F: /* 66 0f prefix */
#include "run660f.h"
emu->old_ip = R_EIP;
R_EIP = ip-2; // don't count 66 0F yet
Run660F(emu); // implemented in Run660f.c
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0x26: /* ES: */
// ignored
@@ -203,14 +209,14 @@
_66_0x8C: /* MOV Ew,Seg */
nextop = F8;
GET_EW;
EW->word[0] = emu->segs[(nextop&38)>>3];
EW->word[0] = emu->segs[(nextop&0x38)>>3];
NEXT;
_66_0x8E: /* MOV Seg,Ew */
nextop = F8;
GET_EW;
emu->segs[((nextop&0x38)>>3)] = EW->word[0];
emu->segs_clean[((nextop&0x38)>>3)] = 0;
emu->segs_serial[((nextop&0x38)>>3)] = 0;
NEXT;
_66_0x8F: /* POP Ew */
nextop = F8;
@@ -350,6 +356,7 @@
Run66D9(emu);
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0xDD:
@@ -358,8 +365,17 @@
Run66DD(emu);
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0xF0: /* LOCK prefix */
emu->old_ip = R_EIP;
R_EIP = ip;
RunLock66(emu);
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0xF2: /* REPNZ prefix */
_66_0xF3: /* REPZ prefix */
+8 -88
View File
@@ -10,11 +10,7 @@
case 0xC5:
case 0xC6:
case 0xC7: /* FADD */
#ifdef USE_FLOAT
ST0.f += ST(nextop&7).f;
#else
ST0.d += ST(nextop&7).d;
#endif
break;
case 0xC8:
case 0xC9:
@@ -24,11 +20,7 @@
case 0xCD:
case 0xCE:
case 0xCF: /* FMUL */
#ifdef USE_FLOAT
ST0.f *= ST(nextop&7).f;
#else
ST0.d *= ST(nextop&7).d;
#endif
break;
case 0xD0:
case 0xD1:
@@ -38,11 +30,7 @@
case 0xD5:
case 0xD6:
case 0xD7: /* FCOM */
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d);
#endif
break;
case 0xD8:
case 0xD9:
@@ -52,11 +40,7 @@
case 0xDD:
case 0xDE:
case 0xDF: /* FCOMP */
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d);
#endif
fpu_do_pop(emu);
break;
case 0xE0:
@@ -67,11 +51,7 @@
case 0xE5:
case 0xE6:
case 0xE7: /* FSUB */
#ifdef USE_FLOAT
ST0.f -= ST(nextop&7).f;
#else
ST0.d -= ST(nextop&7).d;
#endif
break;
case 0xE8:
case 0xE9:
@@ -81,11 +61,7 @@
case 0xED:
case 0xEE:
case 0xEF: /* FSUBR */
#ifdef USE_FLOAT
ST0.f = ST(nextop&7).f - ST0.f;
#else
ST0.d = ST(nextop&7).d - ST0.d;
#endif
break;
case 0xF0:
case 0xF1:
@@ -95,11 +71,7 @@
case 0xF5:
case 0xF6:
case 0xF7: /* FDIV */
#ifdef USE_FLOAT
ST0.f /= ST(nextop&7).f;
#else
ST0.d /= ST(nextop&7).d;
#endif
break;
case 0xF8:
case 0xF9:
@@ -109,46 +81,26 @@
case 0xFD:
case 0xFE:
case 0xFF: /* FDIVR */
#ifdef USE_FLOAT
ST0.f = ST(nextop&7).f / ST0.f;
#else
ST0.d = ST(nextop&7).d / ST0.d;
#endif
break;
default:
switch((nextop>>3)&7) {
case 0: /* FADD ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f += *(float*)ED;
#else
ST0.d += *(float*)ED;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f += f;
#else
memcpy(&f, ED, sizeof(float));
ST0.d += f;
#endif
}
break;
case 1: /* FMUL ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f *= *(float*)ED;
#else
ST0.d *= *(float*)ED;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f *= f;
#else
memcpy(&f, ED, sizeof(float));
ST0.d *= f;
#endif
}
break;
case 2: /* FCOM ST0, float */
@@ -156,7 +108,7 @@
if(!(((uintptr_t)ED)&3))
fpu_fcom(emu, *(float*)ED);
else {
*(uint32_t*)&f = ED->dword[0];
memcpy(&f, ED, sizeof(float));
fpu_fcom(emu, f);
}
break;
@@ -165,7 +117,7 @@
if(!(((uintptr_t)ED)&3))
fpu_fcom(emu, *(float*)ED);
else {
*(uint32_t*)&f = ED->dword[0];
memcpy(&f, ED, sizeof(float));
fpu_fcom(emu, f);
}
fpu_do_pop(emu);
@@ -173,69 +125,37 @@
case 4: /* FSUB ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f -= *(float*)ED;
#else
ST0.d -= *(float*)ED;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f -= f;
#else
memcpy(&f, ED, sizeof(float));
ST0.d -= f;
#endif
}
break;
case 5: /* FSUBR ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f = *(float*)ED - ST0.f;
#else
ST0.d = *(float*)ED - ST0.d;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f = f - ST0.f;
#else
memcpy(&f, ED, sizeof(float));
ST0.d = f - ST0.d;
#endif
}
break;
case 6: /* FDIV ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f /= *(float*)ED;
#else
ST0.d /= *(float*)ED;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f /= f;
#else
memcpy(&f, ED, sizeof(float));
ST0.d /= f;
#endif
}
break;
case 7: /* FDIVR ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f = *(float*)ED / ST0.f;
#else
ST0.d = *(float*)ED / ST0.d;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f = f / ST0.f;
#else
memcpy(&f, ED, sizeof(float));
ST0.d = f / ST0.d;
#endif
}
break;
default:
+37 -151
View File
@@ -1,5 +1,3 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
nextop = F8;
switch (nextop) {
case 0xC0:
@@ -31,18 +29,10 @@
break;
case 0xE0: /* FCHS */
#ifdef USE_FLOAT
ST0.f = -ST0.f;
#else
ST0.d = -ST0.d;
#endif
break;
case 0xE1: /* FABS */
#ifdef USE_FLOAT
ST0.f = fabsf(ST0.f);
#else
ST0.d = fabs(ST0.d);
#endif
break;
case 0xE4: /* FTST */
@@ -54,153 +44,96 @@
case 0xE8: /* FLD1 */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = 1.0f;
#else
ST0.d = 1.0;
#endif
break;
case 0xE9: /* FLDL2T */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = L2T;
#else
ST0.d = L2T;
#endif
break;
case 0xEA: /* FLDL2E */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = L2E;
#else
ST0.d = L2E;
#endif
break;
case 0xEB: /* FLDPI */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = PI;
#else
ST0.d = PI;
#endif
break;
case 0xEC: /* FLDLG2 */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = LG2;
#else
ST0.d = LG2;
#endif
break;
case 0xED: /* FLDLN2 */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = LN2;
#else
ST0.d = LN2;
#endif
break;
case 0xEE: /* FLDZ */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = 0.0f;
#else
ST0.d = 0.0;
#endif
break;
case 0xF0: /* F2XM1 */
#ifdef USE_FLOAT
ST0.f = exp2f(ST0.f) - 1.0f;
#else
ST0.d = exp2(ST0.d) - 1.0;
#endif
break;
case 0xF1: /* FYL2X */
#ifdef USE_FLOAT
ST(1).f = log2f(ST0.f)*ST(1).f;
#else
ST(1).d = log2(ST0.d)*ST(1).d;
#endif
ST(1).d *= log2(ST0.d);
fpu_do_pop(emu);
break;
case 0xF2: /* FPTAN */
#ifdef USE_FLOAT
ST0.f = tanf(ST0.f);
fpu_do_push(emu);
ST0.f = 1.0f;
#else
ST0.d = tan(ST0.d);
fpu_do_push(emu);
ST0.d = 1.0;
#endif
emu->sw.f.F87_C2 = 0;
break;
case 0xF3: /* FPATAN */
#ifdef USE_FLOAT
ST1.f = atan2f(ST1.f, ST0.f);
#else
ST1.d = atan2(ST1.d, ST0.d);
#endif
fpu_do_pop(emu);
break;
case 0xF4: /* FXTRACT */
#ifdef USE_FLOAT
tmp32s = (ST0.ll&0x7f700000)>>23;
tmp32s -= 127;
ST0.f /= exp2f(tmp32s);
fpu_do_push(emu);
ST0.f = tmp32s;
#else
tmp32s = (ST0.ll&0x7ff0000000000000LL)>>52;
tmp32s -= 1023;
ST0.d /= exp2(tmp32s);
ST0.d = frexp(ST0.d, &tmp32s);
fpu_do_push(emu);
ST0.d = tmp32s;
#endif
break;
case 0xF8: /* FPREM */
#ifdef USE_FLOAT
ll = ST0.f / ST1.f;
ST0.f -= ST1.f * ll;
#else
ll = ST0.d / ST1.d;
ST0.d -= ST1.d * ll;
#endif
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = (ll&1);
emu->sw.f.F87_C3 = ((ll>>1)&1);
emu->sw.f.F87_C1 = ((ll>>2)&1);
break;
case 0xF5: /* FPREM1 */
// get exponant(ST(0))-exponant(ST(1)) in temp32s
#ifdef USE_FLOAT
tmp32s = ((ST0.ll&0x7f700000)>>23) - ((ST1.ll&0x7f700000)>>23);
#else
tmp32s = ((ST0.ll&0x7ff0000000000000LL)>>52) - ((ST1.ll&0x7ff0000000000000LL)>>52);
#endif
{
int e0, e1;
frexp(ST0.d, &e0);
frexp(ST1.d, &e1);
tmp32s = e0 - e1;
}
if(tmp32s<64)
{
#ifdef USE_FLOAT
ll = (int64_t)round(ST0.f/ST1.f);
ST0.f = ST0.f - (ST1.f*ll);
#else
ll = (int64_t)round(ST0.d/ST1.d);
ll = (int64_t)floor(ST0.d/ST1.d);
ST0.d = ST0.d - (ST1.d*ll);
#endif
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (ll&1)?1:0;
emu->sw.f.F87_C3 = (ll&2)?1:0;
emu->sw.f.F87_C0 = (ll&4)?1:0;
} else {
#ifdef USE_FLOAT
ll = (int64_t)(floor((ST0.f/ST1.f))/powf(2, tmp32s - 32));
ST0.f = ST0.f - ST1.f*ll*powf(2, 32);
#else
ll = (int64_t)(floor((ST0.d/ST1.d))/pow(2, tmp32s - 32));
ST0.d = ST0.d - ST1.d*ll*pow(2, tmp32s - 32);
#endif
ll = (int64_t)(floor((ST0.d/ST1.d))/exp2(tmp32s - 32));
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
emu->sw.f.F87_C2 = 1;
}
break;
case 0xF5: /* FPREM1 */
// get exponant(ST(0))-exponant(ST(1)) in temp32s
{
int e0, e1;
frexp(ST0.d, &e0);
frexp(ST1.d, &e1);
tmp32s = e0 - e1;
}
if(tmp32s<64)
{
ll = (int64_t)round(ST0.d/ST1.d);
ST0.d = ST0.d - (ST1.d*ll);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (ll&1)?1:0;
emu->sw.f.F87_C3 = (ll&2)?1:0;
emu->sw.f.F87_C0 = (ll&4)?1:0;
} else {
ll = (int64_t)(trunc((ST0.d/ST1.d))/exp2(tmp32s - 32));
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
emu->sw.f.F87_C2 = 1;
}
break;
@@ -211,56 +144,28 @@
emu->top=(emu->top+1)&7; // this will probably break a few things
break;
case 0xF9: /* FYL2XP1 */
#ifdef USE_FLOAT
ST(1).f = log2f(ST0.f + 1.0f)*ST(1).f;
#else
ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
#endif
ST(1).d *= log2(ST0.d + 1.0);
fpu_do_pop(emu);
break;
case 0xFA: /* FSQRT */
#ifdef USE_FLOAT
ST0.f = sqrtf(ST0.f);
#else
ST0.d = sqrt(ST0.d);
#endif
break;
case 0xFB: /* FSINCOS */
fpu_do_push(emu);
#ifdef USE_FLOAT
sincosf(ST1.f, &ST1.f, &ST0.f);
#else
sincos(ST1.d, &ST1.d, &ST0.d);
#endif
break;
case 0xFC: /* FRNDINT */
#ifdef USE_FLOAT
ST0.f = fpu_round(emu, ST0.f);
#else
ST0.d = fpu_round(emu, ST0.d);
#endif
break;
case 0xFD: /* FSCALE */
// this could probably be done by just altering the exponant part of the float...
#ifdef USE_FLOAT
ST0.f *= exp2f(truncf(ST1.f));
#else
ST0.d *= exp2(trunc(ST1.d));
#endif
break;
case 0xFE: /* FSIN */
#ifdef USE_FLOAT
ST0.f = sinf(ST0.f);
#else
ST0.d = sin(ST0.d);
#endif
break;
case 0xFF: /* FCOS */
#ifdef USE_FLOAT
ST0.f = cosf(ST0.f);
#else
ST0.d = cos(ST0.d);
#endif
break;
@@ -288,42 +193,30 @@
case 0: /* FLD ST0, Ed float */
GET_ED;
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.ll = ED->dword[0];
#else
if(!(((uintptr_t)ED)&3))
ST0.d = *(float*)ED;
else {
memcpy(&f, ED->dword, sizeof(float));
memcpy(&f, ED, sizeof(float));
ST0.d = f;
}
#endif
break;
case 2: /* FST Ed, ST0 */
GET_ED;
#ifdef USE_FLOAT
*(float*)ED = ST0.f;
#else
if(!(((uintptr_t)ED)&3))
*(float*)ED = ST0.d;
else {
f = ST0.d;
memcpy(ED->dword, &f, sizeof(float));
memcpy(ED, &f, sizeof(float));
}
#endif
break;
case 3: /* FSTP Ed, ST0 */
GET_ED;
#ifdef USE_FLOAT
ED->dword[0] = ST0.ll;
#else
if(!(((uintptr_t)ED)&3))
*(float*)ED = ST0.d;
else {
f = ST0.d;
memcpy(ED->dword, &f, sizeof(float));
memcpy(ED, &f, sizeof(float));
}
#endif
fpu_do_pop(emu);
break;
case 4: /* FLDENV m */
@@ -341,12 +234,6 @@
// warning, incomplete
GET_ED;
fpu_savenv(emu, (char*)ED, 0);
ED->dword[0] = emu->cw;
ED->dword[1] = emu->sw.x16;
// tagword: 2bits*8
ED->word[4] = 0;
for (int i=0; i<8; ++i)
ED->word[4] |= (emu->p_regs[i].tag)<<(i*2);
// intruction pointer: 48bits
// data (operand) pointer: 48bits
// last opcode: 11bits save: 16bits restaured (1st and 2nd opcode only)
@@ -359,4 +246,3 @@
goto _default;
}
}
#pragma GCC diagnostic pop
+2 -30
View File
@@ -51,11 +51,7 @@
break;
case 0xE9: /* FUCOMPP */
#ifdef USE_FLOAT
fpu_fcom(emu, ST1.f);
#else
fpu_fcom(emu, ST1.d); // bad, should handle QNaN and IA interrupt
#endif
fpu_do_pop(emu);
fpu_do_pop(emu);
break;
@@ -76,19 +72,11 @@
switch((nextop>>3)&7) {
case 0: /* FIADD ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f += ED->sdword[0];
#else
ST0.d += ED->sdword[0];
#endif
break;
case 1: /* FIMUL ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f *= ED->sdword[0];
#else
ST0.d *= ED->sdword[0];
#endif
break;
case 2: /* FICOM ST0, Ed int */
GET_ED;
@@ -101,35 +89,19 @@
break;
case 4: /* FISUB ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f -= ED->sdword[0];
#else
ST0.d -= ED->sdword[0];
#endif
break;
case 5: /* FISUBR ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f = ED->sdword[0] - ST0.f;
#else
ST0.d = ED->sdword[0] - ST0.d;
#endif
ST0.d = (double)ED->sdword[0] - ST0.d;
break;
case 6: /* FIDIV ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f /= ED->sdword[0];
#else
ST0.d /= ED->sdword[0];
#endif
break;
case 7: /* FIDIVR ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f = ED->sdword[0] / ST0.f;
#else
ST0.d = ED->sdword[0] / ST0.d;
#endif
ST0.d = (double)ED->sdword[0] / ST0.d;
break;
}
}
+10 -102
View File
@@ -49,6 +49,8 @@
ST0.ll = ST(nextop&7).ll;
break;
case 0xE1: /* FDISI8087_NOP */
break;
case 0xE2: /* FNCLEX */
//Clears the floating-point exception flags (PE, UE, OE, ZE, DE, and IE),
// the exception summary status flag (ES), the stack fault flag (SF), and the busy flag (B) in the FPU status word
@@ -73,11 +75,7 @@
case 0xED:
case 0xEE:
case 0xEF:
#ifdef USE_FLOAT
fpu_fcomi(emu, ST(nextop&7).f);
#else
fpu_fcomi(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
#endif
break;
case 0xF0: /* FCOMI ST0, STx */
@@ -88,14 +86,9 @@
case 0xF5:
case 0xF6:
case 0xF7:
#ifdef USE_FLOAT
fpu_fcomi(emu, ST(nextop&7).f);
#else
fpu_fcomi(emu, ST(nextop&7).d);
#endif
break;
case 0xE0:
case 0xE1:
case 0xE4:
case 0xE5:
case 0xE6:
@@ -103,134 +96,49 @@
goto _default;
default:
switch((nextop>>3)&7) {
case 0: /* FILD ST0, Gd */
case 0: /* FILD ST0, Ed */
GET_ED;
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = ED->sdword[0];
#else
ST0.d = ED->sdword[0];
#endif
break;
case 1: /* FISTTP Ed, ST0 */
GET_ED;
#ifdef USE_FLOAT
tmp32s = ST0.f; // TODO: Handling of FPU Exception
if(tmp32s==0x7fffffff && isgreater(ST0.f, (float)(int32_t)0x7fffffff))
tmp32s = 0x80000000;
#else
tmp32s = ST0.d; // TODO: Handling of FPU Exception
if(tmp32s==0x7fffffff && isgreater(ST0.d, (double)(int32_t)0x7fffffff))
tmp32s = 0x80000000;
#endif
fpu_do_pop(emu);
ED->sdword[0] = tmp32s;
break;
case 2: /* FIST Ed, ST0 */
GET_ED;
#ifdef USE_FLOAT
if(isgreater(ST0.f, (float)(int32_t)0x7fffffff) || isless(ST0.f, -(float)(int32_t)0x7fffffff))
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff) || !isfinite(ST0.d))
ED->sdword[0] = 0x80000000;
else {
switch(emu->round) {
case ROUND_Nearest:
ED->sdword[0] = floorf(ST0.f+0.5);
break;
case ROUND_Down:
ED->sdword[0] = floorf(ST0.f);
break;
case ROUND_Up:
ED->sdword[0] = ceilf(ST0.f);
break;
case ROUND_Chop:
ED->sdword[0] = ST0.f;
break;
}
volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR
ED->sdword[0] = tmp;
}
#else
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff))
ED->sdword[0] = 0x80000000;
else {
switch(emu->round) {
case ROUND_Nearest:
ED->sdword[0] = floor(ST0.d+0.5);
break;
case ROUND_Down:
ED->sdword[0] = floor(ST0.d);
break;
case ROUND_Up:
ED->sdword[0] = ceil(ST0.d);
break;
case ROUND_Chop:
ED->sdword[0] = ST0.d;
break;
}
}
#endif
break;
case 3: /* FISTP Ed, ST0 */
GET_ED;
#ifdef USE_FLOAT
if(isgreater(ST0.f, (float)(int32_t)0x7fffffff) || isless(ST0.f, -(float)(int32_t)0x7fffffff))
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff) || !isfinite(ST0.d))
ED->sdword[0] = 0x80000000;
else {
switch(emu->round) {
case ROUND_Nearest:
ED->sdword[0] = floorf(ST0.f+0.5);
break;
case ROUND_Down:
ED->sdword[0] = floorf(ST0.f);
break;
case ROUND_Up:
ED->sdword[0] = ceilf(ST0.f);
break;
case ROUND_Chop:
ED->sdword[0] = ST0.f;
break;
}
volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR
ED->sdword[0] = tmp;
}
#else
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff))
ED->sdword[0] = 0x80000000;
else {
switch(emu->round) {
case ROUND_Nearest:
ED->sdword[0] = floor(ST0.d+0.5);
break;
case ROUND_Down:
ED->sdword[0] = floor(ST0.d);
break;
case ROUND_Up:
ED->sdword[0] = ceil(ST0.d);
break;
case ROUND_Chop:
ED->sdword[0] = ST0.d;
break;
}
}
#endif
fpu_do_pop(emu);
break;
case 5: /* FLD ST0, Gt */
case 5: /* FLD ST0, Et */
GET_ED;
fpu_do_push(emu);
memcpy(&STld(0).ld, ED, 10);
#ifdef USE_FLOAT
LD2D(&STld(0), &d);
ST0.f = d;
#else
LD2D(&STld(0), &ST(0).d);
#endif
STld(0).ref = ST0.ll;
break;
case 7: /* FSTP tbyte */
GET_ED;
if(ST0.ll!=STld(0).ref)
#ifdef USE_FLOAT
{d = ST0.f; D2LD(&d, ED);}
#else
D2LD(&ST0.d, ED);
#endif
else
memcpy(ED, &STld(0).ld, 10);
fpu_do_pop(emu);
+8 -96
View File
@@ -1,5 +1,3 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
nextop = F8;
switch(nextop) {
case 0xC0:
@@ -10,11 +8,7 @@
case 0xC5:
case 0xC6:
case 0xC7: /* FADD */
#ifdef USE_FLOAT
ST(nextop&7).f += ST0.f;
#else
ST(nextop&7).d += ST0.d;
#endif
break;
case 0xC8:
case 0xC9:
@@ -24,11 +18,7 @@
case 0xCD:
case 0xCE:
case 0xCF: /* FMUL */
#ifdef USE_FLOAT
ST(nextop&7).f *= ST0.f;
#else
ST(nextop&7).d *= ST0.d;
#endif
break;
case 0xD0:
case 0xD1:
@@ -38,11 +28,7 @@
case 0xD5:
case 0xD6:
case 0xD7: /* FCOM */
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d);
#endif
break;
case 0xD8:
case 0xD9:
@@ -52,11 +38,7 @@
case 0xDD:
case 0xDE:
case 0xDF: /* FCOMP */
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d); // TODO: is this ok?
#endif
fpu_do_pop(emu);
break;
case 0xE0:
@@ -67,11 +49,7 @@
case 0xE5:
case 0xE6:
case 0xE7: /* FSUBR */
#ifdef USE_FLOAT
ST(nextop&7).f = ST0.f -ST(nextop&7).f;
#else
ST(nextop&7).d = ST0.d -ST(nextop&7).d;
#endif
break;
case 0xE8:
case 0xE9:
@@ -81,11 +59,7 @@
case 0xED:
case 0xEE:
case 0xEF: /* FSUB */
#ifdef USE_FLOAT
ST(nextop&7).f -= ST0.f;
#else
ST(nextop&7).d -= ST0.d;
#endif
break;
case 0xF0:
case 0xF1:
@@ -95,11 +69,7 @@
case 0xF5:
case 0xF6:
case 0xF7: /* FDIVR */
#ifdef USE_FLOAT
ST(nextop&7).f = ST0.f / ST(nextop&7).f;
#else
ST(nextop&7).d = ST0.d / ST(nextop&7).d;
#endif
break;
case 0xF8:
case 0xF9:
@@ -109,54 +79,32 @@
case 0xFD:
case 0xFE:
case 0xFF: /* FDIV */
#ifdef USE_FLOAT
ST(nextop&7).f /= ST0.f;
#else
ST(nextop&7).d /= ST0.d;
#endif
break;
default:
GET_ED;
switch((nextop>>3)&7) {
case 0: /* FADD ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f += *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f += d;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d += *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
ST0.d += d;
}
#endif
break;
case 1: /* FMUL ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f *= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f *= d;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d *= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
ST0.d *= d;
}
#endif
break;
case 2: /* FCOM ST0, double */
if(!(((uintptr_t)ED)&7))
fpu_fcom(emu, *(double*)ED);
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
fpu_fcom(emu, d);
}
break;
@@ -164,78 +112,42 @@
if(!(((uintptr_t)ED)&7))
fpu_fcom(emu, *(double*)ED);
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
fpu_fcom(emu, d);
}
fpu_do_pop(emu);
break;
case 4: /* FSUB ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f -= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f -= d;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d -= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
ST0.d -= d;
}
#endif
break;
case 5: /* FSUBR ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f = *(double*)ED - ST0.f;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f = d - ST0.f;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d = *(double*)ED - ST0.d;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
ST0.d = d - ST0.d;
}
#endif
break;
case 6: /* FDIV ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f /= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f /= d;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d /= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
ST0.d /= d;
}
#endif
break;
case 7: /* FDIVR ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f = *(double*)ED / ST0.f;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f = d / ST0.f;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d = *(double*)ED / ST0.d;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
ST0.d = d / ST0.d;
}
#endif
break;
default:
goto _default;
+21 -41
View File
@@ -41,11 +41,7 @@
case 0xE5:
case 0xE6:
case 0xE7:
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
#endif
break;
case 0xE8: /* FUCOMP ST0, STx */
case 0xE9:
@@ -55,11 +51,7 @@
case 0xED:
case 0xEE:
case 0xEF:
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
#endif
fpu_do_pop(emu);
break;
@@ -94,39 +86,37 @@
case 0: /* FLD double */
GET_ED;
fpu_do_push(emu);
#ifdef USE_FLOAT
*(uint64_t*)&d = *(int64_t*)ED;
ST0.f = d;
#else
ST0.ll = *(int64_t*)ED;
#endif
if(!(((uintptr_t)ED)&7))
ST0.d = *(double*)ED;
else {
memcpy(&ST0.d, ED, sizeof(double));
}
break;
case 1: /* FISTTP ED qword */
GET_ED;
#ifdef USE_FLOAT
*(int64_t*)ED = ST0.f;
#else
*(int64_t*)ED = ST0.d;
#endif
if(!(((uintptr_t)ED)&7))
*(int64_t*)ED = ST0.d;
else {
int64_t i64 = ST0.d;
memcpy(ED, &i64, sizeof(int64_t));
}
fpu_do_pop(emu);
break;
case 2: /* FST double */
GET_ED;
#ifdef USE_FLOAT
d = ST0.f;
*(int64_t*)ED = *(uint64_t*)&d;
#else
*(int64_t*)ED = ST0.ll;
#endif
if(!(((uintptr_t)ED)&7))
*(double*)ED = ST0.d;
else {
memcpy(ED, &ST0.d, sizeof(double));
}
break;
case 3: /* FSTP double */
GET_ED;
#ifdef USE_FLOAT
d = ST0.f;
*(int64_t*)ED = *(uint64_t*)&d;
#else
*(int64_t*)ED = ST0.ll;
#endif
if(!(((uintptr_t)ED)&7))
*(double*)ED = ST0.d;
else {
memcpy(ED, &ST0.d, sizeof(double));
}
fpu_do_pop(emu);
break;
case 4: /* FRSTOR m108byte */
@@ -137,12 +127,7 @@
char* p =(char*)ED;
p += 28;
for (int i=0; i<8; ++i) {
#ifdef USE_FLOAT
d = ST(i).f;
LD2D(p, &d);
#else
LD2D(p, &ST(i).d);
#endif
p+=10;
}
}
@@ -157,12 +142,7 @@
char* p =(char*)ED;
p += 28;
for (int i=0; i<8; ++i) {
#ifdef USE_FLOAT
D2LD(&d, p);
ST(i).f = d;
#else
D2LD(&ST(i).d, p);
#endif
p+=10;
}
}
+18 -87
View File
@@ -1,55 +1,41 @@
nextop = F8;
switch (nextop) {
case 0xC1: /* FADDP ST1, ST0 */
#ifdef USE_FLOAT
ST(1).f += ST0.f;
#else
ST(1).d += ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xC0: /* FADDP STx, ST0 */
case 0xC1: /* FADDP ST1, ST0 */
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
#ifdef USE_FLOAT
ST(nextop&7).f += ST0.f;
#else
ST(nextop&7).d += ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xC9: /* FMULP ST1, ST0 */
#ifdef USE_FLOAT
ST1.f *= ST0.f;
#else
ST1.d *= ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xC8: /* FMULP STx, ST0 */
case 0xC9: /* FMULP ST1, ST0 */
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
#ifdef USE_FLOAT
ST(nextop&7).f *= ST0.f;
#else
ST(nextop&7).d *= ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7: /* FCOMP */
fpu_fcom(emu, ST(nextop&7).d);
fpu_do_pop(emu);
break;
case 0xD9: /* FCOMPP */
#ifdef USE_FLOAT
fpu_fcom(emu, ST1.f);
#else
fpu_fcom(emu, ST1.d);
#endif
fpu_do_pop(emu);
fpu_do_pop(emu);
break;
@@ -65,33 +51,18 @@
case 0xE5:
case 0xE6:
case 0xE7:
#ifdef USE_FLOAT
ST(nextop&7).f = ST0.f - ST(nextop&7).f;
#else
ST(nextop&7).d = ST0.d - ST(nextop&7).d;
#endif
fpu_do_pop(emu);
break;
case 0xE9: /* FSUBP ST1, ST0 */
#ifdef USE_FLOAT
ST1.f -= ST0.f;
#else
ST1.d -= ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xE8: /* FSUBP STx, ST0 */
case 0xE9: /* FSUBP ST1, ST0 */
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
#ifdef USE_FLOAT
ST(nextop&7).f -= ST0.f;
#else
ST(nextop&7).d -= ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xF0: /* FDIVRP STx, ST0 */
@@ -102,11 +73,7 @@
case 0xF5:
case 0xF6:
case 0xF7:
#ifdef USE_FLOAT
ST(nextop&7).f = ST0.f / ST(nextop&7).f;
#else
ST(nextop&7).d = ST0.d / ST(nextop&7).d;
#endif
fpu_do_pop(emu);
break;
case 0xF8: /* FDIVP STx, ST0 */
@@ -117,23 +84,11 @@
case 0xFD:
case 0xFE:
case 0xFF:
#ifdef USE_FLOAT
ST(nextop&7).f /= ST0.f;
#else
ST(nextop&7).d /= ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
case 0xD8:
case 0xD8:
case 0xDA:
case 0xDB:
case 0xDC:
@@ -146,51 +101,27 @@
switch((nextop>>3)&7) {
case 0: /* FIADD ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f += EW->sword[0];
#else
ST0.d += EW->sword[0];
#endif
break;
case 1: /* FIMUL ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f *= EW->sword[0];
#else
ST0.d *= EW->sword[0];
#endif
break;
case 4: /* FISUB ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f -= EW->sword[0];
#else
ST0.d -= EW->sword[0];
#endif
break;
case 5: /* FISUBR ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f = EW->sword[0] - ST0.f;
#else
ST0.d = EW->sword[0] - ST0.d;
#endif
ST0.d = (double)EW->sword[0] - ST0.d;
break;
case 6: /* FIDIV ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f /= EW->sword[0];
#else
ST0.d /= EW->sword[0];
#endif
break;
case 7: /* FIDIVR ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f = EW->sword[0] / ST0.f;
#else
ST0.d = EW->sword[0] / ST0.d;
#endif
ST0.d = (double)EW->sword[0] / ST0.d;
break;
default:
goto _default;
+38 -117
View File
@@ -1,5 +1,17 @@
nextop = F8;
switch (nextop) {
case 0xC0: /* FFREEP STx */
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
fpu_do_free(emu, nextop-0xC0);
fpu_do_pop(emu);
break;
case 0xE0: /* FNSTSW AX */
emu->sw.f.F87_TOP = emu->top&7;
R_AX = emu->sw.x16;
@@ -13,11 +25,7 @@
case 0xED:
case 0xEE:
case 0xEF:
#ifdef USE_FLOAT
fpu_fcomi(emu, ST(nextop&7).f);
#else
fpu_fcomi(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
#endif
fpu_do_pop(emu);
break;
@@ -29,22 +37,10 @@
case 0xF5:
case 0xF6:
case 0xF7:
#ifdef USE_FLOAT
fpu_fcomi(emu, ST(nextop&7).f);
#else
fpu_fcomi(emu, ST(nextop&7).d);
#endif
fpu_do_pop(emu);
break;
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
case 0xC8:
case 0xC9:
case 0xCA:
@@ -92,105 +88,27 @@
GET_EW;
tmp16s = EW->sword[0];
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = tmp16s;
#else
ST0.d = tmp16s;
#endif
break;
case 1: /* FISTTP Ew, ST0 */
GET_EW;
#ifdef USE_FLOAT
tmp16s = ST0.f;
#else
tmp16s = ST0.d;
#endif
EW->sword[0] = tmp16s;
fpu_do_pop(emu);
break;
case 2: /* FIST Ew, ST0 */
GET_EW;
#ifdef USE_FLOAT
if(isgreater(ST0.f, (float)(int32_t)0x7fff) || isless(ST0.f, -(float)(int32_t)0x7fff))
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff) || !isfinite(ST0.d))
EW->sword[0] = 0x8000;
else {
switch(emu->round) {
case ROUND_Nearest:
EW->sword[0] = floorf(ST0.f+0.5);
break;
case ROUND_Down:
EW->sword[0] = floorf(ST0.f);
break;
case ROUND_Up:
EW->sword[0] = ceilf(ST0.f);
break;
case ROUND_Chop:
EW->sword[0] = ST0.f;
break;
}
}
#else
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff))
EW->sword[0] = 0x8000;
else {
switch(emu->round) {
case ROUND_Nearest:
EW->sword[0] = floor(ST0.d+0.5);
break;
case ROUND_Down:
EW->sword[0] = floor(ST0.d);
break;
case ROUND_Up:
EW->sword[0] = ceil(ST0.d);
break;
case ROUND_Chop:
EW->sword[0] = ST0.d;
break;
}
}
#endif
else
EW->sword[0] = fpu_round(emu, ST0.d);
break;
case 3: /* FISTP Ew, ST0 */
GET_EW;
#ifdef USE_FLOAT
if(isgreater(ST0.f, (float)(int32_t)0x7fff) || isless(ST0.f, -(float)(int32_t)0x7fff))
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff) || !isfinite(ST0.d))
EW->sword[0] = 0x8000;
else {
switch(emu->round) {
case ROUND_Nearest:
EW->sword[0] = floorf(ST0.f+0.5);
break;
case ROUND_Down:
EW->sword[0] = floorf(ST0.f);
break;
case ROUND_Up:
EW->sword[0] = ceilf(ST0.f);
break;
case ROUND_Chop:
EW->sword[0] = ST0.f;
break;
}
}
#else
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff))
EW->sword[0] = 0x8000;
else {
switch(emu->round) {
case ROUND_Nearest:
EW->sword[0] = floor(ST0.d+0.5);
break;
case ROUND_Down:
EW->sword[0] = floor(ST0.d);
break;
case ROUND_Up:
EW->sword[0] = ceil(ST0.d);
break;
case ROUND_Chop:
EW->sword[0] = ST0.d;
break;
}
}
#endif
else
EW->sword[0] = fpu_round(emu, ST0.d);
fpu_do_pop(emu);
break;
case 4: /* FBLD ST0, tbytes */
@@ -202,11 +120,7 @@
GET_ED;
tmp64s = *(int64_t*)ED;
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = tmp64s;
#else
ST0.d = tmp64s;
#endif
STll(0).ll = tmp64s;
STll(0).ref = ST0.ll;
break;
@@ -217,20 +131,27 @@
break;
case 7: /* FISTP i64 */
GET_ED;
if(STll(0).ref==ST(0).ll) {
*(int64_t*)ED = STll(0).ll;
if((uintptr_t)ED & 0x7) {
// un-aligned!
if(STll(0).ref==ST(0).ll)
memcpy(ED, &STll(0).ll, sizeof(int64_t));
else {
int64_t i64;
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
i64 = 0x8000000000000000LL;
else
i64 = fpu_round(emu, ST0.d);
memcpy(ED, &i64, sizeof(int64_t));
}
} else {
#ifdef USE_FLOAT
if(isgreater(ST0.f, (float)(int64_t)0x7fffffffffffffffLL) || isless(ST0.f, (float)(int64_t)0x8000000000000000LL))
*(int64_t*)ED = 0x8000000000000000LL;
else
*(int64_t*)ED = (int64_t)ST0.f;
#else
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL))
*(int64_t*)ED = 0x8000000000000000LL;
else
*(int64_t*)ED = (int64_t)ST0.d;
#endif
if(STll(0).ref==ST(0).ll)
*(int64_t*)ED = STll(0).ll;
else {
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
*(int64_t*)ED = 0x8000000000000000LL;
else
*(int64_t*)ED = fpu_round(emu, ST0.d);
}
}
fpu_do_pop(emu);
break;
+102
View File
@@ -125,6 +125,93 @@
}
break;
#define GOCOND(BASE, PREFIX, CONDITIONAL) \
case BASE+0: \
PREFIX \
if(ACCESS_FLAG(F_OF)) \
CONDITIONAL \
break; \
case BASE+1: \
PREFIX \
if(!ACCESS_FLAG(F_OF)) \
CONDITIONAL \
break; \
case BASE+2: \
PREFIX \
if(ACCESS_FLAG(F_CF)) \
CONDITIONAL \
break; \
case BASE+3: \
PREFIX \
if(!ACCESS_FLAG(F_CF)) \
CONDITIONAL \
break; \
case BASE+4: \
PREFIX \
if(ACCESS_FLAG(F_ZF)) \
CONDITIONAL \
break; \
case BASE+5: \
PREFIX \
if(!ACCESS_FLAG(F_ZF)) \
CONDITIONAL \
break; \
case BASE+6: \
PREFIX \
if((ACCESS_FLAG(F_ZF) || ACCESS_FLAG(F_CF))) \
CONDITIONAL \
break; \
case BASE+7: \
PREFIX \
if(!(ACCESS_FLAG(F_ZF) || ACCESS_FLAG(F_CF))) \
CONDITIONAL \
break; \
case BASE+8: \
PREFIX \
if(ACCESS_FLAG(F_SF)) \
CONDITIONAL \
break; \
case BASE+9: \
PREFIX \
if(!ACCESS_FLAG(F_SF)) \
CONDITIONAL \
break; \
case BASE+0xA: \
PREFIX \
if(ACCESS_FLAG(F_PF)) \
CONDITIONAL \
break; \
case BASE+0xB: \
PREFIX \
if(!ACCESS_FLAG(F_PF)) \
CONDITIONAL \
break; \
case BASE+0xC: \
PREFIX \
if(ACCESS_FLAG(F_SF) != ACCESS_FLAG(F_OF)) \
CONDITIONAL \
break; \
case BASE+0xD: \
PREFIX \
if(ACCESS_FLAG(F_SF) == ACCESS_FLAG(F_OF)) \
CONDITIONAL \
break; \
case BASE+0xE: \
PREFIX \
if(ACCESS_FLAG(F_ZF) || (ACCESS_FLAG(F_SF) != ACCESS_FLAG(F_OF))) \
CONDITIONAL \
break; \
case BASE+0xF: \
PREFIX \
if(!ACCESS_FLAG(F_ZF) && (ACCESS_FLAG(F_SF) == ACCESS_FLAG(F_OF))) \
CONDITIONAL \
break;
GOCOND(0x80
, tmp32s = F32S; CHECK_FLAGS(emu);
, ip += tmp32s;
) /* 0x80 -> 0x8F Jxx */
case 0xC2: /* CMPSD Gx, Ex, Ib */
nextop = F8;
GET_EX;
@@ -143,6 +230,15 @@
GX.q[0]=(tmp8s)?0xffffffffffffffffLL:0LL;
break;
case 0xD0: /* ADDSUBPS Gx, Ex */
nextop = F8;
GET_EX;
GX.f[0] -= EX->f[0];
GX.f[1] += EX->f[1];
GX.f[2] -= EX->f[2];
GX.f[3] += EX->f[3];
break;
case 0xD6: /* MOVDQ2Q Gm, Ex */
nextop = F8;
GET_EX;
@@ -157,6 +253,12 @@
GX.q[1] = 0;
break;
case 0xF0: /* LDDQU Gx, Ex */
nextop = F8;
GET_EX;
memcpy(&GX, EX, 16);
break;
default:
goto _default;
}
+13
View File
@@ -15,6 +15,19 @@
GET_EX;
EX->ud[0] = GX.ud[0];
break;
case 0x12: /* MOVSLDUP Gx, Ex */
nextop = F8;
GET_EX;
GX.ud[1] = GX.ud[0] = EX->ud[0];
GX.ud[3] = GX.ud[2] = EX->ud[2];
break;
case 0x16: /* MOVSHDUP Gx, Ex */
nextop = F8;
GET_EX;
GX.ud[1] = GX.ud[0] = EX->ud[1];
GX.ud[3] = GX.ud[2] = EX->ud[3];
break;
case 0x1E: /* NOP / ENDBR32 / ENDBR64 */
nextop = F8;
+15 -5
View File
@@ -35,6 +35,13 @@ static uint32_t x86emu_parity_tab[8] =
};
static uint8_t EndEmuMarker[] = {0xcc, 'S', 'C', 0, 0, 0, 0};
#ifdef DYNAREC
void DynablockEmuMarker(box86context_t* context)
{
dynarec_log(LOG_DUMP, "Create bridge memory map for PushExit\n");
addDBFromAddressRange(context, (uintptr_t)&EndEmuMarker[0], sizeof(EndEmuMarker), 0);
}
#endif
void PushExit(x86emu_t* emu)
{
Push(emu, (uint32_t)&EndEmuMarker);
@@ -195,7 +202,7 @@ void CloneEmu(x86emu_t *newemu, const x86emu_t* emu)
memcpy(&newemu->flags, &emu->flags, sizeof(emu->flags));
newemu->old_ip = emu->old_ip;
memcpy(newemu->segs, emu->segs, sizeof(emu->segs));
memset(newemu->segs_clean, 0, sizeof(newemu->segs_clean));
memset(newemu->segs_serial, 0, sizeof(newemu->segs_serial));
memcpy(newemu->fpu, emu->fpu, sizeof(emu->fpu));
memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
@@ -310,11 +317,7 @@ const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
// start with FPU regs...
if(emu->fpu_stack) {
for (int i=0; i<emu->fpu_stack; i++) {
#ifdef USE_FLOAT
sprintf(tmp, "ST%d=%f", i, emu->fpu[(emu->top+i)&7].f);
#else
sprintf(tmp, "ST%d=%f", i, emu->fpu[(emu->top+i)&7].d);
#endif
strcat(buff, tmp);
int c = 10-strlen(tmp);
if(c<1) c=1;
@@ -464,3 +467,10 @@ uint64_t ReadTSC(x86emu_t* emu)
return (uint64_t)(tv.tv_sec) * 1000000 + tv.tv_usec;
#endif
}
void ResetSegmentsCache(x86emu_t *emu)
{
if(!emu)
return;
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
}
+10 -3
View File
@@ -56,7 +56,7 @@ typedef struct x86emu_s {
// segments
uint32_t segs[6]; // only 32bits value?
uintptr_t segs_offs[6]; // computed offset associate with segment
int segs_clean[6]; // are seg offset clean (1) or does they need to be re-computed (0)?
uint32_t segs_serial[6]; // are seg offset clean (not 0) or does they need to be re-computed (0)? For GS, serial need to be the same as context->sel_serial
// emu control
int quit;
int error;
@@ -65,12 +65,13 @@ typedef struct x86emu_s {
int exit;
int quitonlongjmp; // quit if longjmp is called
int longjmp; // if quit because of longjmp
// parent context
box86context_t *context;
#ifdef DYNAREC
// virtual return stack
int cstacki; // current index
uint64_t cstack[CSTACK+1]; // pair of x86 address / native address for call/ret, using uint64_t for alignement, +1 for allignment
#endif
// parent context
box86context_t *context;
// cpu helpers
reg32_t zero;
reg32_t *sbiidx[8];
@@ -83,8 +84,14 @@ typedef struct x86emu_s {
i386_ucontext_t *uc_link; // to handle setcontext
int type; // EMUTYPE_xxx define
} x86emu_t;
#define EMUTYPE_NONE 0
#define EMUTYPE_MAIN 1
#define EMUTYPE_SIGNAL 2
//#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
+35 -5
View File
@@ -1,3 +1,5 @@
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <dlfcn.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -33,6 +35,7 @@ x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
for (int i=my_context->atfork_sz-1; i>=0; --i)
if(my_context->atforks[i].prepare)
EmuCall(emu, my_context->atforks[i].prepare);
int type = emu->type;
int v;
if(forktype==2) {
iFpppp_t forkpty = (iFpppp_t)emu->forkpty_info->f;
@@ -40,6 +43,8 @@ x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
emu->forkpty_info = NULL;
} else
v = fork();
if(type == EMUTYPE_MAIN)
thread_set_emu(emu);
if(v==EAGAIN || v==ENOMEM) {
// error...
} else if(v!=0) {
@@ -64,6 +69,9 @@ void x86Int3(x86emu_t* emu)
if(Peek(emu, 0)=='S' && Peek(emu, 1)=='C') // Signature for "Out of x86 door"
{
R_EIP += 2;
#ifdef RK3399
volatile // to avoid addr to be put in an VFPU register
#endif
uint32_t addr = Fetch32(emu);
if(addr==0) {
//printf_log(LOG_INFO, "%p:Exit x86 emu (emu=%p)\n", *(void**)(R_ESP), emu);
@@ -86,7 +94,13 @@ void x86Int3(x86emu_t* emu)
int post = 0;
int perr = 0;
uint32_t *pu32 = NULL;
const char *s = GetNativeName((void*)addr);
const char *s = NULL;
{
Dl_info info;
if(dladdr((void*)addr, &info))
s = info.dli_sname;
}
if(!s) s = GetNativeName((void*)addr);
if(addr==(uintptr_t)PltResolver) {
snprintf(buff, 256, "%s", " ... ");
} else
@@ -110,9 +124,16 @@ void x86Int3(x86emu_t* emu)
tmp = *(char**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
perr = 1;
} else if(strcmp(s, "mkdir")==0) {
tmp = *(char**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8));
perr = 1;
} else if(!strcmp(s, "fopen")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
perr = 1;
} else if(!strcmp(s, "freopen")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", %p)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(!strcmp(s, "fopen64")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
perr = 2;
@@ -137,6 +158,9 @@ void x86Int3(x86emu_t* emu)
} else if(strstr(s, "__xstat64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strcmp(s, "__xstat")==0) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "__lxstat64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
@@ -184,6 +208,12 @@ void x86Int3(x86emu_t* emu)
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "printf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if(strstr(s, "puts")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if(strstr(s, "fputs")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\"...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "fprintf")==s) {
pu32 = *(uint32_t**)(R_ESP+8);
if(((uintptr_t)pu32)<0x5) // probably a __fprint_chk
@@ -191,6 +221,10 @@ void x86Int3(x86emu_t* emu)
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
} else if(strstr(s, "vfprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(char**)(R_ESP+8));
} 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));
} else if(strstr(s, "vkGetDeviceProcAddr")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "sscanf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "XCreateWindow")==s) {
@@ -229,11 +263,7 @@ void x86Int3(x86emu_t* emu)
break;
case 3: snprintf(buff2, 63, "(%s)", pu32?((char*)pu32):"nil");
break;
#ifdef USE_FLOAT
case 4: snprintf(buff2, 63, " (%f)", ST0.f);
#else
case 4: snprintf(buff2, 63, " (%f)", ST0.d);
#endif
break;
case 5: {
uint32_t* p = (uint32_t*)R_EAX;
+2 -2
View File
@@ -891,7 +891,7 @@ uint16_t shld16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s)
CLEAR_FLAG(F_OF);
}
} else {
res = (fill << (cnt)) | (fill >> (16 - cnt));
res = (fill << (cnt)) | (d >> (16 - cnt));
if(s==16)
cf = d & 1;
else
@@ -965,7 +965,7 @@ uint16_t shrd16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s)
}
} else {
cf = fill & (1 << (cnt - 1));
res = (fill >> cnt) | (fill << (16 - cnt));
res = (fill >> cnt) | (d << (16 - cnt));
CONDITIONAL_SET_FLAG(cf, F_CF);
CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+120 -69
View File
@@ -19,6 +19,10 @@
#include "x87emu_private.h"
#include "box86context.h"
#include "my_cpuid.h"
#include "bridge.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
int my_setcontext(x86emu_t* emu, void* ucp);
@@ -39,7 +43,7 @@ int Run(x86emu_t *emu, int step)
double d;
float f;
int64_t ll;
sse_regs_t *opex, eax1, *opx2;
sse_regs_t *opex, eax1;
mmx_regs_t *opem, eam1;
if(emu->quit)
@@ -72,7 +76,7 @@ int Run(x86emu_t *emu, int step)
&&_0x48, &&_0x49, &&_0x4A, &&_0x4B, &&_0x4C, &&_0x4D, &&_0x4E, &&_0x4F,
&&_0x50, &&_0x51, &&_0x52, &&_0x53, &&_0x54, &&_0x55, &&_0x56, &&_0x57,
&&_0x58, &&_0x59, &&_0x5A, &&_0x5B, &&_0x5C, &&_0x5D, &&_0x5E, &&_0x5F,
&&_0x60, &&_0x61, &&_0x62, &&_default, &&_0x64, &&_0x65, &&_0x66, &&_0x67,
&&_0x60, &&_0x61, &&_0x62, &&_0x63, &&_0x64, &&_0x65, &&_0x66, &&_0x67,
&&_0x68, &&_0x69, &&_0x6A, &&_0x6B, &&_0x6C, &&_0x6D, &&_0x6E, &&_0x6F, //0x68-0x6F
&&_0x70_0, &&_0x70_1, &&_0x70_2, &&_0x70_3, &&_0x70_4, &&_0x70_5, &&_0x70_6, &&_0x70_7, //0x70-0x77
&&_0x70_8, &&_0x70_9, &&_0x70_A, &&_0x70_B, &&_0x70_C, &&_0x70_D, &&_0x70_E, &&_0x70_F, //0x78-0x7F
@@ -84,9 +88,9 @@ int Run(x86emu_t *emu, int step)
&&_0xA8, &&_0xA9, &&_0xAA, &&_0xAB, &&_0xAC, &&_0xAD, &&_0xAE, &&_0xAF,
&&_0xB0, &&_0xB1, &&_0xB2, &&_0xB3, &&_0xB4, &&_0xB5, &&_0xB6, &&_0xB7,
&&_0xB8, &&_0xB9, &&_0xBA, &&_0xBB, &&_0xBC, &&_0xBD, &&_0xBE, &&_0xBF,
&&_0xC0, &&_0xC1, &&_0xC2, &&_0xC3, &&_default, &&_default, &&_0xC6, &&_0xC7,
&&_0xC8, &&_0xC9, &&_default, &&_default, &&_0xCC, &&_0xCD, &&_default, &&_0xCF, //0xC8-0xCF
&&_0xD0, &&_0xD1, &&_0xD2, &&_0xD3, &&_0xD4, &&_0xD5, &&_default, &&_0xD7,
&&_0xC0, &&_0xC1, &&_0xC2, &&_0xC3, &&_0xC4, &&_0xC5, &&_0xC6, &&_0xC7,
&&_0xC8, &&_0xC9, &&_default, &&_0xCB, &&_0xCC, &&_0xCD, &&_default, &&_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,
&&_0xE8, &&_0xE9, &&_default, &&_0xEB, &&_0xEC, &&_0xED, &&_default, &&_default,
@@ -95,10 +99,10 @@ int Run(x86emu_t *emu, int step)
};
static const void* opcodes0f[256] = {
&&_0f_0x00, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
&&_0f_0x00, &&_0f_0x01, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
&&_default, &&_default, &&_default, &&_0f_0x0B, &&_default ,&&_default, &&_default, &&_default, //0x08-0x0F
&&_0f_0x10, &&_0f_0x11, &&_0f_0x12, &&_0f_0x13, &&_0f_0x14, &&_0f_0x15, &&_0f_0x16, &&_0f_0x17, //0x10-0x17
&&_0f_0x18, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_0f_0x1F, //0x18-0x1F
&&_0f_0x18, &&_default, &&_0f_0x1A, &&_0f_0x1B, &&_default ,&&_default, &&_default, &&_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
@@ -119,10 +123,10 @@ int Run(x86emu_t *emu, int step)
&&_0f_0xA8, &&_0f_0xA9, &&_default, &&_0f_0xAB, &&_0f_0xAC, &&_0f_0xAD, &&_0f_0xAE, &&_0f_0xAF,
&&_0f_0xB0, &&_0f_0xB1, &&_default, &&_0f_0xB3, &&_default, &&_default, &&_0f_0xB6, &&_0f_0xB7,
&&_default, &&_default, &&_0f_0xBA, &&_0f_0xBB, &&_0f_0xBC, &&_0f_0xBD, &&_0f_0xBE, &&_0f_0xBF,
&&_0f_0xC0, &&_0f_0xC1, &&_0f_0xC2, &&_default, &&_0f_0xC4, &&_0f_0xC5, &&_0f_0xC6, &&_0f_0xC7,
&&_0f_0xC0, &&_0f_0xC1, &&_0f_0xC2, &&_0f_0xC3, &&_0f_0xC4, &&_0f_0xC5, &&_0f_0xC6, &&_0f_0xC7,
&&_0f_0xC8, &&_0f_0xC9, &&_0f_0xCA, &&_0f_0xCB, &&_0f_0xCC, &&_0f_0xCD, &&_0f_0xCE, &&_0f_0xCF, //0xC8-0xCF
&&_default, &&_0f_0xD1, &&_0f_0xD2, &&_0f_0xD3, &&_0f_0xD4 ,&&_0f_0xD5, &&_default, &&_0f_0xD7, //0xD0-0xD7
&&_0f_0xD8, &&_0f_0xD9, &&_default, &&_0f_0xDB, &&_0f_0xDC ,&&_0f_0xDD, &&_default, &&_0f_0xDF, //0xD8-0xDF
&&_0f_0xD8, &&_0f_0xD9, &&_0f_0xDA, &&_0f_0xDB, &&_0f_0xDC ,&&_0f_0xDD, &&_0f_0xDE, &&_0f_0xDF, //0xD8-0xDF
&&_0f_0xE0, &&_0f_0xE1, &&_0f_0xE2, &&_0f_0xE3, &&_0f_0xE4 ,&&_0f_0xE5, &&_default, &&_0f_0xE7, //0xE0-0xE7
&&_0f_0xE8, &&_0f_0xE9, &&_0f_0xEA, &&_0f_0xEB, &&_0f_0xEC ,&&_0f_0xED, &&_0f_0xEE, &&_0f_0xEF, //0xE8-0xEF
&&_default, &&_0f_0xF1, &&_0f_0xF2, &&_0f_0xF3, &&_0f_0xF4 ,&&_0f_0xF5, &&_0f_0xF6, &&_0f_0xF7, //0xF0-0xF7
@@ -160,45 +164,10 @@ int Run(x86emu_t *emu, int step)
&&_default, &&_66_0xD9, &&_default, &&_default, &&_default ,&&_66_0xDD, &&_default, &&_default, //0xD8-0xDF
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xE0-0xE7
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xE8-0xEF
&&_default, &&_default, &&_66_0xF2, &&_66_0xF3, &&_default, &&_default, &&_default, &&_66_0xF7,
&&_66_0xF0, &&_default, &&_66_0xF2, &&_66_0xF3, &&_default, &&_default, &&_default, &&_66_0xF7,
&&_66_0xF8, &&_66_0xF9, &&_default, &&_default, &&_default, &&_default, &&_default, &&_66_0xFF
};
static const void* opcodes660f[256] = {
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x08-0x0F
&&_6f_0x10, &&_6f_0x11, &&_6f_0x12, &&_6f_0x13, &&_6f_0x14, &&_6f_0x15, &&_6f_0x16, &&_6f_0x17,
&&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_6f_0x1F,
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x20-0x27
&&_6f_0x28, &&_6f_0x29, &&_6f_0x2A, &&_default, &&_6f_0x2C, &&_6f_0x2D, &&_6f_0x2E, &&_6f_0x2F,
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x30-0x37
&&_6f_0x38, &&_default, &&_6f_0x3A, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x38-0x3F
&&_6f_0x40_0, &&_6f_0x40_1, &&_6f_0x40_2, &&_6f_0x40_3, &&_6f_0x40_4, &&_6f_0x40_5, &&_6f_0x40_6, &&_6f_0x40_7,
&&_6f_0x40_8, &&_6f_0x40_9, &&_6f_0x40_A, &&_6f_0x40_B, &&_6f_0x40_C, &&_6f_0x40_D, &&_6f_0x40_E, &&_6f_0x40_F,
&&_6f_0x50, &&_6f_0x51, &&_default, &&_default, &&_6f_0x54, &&_6f_0x55, &&_6f_0x56, &&_6f_0x57,
&&_6f_0x58, &&_6f_0x59, &&_6f_0x5A, &&_6f_0x5B, &&_6f_0x5C, &&_6f_0x5D, &&_6f_0x5E, &&_6f_0x5F,
&&_6f_0x60, &&_6f_0x61, &&_6f_0x62, &&_6f_0x63, &&_6f_0x64, &&_6f_0x65, &&_6f_0x66, &&_6f_0x67,
&&_6f_0x68, &&_6f_0x69, &&_6f_0x6A, &&_6f_0x6B, &&_6f_0x6C, &&_6f_0x6D, &&_6f_0x6E, &&_6f_0x6F,
&&_6f_0x70, &&_6f_0x71, &&_6f_0x72, &&_6f_0x73, &&_6f_0x74, &&_6f_0x75, &&_6f_0x76, &&_default,
&&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_6f_0x7E, &&_6f_0x7F, //0x78-0x7F
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x80-0x87
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x88-0x8F
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x90-0x97
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x98-0x9F
&&_default, &&_default, &&_default, &&_6f_0xA3, &&_6f_0xA4, &&_6f_0xA5, &&_default, &&_default,
&&_default, &&_default, &&_default, &&_6f_0xAB, &&_6f_0xAC, &&_6f_0xAD, &&_default, &&_6f_0xAF,
&&_default, &&_6f_0xB1, &&_default, &&_6f_0xB3, &&_default, &&_default, &&_6f_0xB6, &&_default,
&&_default, &&_default, &&_6f_0xBA, &&_6f_0xBB, &&_6f_0xBC, &&_6f_0xBD, &&_6f_0xBE, &&_default, //0xB8-0xBF
&&_default, &&_6f_0xC1, &&_6f_0xC2, &&_default, &&_6f_0xC4, &&_6f_0xC5, &&_6f_0xC6, &&_default,
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xC8-0xCF
&&_default, &&_6f_0xD1, &&_6f_0xD2, &&_6f_0xD3, &&_6f_0xD4, &&_6f_0xD5, &&_6f_0xD6, &&_6f_0xD7,
&&_6f_0xD8, &&_6f_0xD9, &&_default, &&_6f_0xDB, &&_6f_0xDC, &&_default, &&_6f_0xDE, &&_6f_0xDF,
&&_6f_0xE0, &&_6f_0xE1, &&_6f_0xE2, &&_6f_0xE3, &&_default, &&_6f_0xE5, &&_6f_0xE6, &&_6f_0xE7,
&&_6f_0xE8, &&_6f_0xE9, &&_6f_0xEA, &&_6f_0xEB, &&_6f_0xEC, &&_6f_0xED, &&_6f_0xEE, &&_6f_0xEF,
&&_default, &&_6f_0xF1, &&_6f_0xF2, &&_6f_0xF3, &&_6f_0xF4, &&_6f_0xF5, &&_6f_0xF6, &&_6f_0xF7,
&&_6f_0xF8, &&_6f_0xF9, &&_6f_0xFA, &&_6f_0xFB, &&_6f_0xFC, &&_6f_0xFD, &&_6f_0xFE, &&_default
};
x86emurun:
ip = R_EIP;
// UnpackFlags(emu);
@@ -294,7 +263,7 @@ _trace:
NEXT;
_0x07: /* POP ES */
emu->segs[_ES] = Pop(emu); // no check, no use....
emu->segs_clean[_ES] = 0;
emu->segs_serial[_ES] = 0;
NEXT;
_0x0E: /* PUSH CS */
@@ -309,7 +278,7 @@ _trace:
NEXT;
_0x17: /* POP SS */
emu->segs[_SS] = Pop(emu); // no check, no use....
emu->segs_clean[_SS] = 0;
emu->segs_serial[_SS] = 0;
NEXT;
_0x1E: /* PUSH DS */
@@ -317,7 +286,7 @@ _trace:
NEXT;
_0x1F: /* POP DS */
emu->segs[_DS] = Pop(emu); // no check, no use....
emu->segs_clean[_DS] = 0;
emu->segs_serial[_DS] = 0;
NEXT;
_0x26: /* ES: */
@@ -418,12 +387,19 @@ _trace:
GET_ED;
// ignoring the test for now
NEXT;
_0x63: /* ARPL Ew, Gw */
nextop = F8;
GET_EW;
// faking to always happy...
SET_FLAG(F_ZF);
NEXT;
_0x64: /* FS: */
emu->old_ip = R_EIP;
R_EIP = ip-1;
RunFS(emu); // implemented in Run66.c
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_0x65: /* GS: */
emu->old_ip = R_EIP;
@@ -431,6 +407,7 @@ _trace:
RunGS(emu); // implemented in Run66.c
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_0x66: /* Prefix to change width of intructions, so here, down to 16bits */
@@ -441,6 +418,7 @@ _trace:
Run67(emu); // implemented in Run66.c
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_0x68: /* Push Id */
@@ -629,6 +607,20 @@ _trace:
NEXT;
_0x86: /* XCHG Eb,Gb */
nextop = F8;
#ifdef DYNAREC
GET_EB;
if((nextop&0xC0)==0xC0) { // reg / reg: no lock
tmp8u = GB;
GB = EB->byte[0];
EB->byte[0] = tmp8u;
} else {
do {
tmp8u = arm_lock_read_b(EB);
} while(arm_lock_write_b(EB, GB));
GB = tmp8u;
}
// dynarec use need it's own mecanism
#else
GET_EB;
if((nextop&0xC0)!=0xC0)
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
@@ -637,9 +629,29 @@ _trace:
EB->byte[0] = tmp8u;
if((nextop&0xC0)!=0xC0)
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
NEXT;
_0x87: /* XCHG Ed,Gd */
nextop = F8;
#ifdef DYNAREC
GET_ED;
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;
if((nextop&0xC0)!=0xC0)
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
@@ -648,6 +660,7 @@ _trace:
ED->dword[0] = tmp32u;
if((nextop&0xC0)!=0xC0)
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
NEXT;
_0x88: /* MOV Eb,Gb */
nextop = F8;
@@ -683,7 +696,9 @@ _trace:
nextop = F8;
GET_EW;
emu->segs[((nextop&0x38)>>3)] = EW->word[0];
emu->segs_clean[((nextop&0x38)>>3)] = 0;
emu->segs_serial[((nextop&0x38)>>3)] = 0;
if(((nextop&0x38)>>3)==_FS)
default_fs = EW->word[0];
NEXT;
_0x8F: /* POP Ed */
nextop = F8;
@@ -878,7 +893,20 @@ _trace:
ip = Pop(emu);
STEP
NEXT;
_0xC4: /* LES Gd,Ed */
nextop = F8;
GET_ED;
emu->segs[_ES] = ED->word[0];
emu->segs_serial[_ES] = 0;
GD.dword[0] = *(uint32_t*)(((void*)ED)+2);
NEXT;
_0xC5: /* LDS Gd,Ed */
nextop = F8;
GET_ED;
emu->segs[_DS] = ED->word[0];
emu->segs_serial[_DS] = 0;
GD.dword[0] = *(uint32_t*)(((void*)ED)+2);
NEXT;
_0xC6: /* MOV Eb,Ib */
nextop = F8;
GET_EB;
@@ -911,6 +939,13 @@ _trace:
R_EBP = Pop(emu);
NEXT;
_0xCB: /* FAR RET */
ip = Pop(emu);
emu->segs[_CS] = Pop(emu); // no check, no use....
emu->segs_serial[_CS] = 0;
// need to check status of CS register!
STEP
NEXT;
_0xCC: /* INT 3 */
emu->old_ip = R_EIP;
R_EIP = ip;
@@ -940,7 +975,7 @@ _trace:
_0xCF: /* IRET */
ip = Pop(emu);
emu->segs[_CS] = Pop(emu);
emu->segs_clean[_CS] = 0;
emu->segs_serial[_CS] = 0;
emu->packed_eflags.x32 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
UnpackFlags(emu);
RESET_FLAGS(emu);
@@ -983,7 +1018,10 @@ _trace:
_0xD5: /* AAD Ib */
R_AX = aad16(emu, R_AX, F8);
NEXT;
_0xD6:
CHECK_FLAGS(emu);
R_AL = ACCESS_FLAG(F_CF)?0xFF:0x00;
NEXT;
_0xD7: /* XLAT */
R_AL = *(uint8_t*)(R_EBX + R_AL);
NEXT;
@@ -1019,6 +1057,7 @@ _trace:
--R_ECX; // don't update flags
if(R_ECX && !ACCESS_FLAG(F_ZF))
ip += tmp8s;
STEP
NEXT;
_0xE1: /* LOOPZ */
CHECK_FLAGS(emu);
@@ -1026,19 +1065,20 @@ _trace:
--R_ECX; // don't update flags
if(R_ECX && ACCESS_FLAG(F_ZF))
ip += tmp8s;
STEP
NEXT;
_0xE2: /* LOOP */
tmp8s = F8S;
--R_ECX; // don't update flags
if(R_ECX)
ip += tmp8s;
STEP
NEXT;
_0xE3: /* JECXZ */
tmp8s = F8S;
if(!R_ECX) {
if(!R_ECX)
ip += tmp8s;
STEP
}
STEP
NEXT;
_0xE4: /* IN AL, Ib */
tmp32s = F8; // port address
@@ -1099,6 +1139,7 @@ _trace:
} else {
#include "runf20f.h"
}
STEP
NEXT;
} else if(nextop==0x66) {
nextop = F8;
@@ -1185,6 +1226,7 @@ _trace:
case 0x1B:
case 0x1C:
case 0x1D:
case 0x25:
case 0x40:
case 0x41:
case 0x42:
@@ -1217,15 +1259,20 @@ _trace:
case 0x7D:
case 0x7E:
case 0x7F: /* BND / NOP */
case 0x86: /* XACQUIRE/XRELEASE XCHG */
case 0x87: /* XACQUIRE/XRELEASE XCHG */
case 0x88: /* XRELEASE MOV... */
case 0x89: /* XRELEASE MOV... ignoring acquire thingy */
case 0x9C:
case 0xC3: /* yup, repz ret is valid */
case 0xE8:
case 0xE9:
case 0xEB:
case 0xF0: /* XACQUIRE/XRELEASE LOCK ... ignoring acquire thingy */
--ip;
NEXT;
case 0x90: /* PAUSE */
NEXT;
case 0xC3: /* REPZ RET... yup */
ip = Pop(emu);
NEXT;
case 0xA4: /* REP MOVSB */
while(tmp32u) {
--tmp32u;
@@ -1460,6 +1507,7 @@ _trace:
NEXT;
_0xFE: /* GRP 5 Eb */
nextop = F8;
tmp32u2 = ip;
GET_EB;
switch((nextop>>3)&7) {
case 0: /* INC Eb */
@@ -1470,8 +1518,8 @@ _trace:
break;
default:
emu->old_ip = R_EIP;
R_EIP = ip;
printf_log(LOG_NONE, "Illegal Opcode %02X %02X\n", opcode, nextop);
R_EIP = ip = tmp32u2;
printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X\n", (void*)ip, opcode, nextop, PK(2), PK(3));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
goto fini;
@@ -1479,6 +1527,7 @@ _trace:
NEXT;
_0xFF: /* GRP 5 Ed */
nextop = F8;
tmp32u2 = ip;
GET_ED;
switch((nextop>>3)&7) {
case 0: /* INC Ed */
@@ -1488,15 +1537,16 @@ _trace:
ED->dword[0] = dec32(emu, ED->dword[0]);
break;
case 2: /* CALL NEAR Ed */
tmp32u = (uintptr_t)getAlternate((void*)ED->dword[0]);
Push(emu, ip);
ip = ED->dword[0]; // should get value in temp var. in case ED use ESP?
ip = tmp32u;
STEP
break;
case 3: /* CALL FAR Ed */
if(nextop>0xc0) {
emu->old_ip = R_EIP;
R_EIP = ip;
printf_log(LOG_NONE, "Illegal Opcode %02X %02X\n", opcode, nextop);
R_EIP = ip = tmp32u2;
printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X\n", (void*)ip, opcode, nextop, PK(2), PK(3));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
goto fini;
@@ -1509,14 +1559,14 @@ _trace:
}
break;
case 4: /* JMP NEAR Ed */
ip = ED->dword[0];
ip = (uintptr_t)getAlternate((void*)ED->dword[0]);
STEP
break;
case 5: /* JMP FAR Ed */
if(nextop>0xc0) {
emu->old_ip = R_EIP;
R_EIP = ip;
printf_log(LOG_NONE, "Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
R_EIP = ip = tmp32u2;
printf_log(LOG_NONE, "Illegal Opcode %p: 0x%02X 0x%02X %02X %02X\n", (void*)ip, opcode, nextop, PK(2), PK(3));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
goto fini;
@@ -1527,12 +1577,13 @@ _trace:
}
break;
case 6: /* Push Ed */
Push(emu, ED->dword[0]);
tmp32u = ED->dword[0];
Push(emu, tmp32u); // avoid potential issue with push [esp+...]
break;
default:
emu->old_ip = R_EIP;
R_EIP = ip;
printf_log(LOG_NONE, "Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
R_EIP = ip = tmp32u2;
printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X %02X %02X\n",(void*)ip, opcode, nextop, PK(2), PK(3), PK(4), PK(5));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
goto fini;
+449 -67
View File
@@ -11,6 +11,9 @@
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
#define F8 *(uint8_t*)(ip++)
@@ -28,14 +31,13 @@ void Run6766(x86emu_t *emu)
uintptr_t ip = R_EIP+2; //skip 67 66
uint8_t opcode = F8;
uint8_t nextop;
reg32_t *op1, *op2;
reg32_t *oped;
switch(opcode) {
case 0x8D: /* LEA Gw,Ew */
nextop = F8;
op1=GetEw16(emu, nextop);
op2=GetG(emu, nextop);
op2->word[0] = (uint16_t)(uintptr_t)op1;
GET_EW16;
GW.word[0] = (uint16_t)(uintptr_t)ED;
break;
@@ -52,11 +54,63 @@ void Run67(x86emu_t *emu)
uint8_t opcode = F8;
int8_t tmp8s;
int32_t tmp32s;
uint32_t tmp32u;
uintptr_t tlsdata;
reg32_t *oped;
uint8_t nextop;
switch(opcode) {
case 0x64:
opcode = F8;
tlsdata = GetFSBaseEmu(emu);
switch(opcode) {
case 0x89: /* MOV ED16,Gd */
nextop = F8;
GET_EW16_OFFS(tlsdata);
ED->dword[0] = GD.dword[0];
break;
case 0x8B: /* MOV Gd,Ed16 */
nextop = F8;
GET_EW16_OFFS(tlsdata);
GD.dword[0] = ED->dword[0];
break;
case 0x8F: /* POP FS:Ed */
nextop = F8;
GET_EW16_OFFS(tlsdata);
ED->dword[0] = Pop(emu);
break;
case 0xA1: /* MOV EAX,Ov16 */
tmp32u = F16;
R_EAX = *(uint32_t*)(tlsdata + tmp32u);
break;
case 0xA3: /* MOV Ov16,EAX */
tmp32u = F16;
*(uint32_t*)(tlsdata + tmp32u) = R_EAX;
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
switch((nextop>>3)&7) {
case 6: /* Push Ed */
GET_EW16_OFFS(tlsdata);
Push(emu, ED->dword[0]);
break;
default:
ip-=2;
UnimpOpcode(emu);
}
break;
default:
ip-=2;
UnimpOpcode(emu);
}
break;
case 0x66: /* MoooRE opcodes */
Run6766(emu);
break;
return;
case 0x6C: /* INSB */
*(int8_t*)(R_DI+GetESBaseEmu(emu)) = 0; // faking port read, using actual segment ES, just in case
@@ -71,31 +125,31 @@ void Run67(x86emu_t *emu)
tmp8s = F8S;
--R_CX; // don't update flags
if(R_CX && !ACCESS_FLAG(F_ZF))
R_EIP += tmp8s;
ip += tmp8s;
break;
case 0xE1: /* LOOPZ */
CHECK_FLAGS(emu);
tmp8s = F8S;
--R_CX; // don't update flags
if(R_CX && ACCESS_FLAG(F_ZF))
R_EIP += tmp8s;
ip += tmp8s;
break;
case 0xE2: /* LOOP */
tmp8s = F8S;
--R_CX; // don't update flags
if(R_CX)
R_EIP += tmp8s;
ip += tmp8s;
break;
case 0xE3: /* JCXZ */
tmp8s = F8S;
if(!R_CX)
R_EIP += tmp8s;
ip += tmp8s;
break;
case 0xE8: /* CALL Id */
tmp32s = F32S; // call is relative
Push(emu, R_EIP);
R_EIP += tmp32s;
Push(emu, ip);
ip += tmp32s;
break;
default:
@@ -111,20 +165,29 @@ void RunLock(x86emu_t *emu)
uint8_t nextop;
reg32_t *oped;
uint8_t tmp8u;
#ifdef DYNAREC
uint8_t tmp8u2;
#endif
uint32_t tmp32u, tmp32u2;
int32_t tmp32s;
pthread_mutex_lock(&emu->context->mutex_lock);
switch(opcode) {
#ifdef DYNAREC
#define GO(B, OP) \
case B+0: \
nextop = F8; \
GET_EB; \
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
do { \
tmp8u = arm_lock_read_b(EB); \
tmp8u = OP##8(emu, tmp8u, GB); \
} while (arm_lock_write_b(EB, tmp8u)); \
break; \
case B+1: \
nextop = F8; \
GET_ED; \
ED->dword[0] = OP##32(emu, ED->dword[0], GD.dword[0]); \
do { \
tmp32u = arm_lock_read_d(ED); \
tmp32u = OP##32(emu, tmp32u, GD.dword[0]); \
} while (arm_lock_write_d(ED, tmp32u)); \
break; \
case B+2: \
nextop = F8; \
@@ -142,7 +205,47 @@ void RunLock(x86emu_t *emu)
case B+5: \
R_EAX = OP##32(emu, R_EAX, F32); \
break;
#else
#define GO(B, OP) \
case B+0: \
nextop = F8; \
GET_EB; \
pthread_mutex_lock(&emu->context->mutex_lock);\
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
pthread_mutex_unlock(&emu->context->mutex_lock);\
break; \
case B+1: \
nextop = F8; \
GET_ED; \
pthread_mutex_lock(&emu->context->mutex_lock);\
ED->dword[0] = OP##32(emu, ED->dword[0], GD.dword[0]); \
pthread_mutex_unlock(&emu->context->mutex_lock);\
break; \
case B+2: \
nextop = F8; \
GET_EB; \
pthread_mutex_lock(&emu->context->mutex_lock);\
GB = OP##8(emu, GB, EB->byte[0]); \
pthread_mutex_unlock(&emu->context->mutex_lock);\
break; \
case B+3: \
nextop = F8; \
GET_ED; \
pthread_mutex_lock(&emu->context->mutex_lock);\
GD.dword[0] = OP##32(emu, GD.dword[0], ED->dword[0]); \
pthread_mutex_unlock(&emu->context->mutex_lock);\
break; \
case B+4: \
pthread_mutex_lock(&emu->context->mutex_lock);\
R_AL = OP##8(emu, R_AL, F8); \
pthread_mutex_unlock(&emu->context->mutex_lock);\
break; \
case B+5: \
pthread_mutex_lock(&emu->context->mutex_lock);\
R_EAX = OP##32(emu, R_EAX, F32); \
pthread_mutex_unlock(&emu->context->mutex_lock);\
break;
#endif
GO(0x00, add) /* ADD 0x00 -> 0x05 */
GO(0x08, or) /* OR 0x08 -> 0x0D */
GO(0x10, adc) /* ADC 0x10 -> 0x15 */
@@ -159,22 +262,52 @@ void RunLock(x86emu_t *emu)
CHECK_FLAGS(emu);
nextop = F8;
GET_EB;
#ifdef DYNAREC
do {
tmp8u = arm_lock_read_b(EB);
cmp8(emu, R_AL, tmp8u);
if(ACCESS_FLAG(F_ZF)) {
tmp32s = arm_lock_write_b(EB, GB);
} else {
R_AL = tmp8u;
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
cmp8(emu, R_AL, EB->byte[0]);
if(ACCESS_FLAG(F_ZF)) {
EB->byte[0] = GB;
} else {
R_AL = EB->byte[0];
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xB1: /* CMPXCHG Ed,Gd */
nextop = F8;
GET_ED;
#ifdef DYNAREC
do {
tmp32u = arm_lock_read_d(ED);
cmp32(emu, R_EAX, tmp32u);
if(ACCESS_FLAG(F_ZF)) {
tmp32s = arm_lock_write_d(ED, GD.dword[0]);
} else {
R_EAX = tmp32u;
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
cmp32(emu, R_EAX, ED->dword[0]);
if(ACCESS_FLAG(F_ZF)) {
ED->dword[0] = GD.dword[0];
} else {
R_EAX = ED->dword[0];
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xB3: /* BTR Ed,Gd */
CHECK_FLAGS(emu);
@@ -186,11 +319,27 @@ void RunLock(x86emu_t *emu)
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
tmp8u&=31;
#ifdef DYNAREC
do {
tmp32u = arm_lock_read_d(ED);
if(tmp32u & (1<<tmp8u)) {
SET_FLAG(F_CF);
tmp32u ^= (1<<tmp8u);
tmp32s = arm_lock_write_d(ED, tmp32u);
} else {
CLEAR_FLAG(F_CF);
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xBA:
nextop = F8;
@@ -204,10 +353,19 @@ void RunLock(x86emu_t *emu)
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
tmp8u&=31;
#ifdef DYNAREC
if(arm_lock_read_d(ED) & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 6: /* BTR Ed, Ib */
CHECK_FLAGS(emu);
@@ -218,15 +376,31 @@ void RunLock(x86emu_t *emu)
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
tmp8u&=31;
#ifdef DYNAREC
do {
tmp32u = arm_lock_read_d(ED);
if(tmp32u & (1<<tmp8u)) {
SET_FLAG(F_CF);
tmp32u ^= (1<<tmp8u);
tmp32s = arm_lock_write_d(ED, tmp32u);
} else {
CLEAR_FLAG(F_CF);
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
ip -= 3; //unfetch
ip -= 2; //unfetchall 0F BA but not F0, continue normal without LOCK
break;
}
break;
@@ -240,30 +414,105 @@ void RunLock(x86emu_t *emu)
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
tmp8u&=31;
#ifdef DYNAREC
do {
tmp32u = arm_lock_read_d(ED);
if(tmp32u & (1<<tmp8u)) {
SET_FLAG(F_CF);
} else {
CLEAR_FLAG(F_CF);
}
tmp32u ^= (1<<tmp8u);
} while(arm_lock_write_d(ED, tmp32u));
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xC0: /* XADD Gb,Eb */
nextop = F8;
GET_EB;
#ifdef DYNAREC
do {
tmp8u = arm_lock_read_b(EB);
tmp8u2 = add8(emu, tmp8u, GB);
} while (arm_lock_write_b(EB, tmp8u2));
GB = tmp8u;
#else
pthread_mutex_lock(&emu->context->mutex_lock);
tmp8u = add8(emu, EB->byte[0], GB);
GB = EB->byte[0];
EB->byte[0] = tmp8u;
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xC1: /* XADD Gd,Ed */
nextop = F8;
GET_ED;
#ifdef DYNAREC
do {
tmp32u = arm_lock_read_d(ED);
tmp32u2 = add32(emu, tmp32u, GD.dword[0]);
} while(arm_lock_write_d(ED, tmp32u2));
GD.dword[0] = tmp32u;
#else
pthread_mutex_lock(&emu->context->mutex_lock);
tmp32u = add32(emu, ED->dword[0], GD.dword[0]);
GD.dword[0] = ED->dword[0];
ED->dword[0] = tmp32u;
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xC7: /* CMPXCHG8B Gq */
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
#ifdef DYNAREC
if(((uintptr_t)ED)&7) {
// unaligned!!!
uint64_t ref = R_EDX;
ref = ref<<32 | R_EAX;
void* p = (void*)(((uintptr_t)ED + 3)&~3);
int d = (((uintptr_t)p - (uintptr_t)ED))*8;
do {
uint64_t m = *(uint64_t*)ED;
m&=~((0xffffffffLL)<<d);
tmp32u = arm_lock_read_d(p);
m|=((uint64_t)tmp32u)<<d;
if(ref == m) {
SET_FLAG(F_ZF);
m = ((uint64_t)R_ECX)<<32 | R_EBX;
tmp32u2 = m>>d;
tmp32s = arm_lock_write_d(p, tmp32u2);
if(!tmp32s)
*(uint64_t*)ED = m;
} else {
CLEAR_FLAG(F_ZF);
R_EAX = m&0xffffffff;
R_EDX = m>>32;
tmp32s = 0;
}
} while(tmp32s);
} else
do {
arm_lock_read_dd(&tmp32u, &tmp32u2, ED);
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
SET_FLAG(F_ZF);
tmp32s = arm_lock_write_dd(R_EBX, R_ECX, ED);
} else {
CLEAR_FLAG(F_ZF);
R_EAX = tmp32u;
R_EDX = tmp32u2;
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
tmp32u = ED->dword[0];
tmp32u2= ED->dword[1];
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
@@ -275,10 +524,12 @@ void RunLock(x86emu_t *emu)
R_EAX = tmp32u;
R_EDX = tmp32u2;
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
// trigger invalid lock?
ip -= 2; // unfetch
ip -= 1; // unfetch 0F but not F0
break;
}
break;
@@ -292,6 +543,19 @@ void RunLock(x86emu_t *emu)
tmp32u = (uint32_t)tmp32s;
} else
tmp32u = F32;
#ifdef DYNAREC
switch((nextop>>3)&7) {
case 0: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, add32(emu, tmp32u2, tmp32u))); break;
case 1: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, or32(emu, tmp32u2, tmp32u))); break;
case 2: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, adc32(emu, tmp32u2, tmp32u))); break;
case 3: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, sbb32(emu, tmp32u2, tmp32u))); break;
case 4: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, and32(emu, tmp32u2, tmp32u))); break;
case 5: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, sub32(emu, tmp32u2, tmp32u))); break;
case 6: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, xor32(emu, tmp32u2, tmp32u))); break;
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
switch((nextop>>3)&7) {
case 0: ED->dword[0] = add32(emu, ED->dword[0], tmp32u); break;
case 1: ED->dword[0] = or32(emu, ED->dword[0], tmp32u); break;
@@ -302,33 +566,51 @@ void RunLock(x86emu_t *emu)
case 6: ED->dword[0] = xor32(emu, ED->dword[0], tmp32u); break;
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0x86: /* XCHG Eb,Gb */
nextop = F8;
GET_EB;
tmp8u = GB;
GB = EB->byte[0];
EB->byte[0] = tmp8u;
break;
case 0x87: /* XCHG Ed,Gd */
nextop = F8;
GET_ED;
tmp32u = GD.dword[0];
GD.dword[0] = ED->dword[0];
ED->dword[0] = tmp32u;
ip--; // let the normal XCHG execute, it have integrated LOCK
break;
case 0x90: // This is xchg reg, reg, so let's ignore the LOCK prefix...
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
ip--;
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
GET_ED;
switch((nextop>>3)&7) {
case 0: /* INC Ed */
#ifdef DYNAREC
do {
tmp32u = arm_lock_read_d(ED);
} while(arm_lock_write_d(ED, inc32(emu, tmp32u)));
#else
pthread_mutex_lock(&emu->context->mutex_lock);
ED->dword[0] = inc32(emu, ED->dword[0]);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 1: /* DEC Ed */
#ifdef DYNAREC
do {
tmp32u = arm_lock_read_d(ED);
} while(arm_lock_write_d(ED, dec32(emu, tmp32u)));
#else
pthread_mutex_lock(&emu->context->mutex_lock);
ED->dword[0] = dec32(emu, ED->dword[0]);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0x%02X 0x%02X\n", opcode, PK(0));
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xFF 0x%02X 0x%02X\n", nextop, PK(0));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
break;
@@ -337,10 +619,60 @@ void RunLock(x86emu_t *emu)
default:
//UnimpOpcode(emu);
// should trigger invalid unlock ?
ip--; // "unfetch" to use normal instruction
ip--; // unfetch "nextop", discard F0 to use normal instruction
}
R_EIP = ip;
}
void RunLock66(x86emu_t *emu)
{
uintptr_t ip = R_EIP+1;
uint8_t opcode = F8;
uint8_t nextop;
reg32_t *oped;
uint16_t tmp16u;
int32_t tmp32s;
switch(opcode) {
case 0x0f:
opcode = F8;
switch (opcode) {
case 0xB1: /* CMPXCHG Ew,Gw */
nextop = F8;
GET_EW;
#ifdef DYNAREC
do {
tmp16u = arm_lock_read_h(ED);
cmp16(emu, R_AX, tmp16u);
if(ACCESS_FLAG(F_ZF)) {
tmp32s = arm_lock_write_h(ED, GW.word[0]);
} else {
R_AX = tmp16u;
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
GET_EW;
cmp16(emu, R_AX, EW->word[0]);
if(ACCESS_FLAG(F_ZF)) {
EW->word[0] = GW.word[0];
} else {
R_AX = EW->word[0];
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
ip-=4; // unfetch nextop, 0F, F0 & 66
UnimpOpcode(emu);
}
break;
default:
ip-=3; // unfetch nextop, F0 & 66
UnimpOpcode(emu);
// should trigger invalid unlock ?
}
R_EIP = ip;
pthread_mutex_unlock(&emu->context->mutex_lock);
}
void RunGS(x86emu_t *emu)
@@ -506,6 +838,11 @@ void RunGS(x86emu_t *emu)
ED->dword[0] = F32;
break;
case 0xE9:
case 0xEB:
--ip; // ignore FS: to execute regular opcode
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
@@ -517,8 +854,9 @@ void RunGS(x86emu_t *emu)
ED->dword[0] = dec32(emu, ED->dword[0]);
break;
case 2: /* CALL NEAR Ed */
Push(emu, R_EIP);
R_EIP = ED->dword[0]; // should get value in temp var. in case ED use ESP?
R_EIP = ED->dword[0];
Push(emu, ip);
ip = R_EIP;
break;
case 3: /* CALL FAR Ed */
if(nextop>0xc0) {
@@ -527,13 +865,13 @@ void RunGS(x86emu_t *emu)
emu->error |= ERR_ILLEGAL;
} else {
Push16(emu, R_CS);
Push(emu, R_EIP);
R_EIP = ED->dword[0];
Push(emu, ip);
ip = ED->dword[0];
R_CS = (ED+1)->word[0];
}
break;
case 4: /* JMP NEAR Ed */
R_EIP = ED->dword[0];
ip = ED->dword[0];
break;
case 5: /* JMP FAR Ed */
if(nextop>0xc0) {
@@ -541,7 +879,7 @@ void RunGS(x86emu_t *emu)
emu->quit=1;
emu->error |= ERR_ILLEGAL;
} else {
R_EIP = ED->dword[0];
ip = ED->dword[0];
R_CS = (ED+1)->word[0];
}
break;
@@ -570,9 +908,31 @@ void RunFS(x86emu_t *emu)
uint8_t tmp8u;
uint32_t tmp32u;
int32_t tmp32s;
int16_t tmp16s;
uintptr_t tlsdata = GetFSBaseEmu(emu);
switch(opcode) {
case 0x01: /* ADD FS:Ed, Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = add32(emu, ED->dword[0], GD.dword[0]);
break;
case 0x03: /* ADD Gd, FS:Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = add32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x11: /* ADC FS:Ed, Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = adc32(emu, ED->dword[0], GD.dword[0]);
case 0x2B: /* SUB Gd, FS:Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = sub32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x33: /* XOR Gd,Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
@@ -584,32 +944,24 @@ void RunFS(x86emu_t *emu)
cmp32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x54: /* PUSH ESP */
tmp32u = R_ESP;
R_ESP -= 4;
*((uint32_t*)(R_ESP+tlsdata)) = tmp32u; //Push(emu, tmp32u);
break;
case 0x50:
case 0x50: /* PUSH Reg */
case 0x51:
case 0x52:
case 0x53:
case 0x54: /* PUSH ESP */
case 0x55:
case 0x56:
case 0x57: /* PUSH Reg */
tmp8u = opcode&7;
*((uint32_t*)(R_ESP+tlsdata)) = emu->regs[tmp8u].dword[0]; //Push(emu, emu->regs[tmp8u].dword[0]);
break;
case 0x58:
case 0x57:
case 0x58: /* POP Reg */
case 0x59:
case 0x5A:
case 0x5B:
case 0x5C: /* POP ESP */
case 0x5C: /* POP ESP */
case 0x5D:
case 0x5E:
case 0x5F: /* POP Reg */
tmp8u = opcode&7;
emu->regs[tmp8u].dword[0] = *((uint32_t*)(R_ESP+tlsdata)); // Pop(emu);
R_ESP += 4;
case 0x5F:
// Segment override if for memory loc, no stack segment
--ip; // so ignore prefix and continue
break;
case 0x67:
@@ -617,27 +969,35 @@ void RunFS(x86emu_t *emu)
switch(opcode) {
case 0x89: /* MOV ED16,Gd */
nextop = F8;
oped=GetEw16off(emu, nextop, tlsdata);
GET_EW16_OFFS(tlsdata);
ED->dword[0] = GD.dword[0];
break;
case 0x8B: /* MOV Gd,Ed16 */
nextop = F8;
oped=GetEw16off(emu, nextop, tlsdata);
GET_EW16_OFFS(tlsdata);
GD.dword[0] = ED->dword[0];
break;
case 0x8F: /* POP FS:Ed */
nextop = F8;
GET_EW16_OFFS(tlsdata);
ED->dword[0] = Pop(emu);
break;
case 0xA1: /* MOV EAX,Ov16 */
tmp16s = F16S;
R_EAX = *(uint32_t*)((tlsdata) + tmp16s);
tmp32u = F16;
R_EAX = *(uint32_t*)(tlsdata + tmp32u);
break;
case 0xA3: /* MOV Ov16,EAX */
tmp16s = F16S;
*(uint32_t*)((tlsdata) + tmp16s) = R_EAX;
tmp32u = F16;
*(uint32_t*)(tlsdata + tmp32u) = R_EAX;
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
switch((nextop>>3)&7) {
case 6: /* Push Ed */
oped=GetEw16off(emu, nextop, tlsdata);
GET_EW16_OFFS(tlsdata);
Push(emu, ED->dword[0]);
break;
default:
@@ -703,11 +1063,27 @@ void RunFS(x86emu_t *emu)
GET_ED_OFFS(tlsdata);
GD.dword[0] = ED->dword[0];
break;
case 0x8C: /* MOV FS:Ed, Seg */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = emu->segs[((nextop&0x38)>>3)];
break;
case 0x8E: /* MOV Seg,FS:Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
emu->segs[((nextop&0x38)>>3)] = ED->word[0];
emu->segs_serial[((nextop&0x38)>>3)] = 0;
break;
case 0x8F: /* POP Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = Pop(emu);
break;
case 0xA0: /* MOV AL,Ob */
tmp32s = F32S;
R_AL = *(uint8_t*)((tlsdata) + tmp32s);
break;
case 0xA1: /* MOV EAX,Ov */
tmp32s = F32S;
R_EAX = *(uint32_t*)((tlsdata) + tmp32s);
@@ -748,6 +1124,11 @@ void RunFS(x86emu_t *emu)
ED->dword[0] = F32;
break;
case 0xE9:
case 0xEB:
--ip; // ignore FS: to execute regular opcode
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
@@ -759,8 +1140,9 @@ void RunFS(x86emu_t *emu)
ED->dword[0] = dec32(emu, ED->dword[0]);
break;
case 2: /* CALL NEAR Ed */
Push(emu, R_EIP);
R_EIP = ED->dword[0]; // should get value in temp var. in case ED use ESP?
R_EIP = ED->dword[0];
Push(emu, ip);
ip = R_EIP;
break;
case 3: /* CALL FAR Ed */
if(nextop>0xc0) {
@@ -769,13 +1151,13 @@ void RunFS(x86emu_t *emu)
emu->error |= ERR_ILLEGAL;
} else {
Push16(emu, R_CS);
Push(emu, R_EIP);
R_EIP = ED->dword[0];
Push(emu, ip);
ip = ED->dword[0];
R_CS = (ED+1)->word[0];
}
break;
case 4: /* JMP NEAR Ed */
R_EIP = ED->dword[0];
ip = ED->dword[0];
break;
case 5: /* JMP FAR Ed */
if(nextop>0xc0) {
@@ -783,7 +1165,7 @@ void RunFS(x86emu_t *emu)
emu->quit=1;
emu->error |= ERR_ILLEGAL;
} else {
R_EIP = ED->dword[0];
ip = ED->dword[0];
R_CS = (ED+1)->word[0];
}
break;
+374 -60
View File
@@ -1,6 +1,90 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#define F8 *(uint8_t*)(ip++)
#define F8S *(int8_t*)(ip++)
#define F16 *(uint16_t*)(ip+=2, ip-2)
#define F16S *(int16_t*)(ip+=2, ip-2)
#define F32 *(uint32_t*)(ip+=4, ip-4)
#define F32S *(int32_t*)(ip+=4, ip-4)
#define PK(a) *(uint8_t*)(ip+a)
#include "modrm.h"
void Run660F(x86emu_t *emu)
{
uintptr_t ip = R_EIP+2; //skip 66 0F
uint8_t opcode;
uint8_t nextop;
reg32_t *oped;
uint8_t tmp8u;
int8_t tmp8s;
uint16_t tmp16u;
int16_t tmp16s;
uint32_t tmp32u;
int32_t tmp32s;
sse_regs_t *opex, eax1, *opx2;
mmx_regs_t *opem;
static const void* opcodes660f[256] = {
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x08-0x0F
&&_6f_0x10, &&_6f_0x11, &&_6f_0x12, &&_6f_0x13, &&_6f_0x14, &&_6f_0x15, &&_6f_0x16, &&_6f_0x17,
&&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_6f_0x1F,
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x20-0x27
&&_6f_0x28, &&_6f_0x29, &&_6f_0x2A, &&_default, &&_6f_0x2C, &&_6f_0x2D, &&_6f_0x2E, &&_6f_0x2F,
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x30-0x37
&&_6f_0x38, &&_default, &&_6f_0x3A, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x38-0x3F
&&_6f_0x40_0, &&_6f_0x40_1, &&_6f_0x40_2, &&_6f_0x40_3, &&_6f_0x40_4, &&_6f_0x40_5, &&_6f_0x40_6, &&_6f_0x40_7,
&&_6f_0x40_8, &&_6f_0x40_9, &&_6f_0x40_A, &&_6f_0x40_B, &&_6f_0x40_C, &&_6f_0x40_D, &&_6f_0x40_E, &&_6f_0x40_F,
&&_6f_0x50, &&_6f_0x51, &&_default, &&_default, &&_6f_0x54, &&_6f_0x55, &&_6f_0x56, &&_6f_0x57,
&&_6f_0x58, &&_6f_0x59, &&_6f_0x5A, &&_6f_0x5B, &&_6f_0x5C, &&_6f_0x5D, &&_6f_0x5E, &&_6f_0x5F,
&&_6f_0x60, &&_6f_0x61, &&_6f_0x62, &&_6f_0x63, &&_6f_0x64, &&_6f_0x65, &&_6f_0x66, &&_6f_0x67,
&&_6f_0x68, &&_6f_0x69, &&_6f_0x6A, &&_6f_0x6B, &&_6f_0x6C, &&_6f_0x6D, &&_6f_0x6E, &&_6f_0x6F,
&&_6f_0x70, &&_6f_0x71, &&_6f_0x72, &&_6f_0x73, &&_6f_0x74, &&_6f_0x75, &&_6f_0x76, &&_default,
&&_default, &&_default, &&_default, &&_default, &&_6f_0x7C, &&_default, &&_6f_0x7E, &&_6f_0x7F, //0x78-0x7F
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x80-0x87
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x88-0x8F
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x90-0x97
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x98-0x9F
&&_default, &&_default, &&_default, &&_6f_0xA3, &&_6f_0xA4, &&_6f_0xA5, &&_default, &&_default,
&&_default, &&_default, &&_default, &&_6f_0xAB, &&_6f_0xAC, &&_6f_0xAD, &&_default, &&_6f_0xAF,
&&_default, &&_6f_0xB1, &&_default, &&_6f_0xB3, &&_default, &&_default, &&_6f_0xB6, &&_6f_0xB7,
&&_default, &&_default, &&_6f_0xBA, &&_6f_0xBB, &&_6f_0xBC, &&_6f_0xBD, &&_6f_0xBE, &&_default, //0xB8-0xBF
&&_default, &&_6f_0xC1, &&_6f_0xC2, &&_default, &&_6f_0xC4, &&_6f_0xC5, &&_6f_0xC6, &&_default,
&&_6f_0xC8, &&_6f_0xC9, &&_6f_0xCA, &&_6f_0xCB, &&_6f_0xCC ,&&_6f_0xCD, &&_6f_0xCE, &&_6f_0xCF, //0xC8-0xCF
&&_default, &&_6f_0xD1, &&_6f_0xD2, &&_6f_0xD3, &&_6f_0xD4, &&_6f_0xD5, &&_6f_0xD6, &&_6f_0xD7,
&&_6f_0xD8, &&_6f_0xD9, &&_6f_0xDA, &&_6f_0xDB, &&_6f_0xDC, &&_6f_0xDD, &&_6f_0xDE, &&_6f_0xDF,
&&_6f_0xE0, &&_6f_0xE1, &&_6f_0xE2, &&_6f_0xE3, &&_6f_0xE4, &&_6f_0xE5, &&_6f_0xE6, &&_6f_0xE7,
&&_6f_0xE8, &&_6f_0xE9, &&_6f_0xEA, &&_6f_0xEB, &&_6f_0xEC, &&_6f_0xED, &&_6f_0xEE, &&_6f_0xEF,
&&_default, &&_6f_0xF1, &&_6f_0xF2, &&_6f_0xF3, &&_6f_0xF4, &&_6f_0xF5, &&_6f_0xF6, &&_6f_0xF7,
&&_6f_0xF8, &&_6f_0xF9, &&_6f_0xFA, &&_6f_0xFB, &&_6f_0xFC, &&_6f_0xFD, &&_6f_0xFE, &&_default
};
#define NEXT goto _fini
opcode = F8;
goto *opcodes660f[opcode];
_default:
emu->old_ip = R_EIP;
R_EIP = ip;
UnimpOpcode(emu);
goto _fini;
#define GOCOND(BASE, PREFIX, CONDITIONAL) \
_6f_##BASE##_0: \
PREFIX \
@@ -211,21 +295,123 @@
nextop = F8;
GET_EX;
eax1 = GX;
for (int i=0; i<15; ++i) {
for (int i=0; i<16; ++i) {
if(EX->ub[i]&128)
GX.ub[i] = 0;
else
GX.ub[i] = eax1.ub[EX->ub[i]&15];
}
break;
case 0x01: /* PHADDW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<4; ++i)
GX.sw[i] = GX.sw[i*2+0]+GX.sw[i*2+1];
if(&GX == EX) {
GX.q[1] = GX.q[0];
} else {
for (int i=0; i<4; ++i)
GX.sw[4+i] = EX->sw[i*2+0] + EX->sw[i*2+1];
}
break;
case 0x02: /* PHADDD Gx, Ex */
nextop = F8;
GET_EX;
GX.sd[0] += GX.sd[1];
GX.sd[1] = GX.sd[2] + GX.sd[3];
if(&GX == EX) {
GX.q[1] = GX.q[0];
} else {
GX.sd[2] = EX->sd[0] + EX->sd[1];
GX.sd[3] = EX->sd[2] + EX->sd[3];
}
break;
case 0x03: /* PHADDSW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<4; ++i) {
tmp32s = GX.sw[i*2+0]+GX.sw[i*2+1];
GX.sw[i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
}
if(&GX == EX) {
GX.q[1] = GX.q[0];
} else {
for (int i=0; i<4; ++i) {
tmp32s = EX->sw[i*2+0] + EX->sw[i*2+1];
GX.sw[4+i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
}
}
break;
case 0x04: /* PMADDUBSW Gx,Ex */
nextop = F8;
GET_EX;
for (int i=0; i<8; ++i) {
tmp32s = (int32_t)(GX.ub[i*2+0])*EX->ub[i*2+0] + (int32_t)(GX.ub[i*2+1])*EX->ub[i*2+1];
GX.sw[i] = (tmp32s>32767)?32767:tmp32s; // no negative value to test
tmp32s = (int32_t)(GX.ub[i*2+0])*EX->sb[i*2+0] + (int32_t)(GX.ub[i*2+1])*EX->sb[i*2+1];
GX.sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
}
break;
case 0x05: /* PHSUBW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<4; ++i)
GX.sw[i] = GX.sw[i*2+0] - GX.sw[i*2+1];
if(&GX == EX) {
GX.q[1] = GX.q[0];
} else {
for (int i=0; i<4; ++i)
GX.sw[4+i] = EX->sw[i*2+0] - EX->sw[i*2+1];
}
break;
case 0x08: /* PSIGNB Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<16; ++i)
GX.sb[i] *= (EX->sb[i]<0)?-1:((EX->sb[i]>0)?1:0);
break;
case 0x09: /* PSIGNW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<8; ++i)
GX.sw[i] *= (EX->sw[i]<0)?-1:((EX->sw[i]>0)?1:0);
break;
case 0x0A: /* PSIGND Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<4; ++i)
GX.sd[i] *= (EX->sd[i]<0)?-1:((EX->sd[i]>0)?1:0);
break;
case 0x0B: /* PMULHRSW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<8; ++i) {
tmp32s = ((((int32_t)(GX.sw[i])*(int32_t)(EX->sw[i]))>>14) + 1)>>1;
GX.uw[i] = tmp32s&0xffff;
}
break;
case 0x1C: /* PABSB Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<16; ++i) {
GX.sb[i] = abs(EX->sb[i]);
}
break;
case 0x1D: /* PABSW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<8; ++i) {
GX.sw[i] = abs(EX->sw[i]);
}
break;
case 0x1E: /* PABSD Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<4; ++i) {
GX.sd[i] = abs(EX->sd[i]);
}
break;
default:
goto _default;
}
@@ -234,32 +420,42 @@
_6f_0x3A: // these are some SSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x0F: // PALIGNR
case 0x0F: // PALIGNR GX, EX, u8
nextop = F8;
GET_EX;
tmp8u = F8;
if(tmp8u>31)
{EX->q[0] = EX->q[1] = 0;}
else if(tmp8u>15) {
{GX.q[0] = GX.q[1] = 0;}
else
#if 0
if(tmp8u>15) {
tmp8u=(tmp8u-16)*8;
if (tmp8u < 64) {
GX.q[0] = (EX->q[0] >> tmp8u) | (EX->q[1] << (64 - tmp8u));
GX.q[1] = (EX->q[1] >> tmp8u);
GX.q[0] = (GX.q[0] >> tmp8u) | (GX.q[1] << (64 - tmp8u));
GX.q[1] = (GX.q[1] >> tmp8u);
} else {
GX.q[0] = EX->q[1] >> (tmp8u - 64);
GX.q[0] = GX.q[1] >> (tmp8u - 64);
GX.q[1] = 0;
}
} else {
tmp8u*=8;
if (tmp8u < 64) {
GX.q[0] = (GX.q[0] >> tmp8u) | (GX.q[1] << (64 - tmp8u));
GX.q[1] = (GX.q[1] >> tmp8u) | (EX->q[0] << (64-tmp8u));
GX.q[0] = (EX->q[0] >> tmp8u) | (EX->q[1] << (64 - tmp8u));
GX.q[1] = (EX->q[1] >> tmp8u) | (GX.q[0] << (64-tmp8u));
} else {
tmp8u -= 64;
GX.q[0] = (GX.q[1] >> tmp8u) | (EX->q[0] << (64 - tmp8u));
GX.q[1] = (EX->q[0] >> tmp8u) | (EX->q[1] >> (64 - tmp8u));
GX.q[0] = (EX->q[1] >> tmp8u) | (GX.q[0] << (64 - tmp8u));
GX.q[1] = (GX.q[0] >> tmp8u) | (GX.q[1] >> (64 - tmp8u));
}
}
#else
{
for (int i=0; i<16; ++i, ++tmp8u)
eax1.ub[i] = (tmp8u>15)?((tmp8u>31)?0:GX.ub[tmp8u-16]):EX->ub[tmp8u];
GX.q[0] = eax1.q[0];
GX.q[1] = eax1.q[1];
}
#endif
break;
default:
goto _default;
@@ -363,18 +559,26 @@
_6f_0x60: /* PUNPCKLBW Gx,Ex */
nextop = F8;
GET_EX;
for(int i=7; i>0; --i)
for(int i=7; i>0; --i) // 0 is untouched
GX.ub[2 * i] = GX.ub[i];
for(int i=0; i<8; ++i)
GX.ub[2 * i + 1] = EX->ub[i];
if(&GX==EX)
for(int i=0; i<8; ++i)
GX.ub[2 * i + 1] = GX.ub[2 * i];
else
for(int i=0; i<8; ++i)
GX.ub[2 * i + 1] = EX->ub[i];
NEXT;
_6f_0x61: /* PUNPCKLWD Gx,Ex */
nextop = F8;
GET_EX;
for(int i=3; i>0; --i)
GX.uw[2 * i] = GX.uw[i];
for(int i=0; i<4; ++i)
GX.uw[2 * i + 1] = EX->uw[i];
if(&GX==EX)
for(int i=0; i<4; ++i)
GX.uw[2 * i + 1] = GX.uw[2 * i];
else
for(int i=0; i<4; ++i)
GX.uw[2 * i + 1] = EX->uw[i];
NEXT;
_6f_0x62: /* PUNPCKLDQ Gx,Ex */
nextop = F8;
@@ -386,10 +590,16 @@
_6f_0x63: /* PACKSSWB Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i)
GX.sb[i] = (GX.sw[i]<-128)?-128:((GX.sw[i]>127)?127:GX.sw[i]);
for(int i=0; i<8; ++i)
GX.sb[8+i] = (EX->sw[i]<-128)?-128:((EX->sw[i]>127)?127:EX->sw[i]);
if(&GX==EX) {
for(int i=0; i<8; ++i)
GX.sb[i] = (EX->sw[i]<-128)?-128:((EX->sw[i]>127)?127:EX->sw[i]);
GX.q[1] = GX.q[0];
} else {
for(int i=0; i<8; ++i)
GX.sb[i] = (GX.sw[i]<-128)?-128:((GX.sw[i]>127)?127:GX.sw[i]);
for(int i=0; i<8; ++i)
GX.sb[8+i] = (EX->sw[i]<-128)?-128:((EX->sw[i]>127)?127:EX->sw[i]);
}
NEXT;
_6f_0x64: /* PCMPGTB Gx,Ex */
nextop = F8;
@@ -409,13 +619,19 @@
for(int i=0; i<4; ++i)
GX.ud[i] = (GX.sd[i]>EX->sd[i])?0xFFFFFFFF:0x00000000;
NEXT;
_6f_0x67: /* PACKUSWB */
_6f_0x67: /* PACKUSWB Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i)
GX.ub[i] = (GX.sw[i]<0)?0:((GX.sw[i]>0xff)?0xff:GX.sw[i]);
for(int i=0; i<8; ++i)
GX.ub[8+i] = (EX->sw[i]<0)?0:((EX->sw[i]>0xff)?0xff:EX->sw[i]);
if(&GX==EX) {
for(int i=0; i<8; ++i)
GX.ub[i] = (EX->sw[i]<0)?0:((EX->sw[i]>0xff)?0xff:EX->sw[i]);
GX.q[1] = GX.q[0];
} else {
for(int i=0; i<8; ++i)
GX.ub[i] = (GX.sw[i]<0)?0:((GX.sw[i]>0xff)?0xff:GX.sw[i]);
for(int i=0; i<8; ++i)
GX.ub[8+i] = (EX->sw[i]<0)?0:((EX->sw[i]>0xff)?0xff:EX->sw[i]);
}
NEXT;
_6f_0x68: /* PUNPCKHBW Gx,Ex */
nextop = F8;
@@ -438,20 +654,25 @@
_6f_0x6A: /* PUNPCKHDQ Gx,Ex */
nextop = F8;
GET_EX;
if(EX==&GX) {eax1 = GX; EX = &eax1;} // copy is needed
// no copy needed if &GX==EX
GX.ud[0] = GX.ud[2];
GX.ud[2] = GX.ud[3];
GX.ud[1] = EX->ud[2];
GX.ud[2] = GX.ud[3];
GX.ud[3] = EX->ud[3];
NEXT;
_6f_0x6B: /* PACKSSDW Gx,Ex */
nextop = F8;
GET_EX;
if(EX==&GX) {eax1 = GX; EX = &eax1;} // copy is needed
for(int i=0; i<4; ++i)
GX.sw[i] = (GX.sd[i]<-32768)?-32768:((GX.sd[i]>32767)?32767:GX.sd[i]);
for(int i=0; i<4; ++i)
GX.sw[4+i] = (EX->sd[i]<-32768)?-32768:((EX->sd[i]>32767)?32767:EX->sd[i]);
if(&GX==EX) {
for(int i=0; i<4; ++i)
GX.sw[i] = (EX->sd[i]<-32768)?-32768:((EX->sd[i]>32767)?32767:EX->sd[i]);
GX.q[1] = GX.q[0];
} else {
for(int i=0; i<4; ++i)
GX.sw[i] = (GX.sd[i]<-32768)?-32768:((GX.sd[i]>32767)?32767:GX.sd[i]);
for(int i=0; i<4; ++i)
GX.sw[4+i] = (EX->sd[i]<-32768)?-32768:((EX->sd[i]>32767)?32767:EX->sd[i]);
}
NEXT;
_6f_0x6C: /* PUNPCKLQDQ Gx,Ex */
nextop = F8;
@@ -607,6 +828,17 @@
GX.ud[i] = (GX.ud[i]==EX->ud[i])?0xffffffff:0;
NEXT;
_6f_0x7C: /* HADDPD Gx, Ex */
nextop = F8;
GET_EX;
GX.d[0] += GX.d[1];
if(EX==&GX) {
GX.d[1] = GX.d[0];
} else {
GX.d[1] = EX->d[0] + EX->d[1];
}
NEXT;
_6f_0x7E: /* MOVD Ed, Gx */
nextop = F8;
GET_ED;
@@ -632,7 +864,10 @@
_6f_0xA5: /* SHLD Ew,Gw,CL */
nextop = F8;
GET_EW;
tmp8u = (opcode==0xA4)?(F8):R_CL;
if(opcode==0xA4)
tmp8u = F8;
else
tmp8u = R_CL;
EW->word[0] = shld16(emu, EW->word[0], GW.word[0], tmp8u);
NEXT;
@@ -651,7 +886,10 @@
_6f_0xAD: /* SHRD Ew,Gw,CL */
nextop = F8;
GET_EW;
tmp8u = (opcode==0xAC)?(F8):R_CL;
if(opcode==0xAC)
tmp8u = F8;
else
tmp8u = R_CL;
EW->word[0] = shrd16(emu, EW->word[0], GW.word[0], tmp8u);
NEXT;
@@ -688,6 +926,11 @@
GET_EB;
GW.word[0] = EB->byte[0];
NEXT;
_6f_0xB7: /* MOVZX Gw,Ew */
nextop = F8;
GET_EW;
GW.word[0] = EW->word[0]; // yeah, the ZX is useless here
NEXT;
_6f_0xBA:
nextop = F8;
@@ -706,6 +949,21 @@
else
CLEAR_FLAG(F_CF);
break;
case 5: /* BTS Ew, Ib */
CHECK_FLAGS(emu);
GET_EW;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
EW=(reg32_t*)(((uint16_t*)(EW))+(tmp8u>>4));
}
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
} else
EW->word[0] ^= (1<<tmp8u);
CLEAR_FLAG(F_CF);
break;
case 6: /* BTR Ew, Ib */
CHECK_FLAGS(emu);
GET_EW;
@@ -721,6 +979,21 @@
} else
CLEAR_FLAG(F_CF);
break;
case 7: /* BTC Ew, Ib */
CHECK_FLAGS(emu);
GET_EW;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
EW=(reg32_t*)(((uint16_t*)(EW))+(tmp8u>>4));
}
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
EW->word[0] ^= (1<<tmp8u);
break;
default:
goto _default;
@@ -819,6 +1092,18 @@
GX.q[1] = eax1.q[1];
NEXT;
_6f_0xC8:
_6f_0xC9:
_6f_0xCA:
_6f_0xCB:
_6f_0xCC:
_6f_0xCD:
_6f_0xCE:
_6f_0xCF: /* BSWAP reg16 */
tmp8s = opcode&7;
emu->regs[tmp8s].word[0] = __builtin_bswap16(emu->regs[tmp8s].word[0]);
NEXT;
_6f_0xD1: /* PSRLW Gx, Ex */
nextop = F8;
GET_EX;
@@ -854,7 +1139,7 @@
GET_EX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX.sw[i] * EX->sw[i];
GX.sw[i] = tmp32s;
GX.sw[i] = tmp32s&0xffff;
}
NEXT;
_6f_0xD6: /* MOVQ Ex,Gx */
@@ -866,18 +1151,21 @@
NEXT;
_6f_0xD7: /* PMOVMSKB Gd,Ex */
nextop = F8;
GET_EX;
GD.dword[0] = 0;
for (int i=0; i<16; ++i)
if(EX->ub[i]&0x80)
GD.dword[0] |= (1<<i);
NEXT;
if((nextop&0xC0)==0xC0) {
GET_EX;
GD.dword[0] = 0;
for (int i=0; i<16; ++i)
if(EX->ub[i]&0x80)
GD.dword[0] |= (1<<i);
NEXT;
} else
goto _default;
_6f_0xD8: /* PSUBUSB Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<16; ++i) {
tmp16s = (int16_t)GX.ub[i] - EX->ub[i];
GX.ub[i] = (tmp16s<0)?0:((tmp16s>255)?255:tmp16s);
GX.ub[i] = (tmp16s<0)?0:tmp16s;
}
NEXT;
_6f_0xD9: /* PSUBUSW Gx,Ex */
@@ -885,10 +1173,15 @@
GET_EX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX.uw[i] - EX->uw[i];
GX.uw[i] = (tmp32s<0)?0:((tmp32s>0xffff)?0xffff:tmp32s);
GX.uw[i] = (tmp32s<0)?0:tmp32s;
}
NEXT;
_6f_0xDA: /* PMINUB Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<16; ++i)
if(EX->ub[i]<GX.ub[i]) GX.ub[i] = EX->ub[i];
NEXT;
_6f_0xDB: /* PAND Gx,Ex */
nextop = F8;
GET_EX;
@@ -903,7 +1196,14 @@
GX.ub[i] = (tmp16s>255)?255:tmp16s;
}
NEXT;
_6f_0xDD: /* PADDUSW Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX.uw[i] + EX->uw[i];
GX.uw[i] = (tmp32s>65535)?65535:tmp32s;
}
NEXT;
_6f_0xDE: /* PMAXUB Gx, Ex */
nextop = F8;
GET_EX;
@@ -913,32 +1213,43 @@
_6f_0xDF: /* PANDN Gx,Ex */
nextop = F8;
GET_EX;
GX.q[0] = (~GX.q[0]) & EX->q[0];
GX.q[1] = (~GX.q[1]) & EX->q[1];
GX.q[0] = (~(GX.q[0])) & EX->q[0];
GX.q[1] = (~(GX.q[1])) & EX->q[1];
NEXT;
_6f_0xE0: /* PAVGB Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<16; ++i) GX.ub[i] = ((uint16_t)GX.ub[i] + EX->ub[i] + 1)>>1;
for (int i=0; i<16; ++i)
GX.ub[i] = ((uint16_t)GX.ub[i] + EX->ub[i] + 1)>>1;
NEXT;
_6f_0xE1: /* PSRAW Gx, Ex */
nextop = F8;
GET_EX;
tmp8u=(EX->q[0]>15)?16:EX->ub[0];
for (int i=0; i<8; ++i) GX.sw[i] >>= tmp8u;
for (int i=0; i<8; ++i)
GX.sw[i] >>= tmp8u;
NEXT;
_6f_0xE2: /* PSRAD Gx, Ex */
nextop = F8;
GET_EX;
tmp8u=(EX->q[0]>31)?32:EX->ub[0];
for (int i=0; i<4; ++i) GX.sd[i] >>= tmp8u;
for (int i=0; i<4; ++i)
GX.sd[i] >>= tmp8u;
NEXT;
_6f_0xE3: /* PAVGW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<8; ++i) GX.uw[i] = ((uint16_t)GX.uw[i] + EX->uw[i] + 1)>>1;
for (int i=0; i<8; ++i)
GX.uw[i] = ((uint32_t)GX.uw[i] + EX->uw[i] + 1)>>1;
NEXT;
_6f_0xE4: /* PMULHUW Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i) {
tmp32u = (uint32_t)GX.uw[i] * EX->uw[i];
GX.uw[i] = (tmp32u>>16)&0xffff;
}
NEXT;
_6f_0xE5: /* PMULHW Gx, Ex */
nextop = F8;
GET_EX;
@@ -954,7 +1265,7 @@
GX.sd[1] = EX->d[1];
GX.q[1] = 0;
NEXT;
_6f_0xE7: /* MOVNTDQ Ex, Gx */
_6f_0xE7: /* MOVNTDQ Ex, Gx */
nextop = F8;
GET_EX;
EX->q[0] = GX.q[0];
@@ -965,7 +1276,7 @@
GET_EX;
for(int i=0; i<16; ++i) {
tmp16s = (int16_t)GX.sb[i] - EX->sb[i];
GX.ub[i] = (tmp16s<-128)?-128:((tmp16s>127)?127:tmp16s);
GX.sb[i] = (tmp16s<-128)?-128:((tmp16s>127)?127:tmp16s);
}
NEXT;
_6f_0xE9: /* PSUBSW Gx,Ex */
@@ -1082,13 +1393,13 @@
nextop = F8;
GET_EX;
for(int i=0; i<16; ++i)
GX.ub[i] -= EX->ub[i];
GX.sb[i] -= EX->sb[i];
NEXT;
_6f_0xF9: /* PSUBW Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i)
GX.uw[i] -= EX->uw[i];
GX.sw[i] -= EX->sw[i];
NEXT;
_6f_0xFA: /* PSUBD Gx,Ex */
nextop = F8;
@@ -1124,5 +1435,8 @@
GX.sd[2] += EX->sd[2];
GX.sd[3] += EX->sd[3];
NEXT;
_fini:
R_EIP = ip;
return;
}
+15 -13
View File
@@ -56,23 +56,24 @@ int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, c
const char* GetNativeName(void* p)
{
static char unknown[10] = "???";
const char *ret = GetNameOffset(my_context->maplib, p);
if(ret)
return ret;
static char buff[500] = {0};
Dl_info info;
if(dladdr(p, &info)==0)
return unknown;
else {
if(dladdr(p, &info)==0) {
const char *ret = GetNameOffset(my_context->maplib, p);
if(ret)
return ret;
sprintf(buff, "%s(%p)", "???", p);
return buff;
} else {
if(info.dli_sname) {
strcpy(buff, info.dli_sname);
if(info.dli_fname) {
strcat(buff, " ("); strcat(buff, info.dli_fname); strcat(buff, ")");
}
} else
return unknown;
} else {
sprintf(buff, "%s(%s/%p)", "???", info.dli_fname, p);
return buff;
}
}
return buff;
}
@@ -744,9 +745,9 @@ void UnpackFlags(x86emu_t* emu)
uintptr_t GetSegmentBaseEmu(x86emu_t* emu, int seg)
{
if(!emu->segs_clean[seg] || seg==_GS) {
if(emu->segs_serial[seg] != emu->context->sel_serial) {
emu->segs_offs[seg] = (uintptr_t)GetSegmentBase(emu->segs[seg]);
emu->segs_clean[seg] = 1;
emu->segs_serial[seg] = emu->context->sel_serial;
}
return emu->segs_offs[seg];
}
@@ -792,8 +793,8 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
if(!start_cnt && my_context->dec && (
(trace_end == 0)
|| ((ip >= trace_start) && (ip < trace_end))) ) {
pthread_mutex_lock(&my_context->mutex_trace);
int tid = syscall(SYS_gettid);
pthread_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");
@@ -806,6 +807,7 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
my_context->trace_tid = tid;
}
#endif
trace_end = 0;
printf_log(LOG_NONE, "%s", DumpCPURegs(emu, ip));
if(PK(0)==0xcc && PK(1)=='S' && PK(2)=='C') {
uint32_t a = *(uint32_t*)(ip+3);
+1
View File
@@ -202,6 +202,7 @@ void Run6766(x86emu_t *emu);
void RunGS(x86emu_t *emu);
void RunFS(x86emu_t *emu);
void RunLock(x86emu_t *emu);
void RunLock66(x86emu_t *emu);
void x86Syscall(x86emu_t *emu);
void x86Int3(x86emu_t* emu);
+23 -2
View File
@@ -56,6 +56,9 @@ typedef struct x86_sigaction_s x86_sigaction_t;
int32_t my_getrandom(x86emu_t* emu, void* buf, uint32_t buflen, uint32_t flags);
int of_convert(int flag);
int32_t my_open(x86emu_t* emu, void* pathname, int32_t flags, uint32_t mode);
#ifndef __NR_memfd_create
int my_memfd_create(x86emu_t* emu, void* name, uint32_t flags);
#endif
#ifndef NOALIGN
int my_epoll_create(x86emu_t* emu, int size);
@@ -64,6 +67,7 @@ int32_t my_epoll_ctl(x86emu_t* emu, int32_t epfd, int32_t op, int32_t fd, void*
int32_t my_epoll_wait(x86emu_t* emu, int32_t epfd, void* events, int32_t maxevents, int32_t timeout);
#endif
int my_sigaction(x86emu_t* emu, int signum, const x86_sigaction_t *act, x86_sigaction_t *oldact);
int32_t my_execve(x86emu_t* emu, const char* path, char* const argv[], char* const envp[]);
// cannot include <fcntl.h>, it conflict with some asm includes...
#ifndef O_NONBLOCK
@@ -199,6 +203,8 @@ scwrap_t syscallwrap[] = {
//{ 221, __NR_fcntl64, 3 },
{ 224, __NR_gettid, 0 },
{ 240, __NR_futex, 6 },
{ 241, __NR_sched_setaffinity, 3 },
{ 242, __NR_sched_getaffinity, 3 },
{ 252, __NR_exit_group, 1 },
#ifdef NOALIGN
{ 254, __NR_epoll_create, 1 },
@@ -217,6 +223,9 @@ scwrap_t syscallwrap[] = {
#ifdef __NR_getrandom
{ 355, __NR_getrandom, 3 },
#endif
#ifdef __NR_memfd_create
{ 356, __NR_memfd_create, 2},
#endif
};
struct mmap_arg_struct {
@@ -322,7 +331,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
case 1: // sys_exit
emu->quit = 1;
emu->exit = 1;
R_EAX = R_EBX; // faking the syscall here, we don't want to really terminate the program now
//R_EAX = syscall(__NR_exit, R_EBX); // the syscall should exit only current thread
R_EAX = R_EBX; // faking the syscall here, we don't want to really terminate the thread now
break;
case 3: // sys_read
R_EAX = (uint32_t)read((int)R_EBX, (void*)R_ECX, (size_t)R_EDX);
@@ -349,7 +359,7 @@ void EXPORT x86Syscall(x86emu_t *emu)
char** argv = (char**)R_ECX;
char** envv = (char**)R_EDX;
printf_log(LOG_DUMP, " => 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 = execve((const char*)R_EBX, (void*)R_ECX, (void*)R_EDX);
R_EAX = my_execve(emu, (const char*)R_EBX, (void*)R_ECX, (void*)R_EDX);
}
break;
#ifndef __NR_time
@@ -576,6 +586,11 @@ void EXPORT x86Syscall(x86emu_t *emu)
case 355: // getrandom
R_EAX = my_getrandom(emu, (void*)R_EBX, R_ECX, R_EDX);
break;
#endif
#ifndef __NR_memfd_create
case 356: // memfd_create
R_EAX = my_memfd_create(emu, (void*)R_EBX, R_ECX);
break;
#endif
default:
printf_log(LOG_INFO, "Error: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
@@ -627,6 +642,8 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
return my_open(emu, p(4), of_convert(u32(8)), u32(12));
case 6: // sys_close
return (uint32_t)close(i32(4));
case 11: // execve
return (uint32_t)my_execve(emu, p(4), p(8), p(12));
case 123: // SYS_modify_ldt
return my_modify_ldt(emu, i32(4), (thread_area_t*)p(8), i32(12));
case 174: // sys_rt_sigaction
@@ -658,6 +675,10 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
#ifndef __NR_getrandom
case 355: // getrandom
return (uint32_t)my_getrandom(emu, p(4), u32(8), u32(12));
#endif
#ifndef __NR_memfd_create
case 356: // memfd_create
return (uint32_t)my_memfd_create(emu, (void*)R_EBX, R_ECX);
#endif
default:
printf_log(LOG_INFO, "Error: Unsupported libc Syscall 0x%02X (%d)\n", s, s);
+8 -4
View File
@@ -89,6 +89,8 @@ uint32_t my_set_thread_area(thread_area_t* td)
pthread_setspecific(my_context->segtls[idx-7].key, (void*)my_context->segtls[idx-7].base);
ResetSegmentsCache(thread_get_emu());
return 0;
}
@@ -120,6 +122,8 @@ uint32_t my_modify_ldt(x86emu_t* emu, int op, thread_area_t* td, int size)
my_context->segtls[idx].limit = td->limit;
pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base);
*/
ResetSegmentsCache(thread_get_emu());
return 0;
}
@@ -157,21 +161,21 @@ static tlsdatasize_t* setupTLSData(box86context_t* context)
void* fillTLSData(box86context_t *context)
{
pthread_mutex_lock(&context->mutex_lock);
pthread_mutex_lock(&context->mutex_tls);
tlsdatasize_t *data = setupTLSData(context);
pthread_mutex_unlock(&context->mutex_lock);
pthread_mutex_unlock(&context->mutex_tls);
return data;
}
void* resizeTLSData(box86context_t *context, void* oldptr)
{
pthread_mutex_lock(&context->mutex_lock);
pthread_mutex_lock(&context->mutex_tls);
tlsdatasize_t* oldata = (tlsdatasize_t*)oldptr;
tlsdatasize_t *data = setupTLSData(context);
// copy the relevent old part, in case something changed
memcpy((void*)((uintptr_t)data->tlsdata+(context->tlssize-oldata->tlssize)), oldata->tlsdata, oldata->tlssize);
// all done, update new size, free old pointer and exit
pthread_mutex_unlock(&context->mutex_lock);
pthread_mutex_unlock(&context->mutex_tls);
free_tlsdatasize(oldptr);
return data;
}
+79 -28
View File
@@ -25,13 +25,8 @@ void fpu_fbst(x86emu_t* emu, uint8_t* d) {
// very aproximative... but should not be much used...
uint8_t p;
uint8_t sign = 0x00;
#ifdef USE_FLOAT
double tmp, v = ST0.f;
if(ST0.f<0.0f)
#else
double tmp, v = ST0.d;
if(ST0.d<0.0)
#endif
{
sign = 0x80;
v = -v;
@@ -64,38 +59,15 @@ void fpu_fbld(x86emu_t* emu, uint8_t* s) {
tmp += m * ((p>>4)&0x0f);
m *= 10;
}
#ifdef USE_FLOAT
ST0.f = tmp;
p =*(s++);
ST0.f += m * (p&0x0f);
if(p&0x80)
ST0.f = -ST0.f;
#else
ST0.d = tmp;
p =*(s++);
ST0.d += m * (p&0x0f);
if(p&0x80)
ST0.d = -ST0.d;
#endif
}
#ifdef USE_FLOAT
typedef union {
double d;
struct {
uint32_t lower;
uint32_t upper;
} l;
struct {
float lower;
float upper;
} f;
int64_t ll;
} FPU_t;
#else
#define FPU_t fpu_reg_t
#endif
#define BIAS80 16383
#define BIAS64 1023
// long double (80bits) -> double (64bits)
@@ -108,9 +80,13 @@ void LD2D(void* ld, void* d)
int16_t b;
} val;
#pragma pack(pop)
#if 1
memcpy(&val, ld, 10);
#else
val.f.l.lower = *(uint32_t*)ld;
val.f.l.upper = *(uint32_t*)(char*)(ld+4);
val.b = *(int16_t*)((char*)ld+8);
#endif
int32_t exp64 = (((uint32_t)(val.b&0x7fff) - BIAS80) + BIAS64);
int32_t exp64final = exp64&0x7ff;
// do specific value first (0, infinite...)
@@ -254,3 +230,78 @@ void fpu_savenv(x86emu_t* emu, char* p, int b16)
*(uint16_t*)p = tags;
// other stuff are not pushed....
}
typedef struct xsave_s {
uint16_t ControlWord; /* 000 */
uint16_t StatusWord; /* 002 */
uint8_t TagWord; /* 004 */
uint8_t Reserved1; /* 005 */
uint16_t ErrorOpcode; /* 006 */
uint32_t ErrorOffset; /* 008 */
uint16_t ErrorSelector; /* 00c */
uint16_t Reserved2; /* 00e */
uint32_t DataOffset; /* 010 */
uint16_t DataSelector; /* 014 */
uint16_t Reserved3; /* 016 */
uint32_t MxCsr; /* 018 */
uint32_t MxCsr_Mask; /* 01c */
sse_regs_t FloatRegisters[8];/* 020 */ // fpu/mmx are store in 128bits here
sse_regs_t XmmRegisters[16]; /* 0a0 */
uint8_t Reserved4[96]; /* 1a0 */
} xsave_t;
void fpu_fxsave(x86emu_t* emu, void* ed)
{
xsave_t *p = (xsave_t*)ed;
// should save flags & all
emu->sw.f.F87_TOP = emu->top&7;
p->ControlWord = emu->cw;
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;
p->TagWord = tags;
p->ErrorOpcode = 0;
p->ErrorOffset = 0;
p->ErrorSelector = 0;
p->DataOffset = 0;
p->DataSelector = 0;
p->MxCsr = 0;
p->MxCsr_Mask = 0;
// copy MMX regs...
for(int i=0; i<8; ++i)
memcpy(&p->FloatRegisters[i].q[0], &emu->mmx[0], sizeof(emu->mmx[0]));
// copy SSE regs
memcpy(&p->XmmRegisters[0], &emu->xmm[0], sizeof(emu->xmm));
// put also FPU regs in a reserved area... on XMM 8-15
for(int i=0; i<8; ++i)
memcpy(&p->XmmRegisters[8+i].q[0], &emu->fpu[0], sizeof(emu->fpu[0]));
// put a magic sign in reserved area, box86 specific
((unsigned int *)p->Reserved4)[11] = 0x50515253;
}
void fpu_fxrstor(x86emu_t* emu, void* ed)
{
xsave_t *p = (xsave_t*)ed;
emu->cw = p->ControlWord;
emu->sw.x16 = p->StatusWord;
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;
// copy back MMX regs...
for(int i=0; i<8; ++i)
memcpy(&emu->mmx[i], &p->FloatRegisters[i].q[0], sizeof(emu->mmx[0]));
// copy SSE regs
memcpy(&emu->xmm[0], &p->XmmRegisters[0], sizeof(emu->xmm));
// check the box86 magic sign in reserved area
if(((unsigned int *)p->Reserved4)[11] == 0x50515253) {
// also FPU regs where a reserved area... on XMM 8-15?
for(int i=0; i<8; ++i)
memcpy(&emu->fpu[0], &p->XmmRegisters[8+i].q[0], sizeof(emu->fpu[0]));
} else {
// copy the mmx to fpu...
for(int i=0; i<8; ++i)
memcpy(&emu->fpu[0], &emu->mmx[i], sizeof(emu->mmx[0]));
}
}
+4 -88
View File
@@ -66,28 +66,9 @@ static inline void fpu_do_free(x86emu_t* emu, int i)
void reset_fpu(x86emu_t* emu);
#ifdef USE_FLOAT
static inline void fpu_fcom(x86emu_t* emu, float b)
#else
static inline void fpu_fcom(x86emu_t* emu, double b)
#endif
{
emu->sw.f.F87_C1 = 0;
#ifdef USE_FLOAT
if(isnan(ST0.f) || isnan(b)) {
emu->sw.f.F87_C0 = 1;
emu->sw.f.F87_C2 = 1;
emu->sw.f.F87_C3 = 1;
} else if (isgreater(ST0.f, b)) {
emu->sw.f.F87_C0 = 0;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C3 = 0;
} else if (isless(ST0.f, b)) {
emu->sw.f.F87_C0 = 1;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C3 = 0;
}
#else
if(isnan(ST0.d) || isnan(b)) {
emu->sw.f.F87_C0 = 1;
emu->sw.f.F87_C2 = 1;
@@ -101,7 +82,6 @@ static inline void fpu_fcom(x86emu_t* emu, double b)
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C3 = 0;
}
#endif
else {
emu->sw.f.F87_C0 = 0;
emu->sw.f.F87_C2 = 0;
@@ -109,32 +89,13 @@ static inline void fpu_fcom(x86emu_t* emu, double b)
}
}
#ifdef USE_FLOAT
static inline void fpu_fcomi(x86emu_t* emu, float b)
#else
static inline void fpu_fcomi(x86emu_t* emu, double b)
#endif
{
RESET_FLAGS(emu);
emu->flags[F_AF] = 0;
emu->flags[F_OF] = 0;
emu->flags[F_SF] = 0;
emu->sw.f.F87_C1 = 0;
#ifdef USE_FLOAT
if(isnan(ST0.f) || isnan(b)) {
emu->flags[F_CF] = 1;
emu->flags[F_PF] = 1;
emu->flags[F_ZF] = 1;
} else if (isgreater(ST0.f, b)) {
emu->flags[F_CF] = 0;
emu->flags[F_PF] = 0;
emu->flags[F_ZF] = 0;
} else if (isless(ST0.f, b)) {
emu->flags[F_CF] = 1;
emu->flags[F_PF] = 0;
emu->flags[F_ZF] = 0;
}
#else
if(isnan(ST0.d) || isnan(b)) {
emu->flags[F_CF] = 1;
emu->flags[F_PF] = 1;
@@ -148,7 +109,6 @@ static inline void fpu_fcomi(x86emu_t* emu, double b)
emu->flags[F_PF] = 0;
emu->flags[F_ZF] = 0;
}
#endif
else {
emu->flags[F_CF] = 0;
emu->flags[F_PF] = 0;
@@ -156,79 +116,45 @@ static inline void fpu_fcomi(x86emu_t* emu, double b)
}
}
#ifdef USE_FLOAT
static inline float fpu_round(x86emu_t* emu, float d) {
if (!isfinite(d))
return d;
switch(emu->round) {
case ROUND_Nearest:
return floorf(d+0.5);
case ROUND_Down:
return floorf(d);
case ROUND_Up:
return ceilf(d);
case ROUND_Chop:
default:
return roundf(d);
}
}
#else
static inline double fpu_round(x86emu_t* emu, double d) {
if (!isfinite(d))
return d;
switch(emu->round) {
case ROUND_Nearest:
return floor(d+0.5);
return nearbyint(d);
case ROUND_Down:
return floor(d);
case ROUND_Up:
return ceil(d);
case ROUND_Chop:
default:
return round(d);
return trunc(d);
}
}
#endif
static inline void fpu_fxam(x86emu_t* emu) {
#ifdef USE_FLOAT
emu->sw.f.F87_C1 = (ST0.ll&0x8000)?1:0;
#else
emu->sw.f.F87_C1 = (ST0.l.upper&0x80000000)?1:0;
#endif
if(!emu->fpu_stack) {
emu->sw.f.F87_C3 = 1;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = 1;
return;
}
#ifdef USE_FLOAT
if(isinf(ST0.f))
#else
if(isinf(ST0.d))
#endif
{ // TODO: Unsuported and denormal not analysed...
emu->sw.f.F87_C3 = 0;
emu->sw.f.F87_C2 = 1;
emu->sw.f.F87_C0 = 1;
return;
}
#ifdef USE_FLOAT
if(isnan(ST0.f))
#else
if(isnan(ST0.d))
#endif
{ // TODO: Unsuported and denormal not analysed...
emu->sw.f.F87_C3 = 0;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = 1;
return;
}
#ifdef USE_FLOAT
if(ST0.f==0.0f)
#else
if(ST0.d==0.0)
#endif
{
emu->sw.f.F87_C3 = 1;
emu->sw.f.F87_C2 = 0;
@@ -244,22 +170,14 @@ static inline void fpu_fxam(x86emu_t* emu) {
static inline void fpu_ftst(x86emu_t* emu) {
emu->sw.f.F87_C1 = 0;
#ifdef USE_FLOAT
if(isinf(ST0.f) || isnan(ST0.f))
#else
if(isinf(ST0.d) || isnan(ST0.d))
#endif
{ // TODO: Unsuported and denormal not analysed...
emu->sw.f.F87_C3 = 1;
emu->sw.f.F87_C2 = 1;
emu->sw.f.F87_C0 = 1;
return;
}
#ifdef USE_FLOAT
if(ST0.f==0.0f)
#else
if(ST0.d==0.0)
#endif
{
emu->sw.f.F87_C3 = 1;
emu->sw.f.F87_C2 = 0;
@@ -269,11 +187,7 @@ static inline void fpu_ftst(x86emu_t* emu) {
// normal...
emu->sw.f.F87_C3 = 0;
emu->sw.f.F87_C2 = 0;
#ifdef USE_FLOAT
emu->sw.f.F87_C0 = (ST0.ll&0x8000)?1:0;
#else
emu->sw.f.F87_C0 = (ST0.l.upper&0x80000000)?1:0;
#endif
}
void fpu_fbst(x86emu_t* emu, uint8_t* d);
@@ -281,5 +195,7 @@ void fpu_fbld(x86emu_t* emu, uint8_t* s);
void fpu_loadenv(x86emu_t* emu, char* p, int b16);
void fpu_savenv(x86emu_t* emu, char* p, int b16);
void fpu_fxsave(x86emu_t* emu, void* ed);
void fpu_fxrstor(x86emu_t* emu, void* ed);
#endif //__X87RUN_PRIVATE_H_
+32 -26
View File
@@ -16,11 +16,21 @@
#include "x86trace.h"
#include "x86run.h"
#define F8 *(uint8_t*)(ip++)
#define F8S *(int8_t*)(ip++)
#define F16 *(uint16_t*)(ip+=2, ip-2)
#define F16S *(int16_t*)(ip+=2, ip-2)
#define F32 *(uint32_t*)(ip+=4, ip-4)
#define F32S *(int32_t*)(ip+=4, ip-4)
#define PK(a) *(uint8_t*)(ip+a)
#include "modrm.h"
void Run66D9(x86emu_t *emu)
{
uint8_t nextop;
reg32_t *op1;
nextop = Fetch8(emu);
uintptr_t ip = R_EIP;
uint8_t nextop = F8;
reg32_t *oped;
switch (nextop) {
case 0xC0:
case 0xC1:
@@ -66,31 +76,34 @@ void Run66D9(x86emu_t *emu)
case 0xFD:
case 0xFE:
case 0xFF:
ip = R_EIP-2;
UnimpOpcode(emu);
break;
default:
switch((nextop>>3)&7) {
case 4: /* FLDENV m */
// warning, incomplete
op1=GetEw(emu, nextop);
fpu_loadenv(emu, (char*)op1, 1);
GET_EW;
fpu_loadenv(emu, (char*)ED, 1);
break;
case 6: /* FNSTENV m */
// warning, incomplete
op1=GetEw(emu, nextop);
fpu_savenv(emu, (char*)op1, 1);
GET_EW;
fpu_savenv(emu, (char*)ED, 1);
break;
default:
ip = R_EIP-2;
UnimpOpcode(emu);
}
}
R_EIP = ip;
}
void Run66DD(x86emu_t *emu)
{
uint8_t nextop;
reg32_t *op1;
nextop = Fetch8(emu);
uintptr_t ip = R_EIP;
uint8_t nextop = F8;
reg32_t *oped;
switch(nextop) {
case 0xC0:
@@ -137,51 +150,44 @@ void Run66DD(x86emu_t *emu)
case 0xFD:
case 0xFE:
case 0xFF:
ip = R_EIP-2;
UnimpOpcode(emu);
break;
default:
switch((nextop>>3)&7) {
case 4: /* FRSTOR m94byte */
op1=GetEw(emu, nextop);
fpu_loadenv(emu, (char*)op1, 1);
GET_EW;
fpu_loadenv(emu, (char*)ED, 1);
// get the STx
{
char* p =(char*)op1;
char* p =(char*)ED;
p += 14;
for (int i=0; i<8; ++i) {
#ifdef USE_FLOAT
LD2D(p, &d);
ST(i).f = d;
#else
LD2D(p, &ST(i).d);
#endif
p+=10;
}
}
break;
case 6: /* FNSAVE m94byte */
op1=GetEw(emu, nextop);
GET_EW;
// ENV first...
fpu_savenv(emu, (char*)op1, 1);
fpu_savenv(emu, (char*)ED, 1);
// save the STx
{
char* p =(char*)op1;
char* p =(char*)ED;
p += 14;
for (int i=0; i<8; ++i) {
#ifdef USE_FLOAT
d = ST(i).f;
D2LD(&d, p);
#else
D2LD(&ST(i).d, p);
#endif
p+=10;
}
}
reset_fpu(emu);
break;
default:
ip = R_EIP-2; // unfetch
UnimpOpcode(emu);
}
}
R_EIP = ip;
}
+42 -26
View File
@@ -12,7 +12,6 @@ typedef struct lib_s lib_t;
typedef struct bridge_s bridge_t;
typedef struct dlprivate_s dlprivate_t;
typedef struct kh_symbolmap_s kh_symbolmap_t;
typedef struct callbacklist_s callbacklist_t;
typedef struct library_s library_t;
typedef struct kh_fts_s kh_fts_t;
typedef struct kh_threadstack_s kh_threadstack_t;
@@ -25,14 +24,16 @@ typedef struct atfork_fnc_s {
void* handle;
} atfork_fnc_t;
#ifdef DYNAREC
typedef struct dynablocklist_s dynablocklist_t;
typedef struct mmaplist_s mmaplist_t;
typedef struct dynmap_s {
dynablocklist_t* dynablocks; // the dynabockist of the block
} dynmap_t;
typedef struct dynablock_s dynablock_t;
typedef struct dynablocklist_s dynablocklist_t;
typedef struct mmaplist_s mmaplist_t;
typedef struct kh_dynablocks_s kh_dynablocks_t;
#define DYNAMAP_SIZE (1<<20)
#define DYNAMAP_SHIFT 12
#endif
typedef void* (*procaddess_t)(const char* name);
typedef void* (*vkprocaddess_t)(void* instance, const char* name);
#define MAX_SIGNAL 64
@@ -60,6 +61,16 @@ typedef struct base_segment_s {
} base_segment_t;
typedef struct box86context_s {
#ifdef DYNAREC
dynablocklist_t** dynmap; // 4G of memory mapped by 4K block
int trace_dynarec;
pthread_mutex_t mutex_dyndump;
pthread_mutex_t mutex_blocks;
pthread_mutex_t mutex_mmap;
mmaplist_t *mmaplist;
int mmapsize;
kh_dynablocks_t *dblist_oversized; // store the list of oversized dynablocks (normal sized are inside mmaplist)
#endif
path_collection_t box86_path; // PATH env. variable
path_collection_t box86_ld_lib; // LD_LIBRARY_PATH env. variable
@@ -67,9 +78,9 @@ typedef struct box86context_s {
int x86trace;
int trace_tid;
#ifdef DYNAREC
int trace_dynarec;
#endif
uint32_t sel_serial; // will be increment each time selectors changes
zydis_t *zydis; // dlopen the zydis dissasembler
void* box86lib; // dlopen on box86 itself
@@ -108,13 +119,17 @@ typedef struct box86context_s {
procaddess_t glxprocaddress;
kh_symbolmap_t *alwrappers; // the map of wrapper for alGetProcAddress
kh_symbolmap_t *almymap; // link to the mysymbolmap if libOpenAL
callbacklist_t *callbacks; // all callbacks
kh_symbolmap_t *vkwrappers; // the map of wrapper for VulkanProcs (TODO: check SDL2)
kh_symbolmap_t *vkmymap; // link to the mysymbolmap of libGL
vkprocaddess_t vkprocaddress;
pthread_mutex_t mutex_once;
pthread_mutex_t mutex_once2;
pthread_mutex_t mutex_trace;
pthread_mutex_t mutex_lock;
#ifndef DYNAREC
pthread_mutex_t mutex_lock; // dynarec build will use their own mecanism
#endif
pthread_mutex_t mutex_tls;
pthread_mutex_t mutex_thread;
library_t *libclib; // shortcut to libc library (if loaded, so probably yes)
@@ -132,11 +147,19 @@ typedef struct box86context_s {
library_t *sdl2ttflib;
library_t *x11lib;
library_t *libxcb;
library_t *libxcbxfixes;
library_t *libxcbshape;
library_t *libxcbshm;
library_t *libxcbrandr;
library_t *libxcbimage;
library_t *libxcbkeysyms;
library_t *libxcbxtest;
library_t *zlib;
library_t *vorbisfile;
library_t *vorbis;
library_t *asound;
library_t *pulse;
library_t *d3dadapter9;
int deferedInit;
elfheader_t **deferedInitList;
@@ -153,14 +176,6 @@ typedef struct box86context_s {
cleanup_t *cleanups; // atexit functions
int clean_sz;
int clean_cap;
#ifdef DYNAREC
pthread_mutex_t mutex_blocks;
pthread_mutex_t mutex_mmap;
dynablocklist_t *dynablocks;
mmaplist_t *mmaplist;
int mmapsize;
dynmap_t* dynmap[65536]; // 4G of memory mapped by 64K block
#endif
#ifndef NOALIGN
kh_fts_t *ftsmap;
#endif
@@ -176,6 +191,7 @@ typedef struct box86context_s {
uintptr_t signals[MAX_SIGNAL];
uintptr_t restorer[MAX_SIGNAL];
int onstack[MAX_SIGNAL];
int is_sigaction[MAX_SIGNAL];
x86emu_t *emu_sig; // the emu with stack used for signal handling (must be separated from main ones)
int no_sigsegv;
@@ -185,6 +201,8 @@ typedef struct box86context_s {
#endif
} box86context_t;
extern box86context_t *my_context; // global context
box86context_t *NewBox86Context(int argc);
void FreeBox86Context(box86context_t** context);
@@ -195,13 +213,11 @@ int AddElfHeader(box86context_t* ctx, elfheader_t* head);
int AddTLSPartition(box86context_t* context, int tlssize);
#ifdef DYNAREC
// the nolinker specified if static map or dynamic (can be deleted) has to be used
uintptr_t AllocDynarecMap(int size, int nolinker);
void FreeDynarecMap(uintptr_t addr, uint32_t size);
uintptr_t AllocDynarecMap(dynablock_t* db, int size);
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size);
dynablocklist_t* getDBFromAddress(uintptr_t addr);
void addDBFromAddressRange(uintptr_t addr, uintptr_t size);
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
void addDBFromAddressRange(box86context_t* context, uintptr_t addr, uintptr_t size, int nolinker);
void cleanDBFromAddressRange(box86context_t* context, uintptr_t addr, uintptr_t size, int destroy);
void protectDB(uintptr_t addr, uintptr_t size);
void unprotectDB(uintptr_t addr, uintptr_t size);
+9 -2
View File
@@ -4,15 +4,22 @@
typedef struct x86emu_s x86emu_t;
typedef struct bridge_s bridge_t;
typedef struct box86context_s box86context_t;
typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
bridge_t *NewBridge();
void FreeBridge(bridge_t** bridge);
uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N);
uintptr_t AddBridge(bridge_t* bridge, box86context_t* context, wrapper_t w, void* fnc, int N);
uintptr_t CheckBridged(bridge_t* bridge, void* fnc);
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N);
uintptr_t AddCheckBridge(bridge_t* bridge, box86context_t* context, wrapper_t w, void* fnc, int N);
uintptr_t AddAutomaticBridge(x86emu_t* emu, bridge_t* bridge, wrapper_t w, void* fnc, int N);
void* GetNativeFnc(uintptr_t fnc);
void* GetNativeFncOrFnc(uintptr_t fnc);
int hasAlternate(void* addr);
void* getAlternate(void* addr);
void addAlternate(void* addr, void* alt);
void cleanAlternate();
#endif //__BRIDGE_H_
+2 -24
View File
@@ -3,34 +3,12 @@
#include <stdint.h>
typedef struct callbacklist_s callbacklist_t;
typedef struct x86emu_s x86emu_t;
callbacklist_t* NewCallbackList();
void FreeCallbackList(callbacklist_t** callbacks);
x86emu_t* AddCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4);
x86emu_t* AddVariableCallback(x86emu_t* emu, int stsize, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4);
x86emu_t* AddSmallCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4);
x86emu_t* AddSharedCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4);
x86emu_t* GetCallback1Arg(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1);
x86emu_t* FreeCallback(x86emu_t* emu);
uint32_t RunCallback(x86emu_t* emu);
void SetCallbackArg(x86emu_t* emu, int arg, void* val);
// set args starting from 0
void SetCallbackArgs(x86emu_t* emu, int nargs, ...);
// set args starting from N
void SetCallbackNArgs(x86emu_t* emu, int N, int nargs, ...);
void* GetCallbackArg(x86emu_t* emu, int arg);
void SetCallbackNArg(x86emu_t* emu, int narg);
void SetCallbackAddress(x86emu_t* emu, uintptr_t address);
uintptr_t GetCallbackAddress(x86emu_t* emu);
int IsCallback(box86context_t* context, x86emu_t* cb);
// use thread local emu to run the function (context is unused now)
uint32_t RunFunction(box86context_t *context, uintptr_t fnc, int nargs, ...);
// use thread local emu to run the function (context is unused now)
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, ...);
// Find a cb using FNC address and argN as a key
x86emu_t* FindCallbackFnc1Arg(x86emu_t* emu, uintptr_t fnc, int argn, void* arg);
#endif //__CALLBACK_H__
+8 -3
View File
@@ -13,6 +13,8 @@ extern int box86_dynarec_linker;
extern int box86_dynarec_trace;
extern int box86_dynarec_forced;
extern int box86_dynarec_largest;
extern int box86_dynarec_smc;
extern int box86_dynarec_safemmap;
#ifdef ARM
extern int arm_vfp; // vfp version (3 or 4), with 32 registers is mendatory
extern int arm_swap;
@@ -24,11 +26,14 @@ extern int trace_xmm; // include XMM reg in trace?
extern int trace_emm; // include EMM reg in trace?
extern int allow_missing_libs;
extern int box86_steam;
extern int box86_nopulse; // diabling the use of wrapped pulseaudio
extern int box86_nogtk; // disabling the use of wrapped gtk
extern uintptr_t trace_start, trace_end;
extern box86context_t *my_context; // global context
extern char* trace_func;
extern uintptr_t fmod_smc_start, fmod_smc_end; // to handle libfmod (from Unreal) SMC (self modifying code)
extern uint16_t default_fs;
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
#define LOG_NONE 0
#define LOG_INFO 1
#define LOG_DEBUG 2
@@ -38,7 +43,7 @@ extern FILE* ftrace;
#define printf_log(L, ...) do {if(L<=box86_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define dynarec_log(L, ...) do {if(L<=box86_dynarec_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define dynarec_log(L, ...) do {if(L<=box86_dynarec_log) {fprintf(ftrace, __VA_ARGS__); /*fflush(ftrace);*/}} while(0)
#define EXPORT __attribute__((visibility("default")))
#ifdef BUILD_DYNAMIC
+6 -12
View File
@@ -2,10 +2,9 @@
#define __DYNABLOCK_H_
typedef struct x86emu_s x86emu_t;
typedef struct dynablock_s dynablock_t;
typedef struct dynablocklist_s dynablocklist_t;
typedef struct kh_dynablocks_s kh_dynablocks_t;
uint32_t X31_hash_code(void* addr, int len);
dynablocklist_t* NewDynablockList(uintptr_t base, uintptr_t text, int textsz, int nolinker, int direct);
@@ -14,28 +13,23 @@ void FreeDynablock(dynablock_t* db);
void MarkDynablock(dynablock_t* db);
void MarkDynablockList(dynablocklist_t** dynablocks);
void ProtectDynablock(dynablock_t* db);
void ProtectkDynablockList(dynablocklist_t** dynablocks);
void ProtectDynablockList(dynablocklist_t** dynablocks);
void ProtectDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
// for debugging purpose
dynablock_t* FindDynablockFromNativeAddress(void* addr);
dynablock_t* FindDynablockFromNativeAddress(void* addr); // defined in box86context.h
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks);
uintptr_t StartDynablockList(dynablocklist_t* db);
uintptr_t EndDynablockList(dynablocklist_t* db);
void FreeDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
// Handling of Dynarec block (i.e. an exectable chunk of x86 translated code)
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current); // return NULL if block is not found / cannot be created. Don't create if create==0
// source is linked to dest (i.e. source->table[x] = dest->block), so add a "mark" in dest, add a "linked" info to source
void AddMark(dynablock_t* source, dynablock_t* dest, void** table);
// remove a Table mark (and also remove lined info from other dynablock, if any)
void RemoveMark(void** table);
dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr);
// Create and Add an new dynablock in the list, handling direct/map
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int with_marks, int* created);
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created);
#endif //__DYNABLOCK_H_
+1 -1
View File
@@ -4,6 +4,6 @@
typedef struct dynablock_s dynablock_t;
typedef struct x86emu_s x86emu_t;
void* FillBlock(dynablock_t* block);
void* FillBlock(dynablock_t* block, uintptr_t addr);
#endif //__DYNAREC_ARM_H_
+2
View File
@@ -53,5 +53,7 @@ dynablocklist_t* GetDynablocksFromElf(elfheader_t* h);
void ResetSpecialCaseMainElf(elfheader_t* h);
void CreateMemorymapFile(box86context_t* context, int fd);
int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is used
#endif //__ELF_LOADER_H_
+78 -6
View File
@@ -126,6 +126,65 @@ typedef struct my_GtkContainerClass_s
void (*_gtk_reserved4) (void);
} my_GtkContainerClass_t;
typedef struct my_GtkActionClass_s
{
my_GObjectClass_t parent_class;
void (* activate) (void* action);
int menu_item_type;
int toolbar_item_type;
void* (* create_menu_item) (void* action);
void* (* create_tool_item) (void* action);
void (* connect_proxy) (void* action, void* proxy);
void (* disconnect_proxy) (void* action, void* proxy);
void* (* create_menu) (void* action);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkActionClass_t;
typedef struct my_GtkMiscClass_s
{
my_GtkWidgetClass_t parent_class;
} my_GtkMiscClass_t;
typedef struct my_GtkLabelClass_s
{
my_GtkMiscClass_t parent_class;
void (* move_cursor) (void* label, int step, int count, int extend_selection);
void (* copy_clipboard) (void* label);
void (* populate_popup) (void* label, void* menu);
int (*activate_link) (void* label, void* uri);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
} my_GtkLabelClass_t;
typedef struct my_GtkTreeViewClass_s
{
my_GtkContainerClass_t parent_class;
void (* set_scroll_adjustments) (void* tree_view, void* hadjustment, void* vadjustment);
void (* row_activated) (void* tree_view, void* path, void* column);
int (* test_expand_row) (void* tree_view, void* iter, void* path);
int (* test_collapse_row) (void* tree_view, void* iter, void* path);
void (* row_expanded) (void* tree_view, void* iter, void* path);
void (* row_collapsed) (void* tree_view, void* iter, void* path);
void (* columns_changed) (void* tree_view);
void (* cursor_changed) (void* tree_view);
int (* move_cursor) (void* tree_view, int step, int count);
int (* select_all) (void* tree_view);
int (* unselect_all) (void* tree_view);
int (* select_cursor_row) (void* tree_view, int start_editing);
int (* toggle_cursor_row) (void* tree_view);
int (* expand_collapse_cursor_row) (void* tree_view, int logical, int expand, int open_all);
int (* select_cursor_parent) (void* tree_view);
int (* start_interactive_search) (void* tree_view);
void (*_gtk_reserved0) (void);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkTreeViewClass_t;
// GTypeValueTable
typedef struct my_GTypeValueTable_s {
void (*value_init) (void* value);
@@ -180,13 +239,25 @@ my_GtkTypeInfo_t* findFreeGtkTypeInfo(my_GtkTypeInfo_t* fcts, int parent);
void InitGTKClass(bridge_t *bridge);
void FiniGTKClass();
void SetGObjectID(int id);
void SetGTKObjectID(int id);
void SetGTKWidgetID(int id);
void SetGTKContainerID(int id);
void SetGTypeName(void* f);
#define GTKCLASSES() \
GTKCLASS(GObject) \
GTKCLASS(GtkObject) \
GTKCLASS(GtkWidget) \
GTKCLASS(GtkContainer) \
GTKCLASS(GtkAction) \
GTKCLASS(GtkLabel) \
GTKCLASS(GtkMisc) \
GTKCLASS(GtkTreeView) \
void* wrapCopyGTKClass(void* class, int type);
#define GTKCLASS(A) void Set##A##ID(int id);
GTKCLASSES()
#undef GTKCLASS
void SetGTypeName(void* f);
void AutoBridgeGtk(void*(*ref)(int), void(*unref)(void*));
void* wrapCopyGTKClass(void* cl, int type);
void* unwrapCopyGTKClass(void* klass, int type);
void my_checkGlobalGdkDisplay();
void my_setGlobalGThreadsInit();
@@ -205,6 +276,7 @@ typedef struct my_signal_s {
my_signal_t* new_mysignal(void* f, void* data, void* destroy);
void my_signal_delete(my_signal_t* sig);
int my_signal_is_valid(void* sig);
int my_signal_cb(void* a, void* b, void* c, void* d);
#endif //__GTKCLASS_H__
+5 -5
View File
@@ -558,11 +558,11 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key)
@param kvar Variable to which key will be assigned
@param code Block of code to execute
*/
#define kh_foreach_key(h, kvar, code) { khint_t __i; \
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
if (!kh_exist(h,__i)) continue; \
(kvar) = kh_key(h,__i); \
code; \
#define kh_foreach_key(h, kvar, code) { khint_t __i; \
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
if (!kh_exist(h,__i)) continue; \
(kvar) = kh_key(h,__i); \
code; \
} }
/*! @function
+2 -7
View File
@@ -102,10 +102,6 @@ typedef enum {
#pragma pack(push, 1)
typedef union {
#ifdef USE_FLOAT
float f;
uint32_t ll; // same, to avoid more #ifdef...
#else
double d;
struct {
uint32_t lower;
@@ -116,7 +112,6 @@ typedef union {
float upper;
} f;
int64_t ll;
#endif
} fpu_reg_t;
typedef union {
@@ -137,8 +132,8 @@ typedef struct {
} fpu_ld_t;
typedef struct {
uint64_t ll;
uint64_t ref;
int64_t ll;
int64_t ref;
} fpu_ll_t;
typedef union {
+1 -1
View File
@@ -34,7 +34,7 @@ int my___sigaction(x86emu_t* emu, int signum, const x86_sigaction_t *act, x86_si
int my_syscall_sigaction(x86emu_t* emu, int signum, const x86_sigaction_restorer_t *act, x86_sigaction_restorer_t *oldact, int sigsetsize);
void init_signal_helper();
void init_signal_helper(box86context_t* context);
void fini_signal_helper();
#endif //__SIGNALS_H__
Loaded 100 of 273 files, more files were not shown because too many files have changed in this diff. Show more