Compare commits

..
1234 Commits
Author SHA1 Message Date
ptitSeb 769c6c8f61 Bumped version to v0.3.2 2024-12-06 15:59:59 +01:00
Yang Liu b250056a61 [DYNAREC] Fixed a typo which leads to regression (#2121) 2024-12-06 15:21:23 +01:00
ptitSeb e305e5f1bb [BOX32][WRAPPER] Cosmetic fix an a function signature 2024-12-06 14:48:41 +01:00
rajdakin 18ce48e2c0 [WRAPPERHELPER] Fixed a use-after-free issue (#2118) 2024-12-06 13:29:20 +01:00
Leslie Zhai 06c93c93fe [LA64_DYNAREC] Added XOR AX, Iw opcode (#2116) 2024-12-06 10:40:02 +01:00
ptitSeb 869ddcfdda [WRAPPER] Another improved dlsym wrapped function, hopefully fixing regression (should help #2115) 2024-12-06 08:53:59 +01:00
ptitSeb 65e5e86c2b [RV64_DYNAREC] Improve native flag handling 2024-12-06 08:50:49 +01:00
ptitSeb 122b5e64e8 [BOX32][WRAPPER] Added a couple more 32bits wrapped functions to libc 2024-12-05 15:19:28 +01:00
ptitSeb 6c66d66b02 [BOX32][ELFLOADER] Be less strick when a symbol for R_386_32 relocation is missing 2024-12-05 15:19:02 +01:00
ptitSeb 85d694b36e [BOX32][WRAPPER] Fixed an issue wih an X11 32bits wrapped function 2024-12-05 15:11:49 +01:00
ptitSeb 44cff3ae25 [BOX32][WRAPPER] Added one more 32bits wrapped function to libc 2024-12-05 14:21:12 +01:00
Leslie Zhai c2d7dc573a [LA64_DYNAREC] Added HLT opcode (#2112) 2024-12-05 20:03:06 +08:00
ptitSeb a30433ea12 [NON4KPAGE] Some more adjustments for non-4Kpagesize system (should help #2110) 2024-12-05 11:12:02 +01:00
Yang Liu 6f7b462d53 [DYNAREC] Introduced TO_NAT to ease register mapping changes in future (#2111) 2024-12-05 10:16:22 +01:00
ptitSeb 95e5724117 [ANDROID] Install Android libs for android build 2024-12-04 18:43:24 +01:00
ptitSeb 1eaef70d2d [ANDROID] Updaed test21 for Android build 2024-12-04 18:27:24 +01:00
ptitSeb 3ed1e565f8 Disable another execution test when pagesize is not 4K 2024-12-04 17:52:05 +01:00
ptitSeb 8d0c976a18 [BOX32] Upped max number of x11 display slot from 4 to 16 2024-12-04 17:15:14 +01:00
ptitSeb 9165ec875a [BOX32] Some fixes to a few file related 32bits wrapped function (now windows gog installer can be used with box32 and wine) 2024-12-04 16:58:05 +01:00
ptitSeb 6a7997b41e [BOX32] Fix mystake on previous commit 2024-12-04 15:47:06 +01:00
ptitSeb 2a9d863131 [BOX32][WRAPPER] Added ldiv 32bits wrapped function (now Undertale works with box32, probably other linux gamestudio games too) 2024-12-04 15:20:14 +01:00
ptitSeb e3e9a86088 Added some more termux path to automatic ld_path 2024-12-04 14:35:41 +01:00
ptitSeb d5c787c213 [RCFILE] Better profile for dav1d 2024-12-04 13:57:30 +01:00
ptitSeb 559040e290 [BOX32][WRAPPER] Added a few more X11 32bits wrapped functions 2024-12-04 11:28:43 +01:00
ptitSeb 59ba5b7f0e [BOX32][WRAPPER] Fixed a typo in Xcursor wrapping (should help #2109) 2024-12-04 09:59:57 +01:00
ptitSeb 474a43a424 [BOX32][WRAPPER] Fixed typos from previous build 2024-12-03 19:48:34 +01:00
ptitSeb fb276bdc6b [BOX32][WRAPER] Fixed Xcursor wrapping 2024-12-03 18:45:46 +01:00
ptitSeb 1c1a26626b [ELFLOADER] Fixed a typo in a hack 2024-12-03 17:41:54 +01:00
ptitSeb 93f29d8cd9 Fix X64 build 2024-12-03 14:02:48 +01:00
ptitSeb 0054dde600 Restored old test21, the CI doesn't seems to like the new one 2024-12-03 12:54:54 +01:00
ptitSeb 794f2104bc Improved signal handling ([BOX32] Too) 2024-12-03 11:43:46 +01:00
Yang Liu 036af9f55f [LA64_DYNAREC] Fixed sign extension of 8-bit immediate in 66 opcodes (#2106) 2024-12-03 11:26:24 +01:00
ptitSeb 5bde45cc86 [DYNAREC] Made weakbarrier=1 and pause=3 default 2024-12-03 11:25:10 +01:00
ptitSeb ae1739f330 Improved dlsym wrapped function, will find more symbols from emulated libs 2024-12-03 10:23:18 +01:00
Yang Liu cfc09e0965 [WRAPPER] Wrapped more symbols in libcrypto3 (#2105) 2024-12-03 10:00:48 +01:00
ptitSeb 26c9b3426f [CI] Bumped test timeout to 120 sec 2024-12-03 09:25:39 +01:00
Yang Liu 963da34562 [CMAKE] Fixed typos (#2104) 2024-12-03 08:52:50 +01:00
ptitSeb 4adad381ce [BOX32] Improved test17 2024-12-02 17:14:42 +01:00
ptitSeb e561196f44 Improved test16 2024-12-02 17:01:08 +01:00
Yang Liu 14bd1368cc [RV64_DYNAREC] Added simple opcodes fusion as "native flags" (#2102)
* [RV64_DYNAREC] Added simple opcodes fusion as "native flags"

* Disable 16bit CMOV

* review
2024-12-02 16:58:20 +01:00
ptitSeb 415fc458be [ARM64_DYNAREC] Improved some x87 opcode behaviour 2024-12-02 16:19:06 +01:00
ptitSeb f2822f1a05 [INTERPRETER] Improved some x87 opcode behaviour 2024-12-02 16:18:41 +01:00
Leslie Zhai 646dd718f5 [LA64_DYNAREC] Added INSB, INSD, OUTSB and OUTSD opcodes (#2100) 2024-12-02 11:07:45 +01:00
ptitSebandrajdakin 83ed8ebb22 Android Long Double handling (#2101)
* [ANDROID] Try to handle LongDouble in vaarg correctly

* [ANDROID] Try to enable test07

* [WRAPPED] Fixed Android long double handling (#2096)

* [WRAPPED] Fixed Android long double handling

* [WRAPPED] Force casting to uintptr_t

* [WRAPPED] Fixed a typing issue, removed a warning in the CI

---------

Co-authored-by: rajdakin <[email protected]>
2024-12-02 10:50:21 +01:00
ptitSeb 88aab487f1 [BOX32] Some improvment on steam handling 2024-12-02 10:25:12 +01:00
ptitSeb 6d1e30cd3c [BOX32][WRAPPER] Improved 32bits freetype wrapping (wine explorer have correct fonts now) 2024-12-01 17:33:57 +01:00
ptitSeb ab73969ea4 [BOX32][WRAPPER] Improved networks functions 2024-12-01 12:32:33 +01:00
ptitSeb 93b371eb8c *[ARM64_DYNAREC] Fixed some cases of memory access on BTR/BTS opcodes (for #2093) 2024-12-01 10:03:25 +01:00
ptitSeb b7007a1bdd [BOX32][WRAPPER] Added a few more FreeType wrapped functions 2024-11-30 17:00:05 +01:00
ptitSeb a26c108464 [ARM64_DYNAREC] Added F2 0F 80..8F opcodes 2024-11-30 16:59:38 +01:00
ptitSeb 2971e9729c [BOX32][WRAPPER] This should fix the build 2024-11-30 15:07:01 +01:00
ptitSeb 6b2d923041 [WRAPPER] Added 1 more function to libgcrypt 2024-11-30 14:54:51 +01:00
ptitSeb cb30db320e [BOX32][WRAPPER] Added some more libc wrapped functions 2024-11-30 14:50:48 +01:00
ptitSeb e1ae914a1d [WRAPPER] Fixed libc wrappers includes 2024-11-30 14:25:08 +01:00
ptitSeb 51aa4b0416 Added a new memExist helper function and use it instead of getMmapped were it make sense 2024-11-30 14:02:28 +01:00
ptitSeb b0db168fb5 [INTERPRETER] Added 0F 30 ocpode ([RM64_DYNAREC] too) (for #2090) 2024-11-30 11:35:14 +01:00
ptitSeb 3b3338d132 [BOX32][WRAPPER] Added a few new wrapped functions 2024-11-29 20:45:40 +01:00
ptitSeb cc50331745 [BOX32][WRAPPED] Added one more obstack wrapped function 2024-11-29 19:15:01 +01:00
ptitSeb 2777bc142f Forgot this file on previous commit 2024-11-29 19:14:17 +01:00
ptitSeb c73545e25b [BOX32][WRAPPER] Added minimum libresolv wrapping 2024-11-29 19:10:11 +01:00
ptitSeb b862e74ae4 [BOX32][WRAPPER] Added obstack_vprintf wrapped symbol 2024-11-29 18:49:14 +01:00
ptitSeb 0d662b8543 [WRAPPER] Refactored some glib2 signal handling 2024-11-29 17:07:58 +01:00
ptitSeb ea0b23b783 Better hadnling of LD_PRELOAS on Steam Pressure Vessel wrapper 2024-11-29 17:07:31 +01:00
ptitSeb f15a187087 [TRACE] Show backtrace on emit_signal too if asked 2024-11-29 10:27:59 +01:00
ptitSeb 12a82cf91f [WRAPPER] Added back faked ITM weak functions 2024-11-29 10:27:23 +01:00
ptitSeb 5af2fa49c3 [WRAPPER] Fixed wrapped dlerror behaviour 2024-11-29 10:25:21 +01:00
Yang Liu 843fe30e46 [RV64] Added nan propagation emulation for interpreter and DynaRec (#2091)
* [RV64] Added nan propagation emulation for interpreter and DynaRec

* oops
2024-11-28 15:14:45 +01:00
ptitSeb 0da561cd20 [WRAPPER] Reworked sqlite3 with new wrapperhelper 2024-11-28 10:10:17 +01:00
rajdakin fd613de55e [WRAPPERHELPER] Transform from function to data if needed (#2089) 2024-11-28 09:17:00 +01:00
Leslie Zhai b2dc460db9 [RV64_DYNAREC] Fix PTEST X_CF typo (#2088) 2024-11-28 08:11:01 +01:00
Leslie Zhai e5b7dfb524 [LA64_DYNAREC] Added LEA opcode (#2087) 2024-11-28 08:09:49 +01:00
ptitSeb de0b602748 Added syscall 280 2024-11-27 19:52:52 +01:00
ptitSeb d0d85e684d [WRAPPER] More work on gtk/gstreamer wrapping 2024-11-27 19:52:52 +01:00
Yang Liu 05b322414a [RV64_DYNAREC] Fixed another regression in vector (#2086) 2024-11-27 17:11:25 +01:00
ptitSeb 38ee050a09 [BOX32] Added 32bits syscall 2 2024-11-27 16:05:22 +01:00
Yang Liu 1ee4959c05 [LA64_DYNAREC] Added nativeflags option support (#2084) 2024-11-27 10:38:46 +01:00
Yang Liu bc9086551b [RV64_DYNAREC] Fixed more regressions for vector (#2082) 2024-11-26 20:58:12 +01:00
ptitSeb f9f0c99c1b [WRAPPER] Reworked gstvideo with new wrapperhelper 2024-11-26 17:33:46 +01:00
ptitSeb a1b46711c4 [WRAPPER] Reworked gsttag with new wrapperhelper 2024-11-26 16:44:47 +01:00
ptitSeb f6bb071f84 [WRAPPER] Reworked gstsdp with new wrapperhelper 2024-11-26 16:41:14 +01:00
ptitSeb 746a0031f8 [WRAPPER] Reworked gst-rtp and gst-rtsp with new wrapperhelper 2024-11-26 16:36:13 +01:00
ptitSeb f78d0ae471 [WRAPPER] Reworked gstriff with new wrapperhelper 2024-11-26 16:27:53 +01:00
ptitSeb 7879a33cdc [WRAPPER] Reworked gst-pbutils with new wrapperhelper 2024-11-26 16:22:39 +01:00
ptitSeb a84a9847be [WRAPPER] Reworked gstnet with new wrapperhelper 2024-11-26 16:20:06 +01:00
ptitSeb 0c54e19c5f [WRAPPER] Reworked gst-gl with new wrapperhelper 2024-11-26 16:17:44 +01:00
rajdakin d507f8a6d0 [WRAPPERHELPER] Accept and ignore semicolons instead of declarations (#2081) 2024-11-26 13:56:18 +01:00
ptitSeb b18efe4e40 [WRAPPER] Reworked gstfft with new wrapperhelper 2024-11-26 11:55:05 +01:00
ptitSeb 83d69939f3 [WRAPPER] Reworked gstcontroller with new wrapperhelper 2024-11-26 11:53:08 +01:00
ptitSeb aee5032597 [WRAPPER] Reworked gstcheck with new wrapperhelper 2024-11-26 10:45:44 +01:00
ptitSeb c7cc78194f [ARM64_DYNAREC][TRACE] Use BLR on ret/retn with TRACE to allow relevant debug informations on bad returns 2024-11-26 10:34:12 +01:00
ptitSeb 089db91b39 [WRAPPER] Reworked gstbase with new wrapperhelper 2024-11-26 10:33:04 +01:00
rajdakin cb33043dd4 [WRAPPERHELPER] Fixed a parsing error (#2079) 2024-11-26 10:16:11 +01:00
Leslie Zhai b207ecad6a [LA64_DYNAREC] Added SBB opcodes (#2076)
* [LA64_DYNAREC] Added SBB opcodes

* [LA64_DYNAREC] clang-format and fix LOCK ADC wrong ed
2024-11-26 08:27:13 +01:00
xctan 48461001d2 [RV64_DYNAREC] Fixed vector packed logical shift opcodes (#2075)
* [RV64_DYNAREC] Fixed vector packed logical shift opcodes

* [RV64_DYNAREC] Fixed a operand violation in vector CVTSD2SS
2024-11-26 08:21:57 +01:00
ptitSeb 12649d04c7 [WRAPPER] Reworked gstaudio with new wrapperhelper 2024-11-25 18:51:48 +01:00
ptitSeb 5033738f73 [WRAPPER] Reworked gstapp with new wrapperhelper 2024-11-25 18:38:51 +01:00
ptitSeb df80b9c5de [WRAPPER] Reworked wrapping of gstallocators with new wrapperhelper 2024-11-25 18:33:35 +01:00
ptitSeb ffa94268d7 [WRAPPER] Reworked gstreamer with new wrapperhelper 2024-11-25 18:06:41 +01:00
xctan b7f0996459 [RV64_DYNAREC] Fixed vector SSE unpack opcodes (#2074) 2024-11-25 18:04:04 +01:00
Chi-Kuan Chiu dcf196c2ae [RBTREE] Document the rationale for memory management (#2060)
Enhanced the rbtree.h header with detailed documentation comments for
each function.
This comment aims to clarify the role of the red-black tree in memory
management and how these functions interact with and manage memory.
2024-11-25 17:08:05 +01:00
rajdakin a71856801b [WRAPPERHELPER] Added the --gst option (#2072) 2024-11-25 16:13:04 +01:00
Yang Liu 84608fc581 [ARM64_DYNAREC] Added DYNAREC_PAUSE option for hint instructions (#2070)
* [ARM64_DYNAREC] Added DYNAREC_PAUSE option for hint instructions

* Use sevl for wfe

* Add docs

* Fix typo

* use switch case
2024-11-25 11:28:19 +01:00
Leslie Zhai c30a392fe8 [LA64_DYNAREC] Add adc8, adc8c, adc16 and testadc (#2069)
* [LA64_DYNAREC] Add adc8, adc8c, adc16 and testadc

* [LA64_DYNAREC] Add missing testcase

* [LA64_DYNAREC] Change ANDI+OR to BSTRINS_D for ADC AL, Ib and removed testadc

* [LA64_DYNAREC] clang-format
2024-11-25 08:12:20 +01:00
rajdakin d8c16de2ec [WRAPPERHELPER] Fixed pragma once handling (#2067) 2024-11-24 22:19:28 +01:00
Yang Liu 2d04cbe97c [ARM64_DYNAREC] Use YIELD instead of WFE (#2066) 2024-11-24 20:04:01 +01:00
xctan ab65422034 [CORE] Enhanced BOX64_DYNAREC_RV64NOEXT (#2065) 2024-11-24 19:32:39 +01:00
xctan 3bde222242 [RV64_DYNAREC] Added, fixed, and optimized opcodes (#2059)
* [RV64_DYNAREC] Added 66 0F 38 37 PCMPGTQ opcode

* [RV64_DYNAREC] Added 66 0F 17 MOVHPD opcode

* [RV64_DYNAREC] Added 66 0F 38 15 PBLENDVPD opcode

* [RV64_DYNAREC] Optimized vector SSE packed compare

* [RV64_DYNAREC] Optimized vector MMX MOVD Gm, Ed

* [RV64_DYNAREC] Optimized vector SSE PMADDWD opcode

* [RV64_DYNAREC] Added vector PCMPGTQ opcode

* [RV64_DYNAREC] Added vector 66 0F 17 MOVHPD opcode

* [RV64_DYNAREC] Optimized vector 66 0F 16 MOVHPD opcode

* [RV64_DYNAREC] Added vector PBLENDVPD opcode

* [RV64_DYNAREC] Optimized vector PMADDUBSW opcode

* [RV64_DYNAREC] Optimized vector SSE logical shifts with Ex

* [RV64_DYNAREC] Optimized vector SSE unpack

* [RV64_DYNAREC] Added F0 F6 /2 LOCK NOT opcode

* [RV64_DYNAREC] Fixed vector packed logical shift
2024-11-24 16:57:34 +01:00
ptitSeb d0af86d5bf [VULKAN] Added a new extension and a missing function 2024-11-24 15:53:12 +01:00
ptitSeb 73b17d4add [ARM64_DYNAREC] Fix a regression, as 90 opcode is not always NOP depending on REX (should help #2064) 2024-11-24 15:28:21 +01:00
Yang Liu 93fa5323c5 [ARM64_DYNAREC] Generate corresponding hint instruction for PAUSE (#2063) 2024-11-24 11:19:36 +01:00
Yang Liu b0c10c9ae5 [RV64_DYNAREC] Minor optimizations on CMPXCHG (#2062) 2024-11-24 08:49:02 +01:00
rajdakin b8ed1b9646 [WRAPPERHELPER] Added support to cast to enum (#2061) 2024-11-23 22:01:40 +01:00
ptitSeb 0912e8f16d [ARM64_DYNAREC] Small optim for emit_shld32c CF flag computation 2024-11-23 14:37:19 +01:00
ptitSeb 327dc2c835 [DYNAREC] Better detection of wait slot 2024-11-23 13:06:26 +01:00
ptitSeb 8f937788ce [BOX32] Removed a debug leftover 2024-11-23 10:21:01 +01:00
Yang Liu 52ba725fa5 Reworked on mmap address alignments for a performance regression (#2057) 2024-11-22 12:06:55 +01:00
ptitSeb a39249454e Slightly better way to decode wrappers 2024-11-21 15:28:30 +01:00
ptitSeb c1f2304c88 Small fix for XSAVE/XRSTOR opcodes ([DYNAREC] too) 2024-11-21 12:08:43 +01:00
Yang Liu 85c6e28d47 [LA64_DYNAREC] Added more opcodes for JDK (#2055) 2024-11-21 11:44:47 +01:00
Yang Liu d1a253f469 [DYNAREC] Reuse strongmem infra for all backends (#2052) 2024-11-21 08:06:47 +01:00
ptitSeb 6aa57f5c73 [RCFILE] More adjustments with new strongmem 2024-11-20 21:02:08 +01:00
ptitSeb 023aeae9e6 Removed another debug leftover 2024-11-20 20:33:47 +01:00
ptitSeb 38880ab5a4 [TRACE] Don't try to decode a bridge if memory is not mapped or un-readable 2024-11-20 20:03:48 +01:00
ptitSeb 4e19324177 Removed a debug leftover 2024-11-20 20:03:10 +01:00
Yang Liu 9757d1b67a [ARM64_DYNAREC] More optimizations on strongmem emulation (#2051) 2024-11-20 18:59:20 +01:00
theofficialgman 5422b108af update pressure_vessel function with additional valid BOX86_LD_LIBRARY_PATH (#2050) 2024-11-20 18:15:03 +01:00
ptitSeb 0d650b183f [RCFILE] Addjusted some profile with new strongmem capabilities 2024-11-20 12:47:56 +01:00
Yang Liu fa432bb9d1 [ARM64_DYNAREC] Added weakbarrier=2 to disable last write barriers (#2049) 2024-11-19 21:22:55 +01:00
Yang Liu 81e4e26dc5 [ARM64_DYNAREC] Re-enable weakbarrier for dmb.ishst (#2048) 2024-11-19 19:59:43 +01:00
Yang Liu 4f6a66f9c6 [CI] Generate and upload .wcp file for Winlator (#2045)
* [CI] Generate and upload .wcp file for Winlator

* patch box64

* test box64 before the patch

* opt out static build

* typos
2024-11-19 13:49:35 +01:00
Yang Liu 127d273ada [DYNAREC] Reworked strong memory emulation (#2043)
* [ARM64_DYNAREC] Reworked strong memory emulation

* Simplify

* [RV64,LA64_DYNAREC] Reworked strong memory emulation

* forgot this

* more tweaks
2024-11-19 09:39:57 +01:00
liuli 469d4f81eb [WRAPPER]my_dbus_message_get_args() args type error (#2042)
* [WRAPPER]my_dbus_message_get_args() args type error

* [WRAPPER]my_dbus_message_get_args() args type error
2024-11-19 08:05:40 +01:00
ptitSeb 8f08a14115 Improved Signal handling ([ARM4_DYNAREC] too) 2024-11-18 17:18:41 +01:00
ptitSeb 4ac43047d0 [BOX32] Fixed previous commit 2024-11-18 11:14:07 +01:00
ptitSeb 4257fdded3 [BOX32] Fixed long double handling on printf like functions 2024-11-18 11:07:44 +01:00
ptitSeb 56298870f6 [ARM64_DYNAREC] Only propagate native flags if at least 1 opcode consume them 2024-11-17 15:14:13 +01:00
ptitSeb 48354185dd [WRAPPER] Added last 2 wrapped function for libexpat 2024-11-17 11:45:30 +01:00
ptitSeb 5f0cbcf26d [WRAPPER] Fixed an isue with __iso99_swcanf wrapped function 2024-11-17 11:45:00 +01:00
ptitSeb ffc875c2d6 [WRAPPER] Added wrapped libzstd.so.1 support, with new wrapperhelper 2024-11-17 11:30:30 +01:00
ptitSeb 8a180e3892 [ARM64_DYNAREC] Cancel native flags when an opcode use native flags not fully covered by the generated ones 2024-11-17 11:02:21 +01:00
ptitSeb c4d3d734b1 [DYNAREC] Mark existing block as dirty when re-creating a memory block 2024-11-17 11:00:28 +01:00
ptitSeb 6e8c244b77 [TRACE] Use lower case hex on rbtree 2024-11-17 10:59:34 +01:00
ptitSeb ac2ed68228 [WRAPPER] Added 2 more wrapped function to libcrypto.so.3 (for #1271) 2024-11-16 14:39:48 +01:00
ptitSeb fb27c89282 [WRAPPER][BOX32] Fixed a few wrapped functions (for hl2) 2024-11-16 14:31:46 +01:00
ptitSeb 74bed6edcb [ARM64_DYNAREC] Fixed potential issues with 0F A3/AB/B3/BB opcodes 2024-11-16 14:31:20 +01:00
ptitSeb 49a854fa7e [INTERPRETER] Fixed potential issue with 0F A3 opcode 2024-11-16 13:44:36 +01:00
ptitSeb 5adabbbcaa [ARM64_DYNAREC] Small optim in emit_sar8c helper 2024-11-16 13:23:23 +01:00
ptitSeb 42eae3e1b4 Expose a few more CPU features 2024-11-16 12:48:12 +01:00
ptitSeb 518d2b0129 Removed a debug leftover 2024-11-16 12:19:14 +01:00
ptitSeb bc8c786b80 Smal adjustment in singal handling for no-execution error 2024-11-16 12:16:51 +01:00
Yang Liu 5ab8a6f6f4 [WRAPPER] Fixed myStackAlignGVariantNew and refined the test too (#2038) 2024-11-15 21:37:36 +01:00
ptitSeb 385a31ec11 [ARM64_DYNAREC] Various fixes and improvments to a few random opcodes 2024-11-15 21:05:41 +01:00
ptitSeb 5c49954f69 [DYNAREC] Zero'd upper 32bits of regs when switching to 32bits from 64bits 2024-11-15 21:05:06 +01:00
ptitSeb 6ce7a1ba1f [INTERPRETER] Zero'd upper 32bits of regs when switching to 32bits from 64bits 2024-11-15 21:03:59 +01:00
ptitSeb 8c1335626f [ARM64_DYNAREC] A few fixes to 8/16bits logic/math opcodes 2024-11-15 15:34:22 +01:00
ptitSeb 8b0eec097b [TRACE] More info on signal 2024-11-15 15:34:00 +01:00
ptitSeb a39c8aa5c5 [INTERPRETER] Some cleanup on base logic/math/shift operations 2024-11-15 14:37:16 +01:00
ptitSeb 27745ceebb Added support for RDMSR, just in case 2024-11-15 14:36:42 +01:00
ptitSeb 64b213fe42 [ARM64_DYNAREC] Try to not call UpdateFlags when switching to a DFNONE state but dfnone is not needed 2024-11-15 14:27:43 +01:00
ptitSeb eaca84e9ba [ARM64_DYNAREC] Very small change on on emit_rol32c helper 2024-11-15 14:26:25 +01:00
xctan bca0f4d66d [RV64_DYNAREC] Added more MMX opcodes for vector (#2037)
* [RV64_DYNAREC] Added 0F 74-76 PCMPEQB/W/D opcodes

* [RV64_DYNAREC] Added 0F 64-66 PCMPGTB/W/D opcodes

* [RV64_DYNAREC] Added 0F E1-E2 PSRAW/D opcodes

* [RV64_DYNAREC] Added 0F 6E MOVD opcode

* [RV64_DYNAREC] Added 0F 73 /2 PSRLQ opcode

* [RV64_DYNAREC] Added 0F 73 /6 PSLLQ opcode
2024-11-15 10:11:11 +01:00
ptitSeb 8c17a37d1a [ARM64_DYNAREC] Reworked 8/16/32/64bits TEST opcodes 2024-11-14 18:54:40 +01:00
xctan 979a3232f9 [RV64_DYNAREC] Added more MMX opcodes for vector (#2035)
* [RV64_DYNAREC] Added 0F 68 PUNPCKHBW opcode

* [RV64_DYNAREC] Added 0F 69 PUNPCKHWD opcode

* [RV64_DYNAREC] Added 0F 6A PUNPCKHDQ opcode

* [RV64_DYNAREC] Updated 0F 68-69 PUNPCKHBW/WD opcodes

* [RV64_DYNAREC] Added 0F 60 PUNPCKLBW opcode

* [RV64_DYNAREC] Added 0F 61 PUNPCKLWD opcode

* [RV64_DYNAREC] Added 0F 62 PUNPCKLDQ opcode

* [RV64_DYNAREC] Simplified MMX PUNPCK{L,H}{BW,WD,DQ}
2024-11-14 17:41:28 +01:00
Yang Liu 47dbbe030c [DYNAREC] Added a experimental BOX64_DYNAREC_WEAKBARRIER option (#2033)
* [DYNAREC] Added a experimental BOX64_DYNAREC_WEAKBARRIER option

* Added it to the RCFILE
2024-11-14 17:41:12 +01:00
ptitSeb d05e719ce3 [ARM64_DYNAREC] Refactor 8/16/32/64bits CMP and REP CMPS/SCAS opcodes 2024-11-14 16:43:01 +01:00
Leslie Zhai 12f4afcba2 [LA64] Implement convert x64_va_list_t to sysv_varargs for float (#2025) (#2031)
* [LA64] Implement convert x64_va_list_t to sysv_varargs for float (#2025)

* [LA64] Implement myStackAlignGVariantNew (#2025)

* [LA64] Limit the log to LOG_DEBUG (#2055)

* [LA64] Add missing file (#2025)
2024-11-14 16:01:36 +01:00
ptitSeb cd2638d11a [ARM64_DYNAREC] Some refactor on 8/16/32/64bits SHL/SHR/SAR opcodes 2024-11-14 15:00:58 +01:00
ptitSeb c87796e51c [ARM64_DYNAREC] Minor change on 16bits neg opcode 2024-11-14 12:43:30 +01:00
ptitSeb d47b555e12 [ARM64_DYNAREC] Some rework on 8/16/32/64 INC/DEC opcodes 2024-11-14 11:20:57 +01:00
Yang Liu 4e568e1fdf Minor adjustments to README, updated README_CN (#2032) 2024-11-14 11:15:36 +01:00
Diego q 0688c53675 Update README.md (#2022)
* Update README.md

I made it more readable to the normal human being, kept all important info, rewrote everything to make it cleaner, and re-organized a few things, let me know if you want anything extra added

* Update README.md

Added And Fixed Some things as requested

* Update README.md

Fixed Everything Requested
2024-11-14 08:11:01 +01:00
ptitSeb 6d523f9c7f [ARM64_DYNAREC] Small optim for 8/16/32/64bits adc/sbb opcodes 2024-11-13 20:00:02 +01:00
ptitSeb 0f4f274bc7 [ARM64_DYNAREC] Various small fixes for some 16bits math/logic opcodes 2024-11-13 19:48:44 +01:00
xctan 09b8c3b94e [RV64_DYNAREC] Added more MMX opcodes for vector (#2027)
* [RV64_DYNAREC] Added 0F D5 PMULLW opcode

* [RV64_DYNAREC] Added 0F E5 PMULHW opcode

* [RV64_DYNAREC] Added 0F F5 PMADDWD opcode

* [RV64_DYNAREC] Added 0F 6B PACKSSDW opcode

* [RV64_DYNAREC] Added 0F 63 PACKSSWB opcode

* [RV64_DYNAREC] Added 0F 67 PACKUSWB opcode

* [RV64_DYNAREC] Removed useless vsetvli in MMX PACKUSWB/SSWB/SSDW
2024-11-13 19:43:57 +01:00
ptitSeb 1dbb676f38 [ARM64_DYNAREC] Reworked 8/16/32/64bits XOR opcodes 2024-11-13 18:46:47 +01:00
ptitSeb 331866bd1d [ARM64_DYNAREC] Fixed previous commit 2024-11-13 18:32:43 +01:00
ptitSeb 2515096f56 [ARM64_DYNAREC] Reworked 8/16/32/64 OR opcodes 2024-11-13 17:34:21 +01:00
ptitSeb 8868023ce9 [ARM64_DYNAREC] Reworked 8/16/32/64bits AND opcodes 2024-11-13 17:12:03 +01:00
ptitSeb dd9d6f8f83 [ARM64_DYNAREC] Small change in sbb32 helper 2024-11-13 15:18:56 +01:00
ptitSeb 21e403c908 [WRAPPER] Added more callback slots for libwaylend-client 2024-11-13 14:39:08 +01:00
ptitSeb f66aa57594 [ARM64_DYNAREC] Improved div/idiv opcode flags (non)handling 2024-11-13 14:38:14 +01:00
Yang Liu 506cb980b1 [RV64_DYNAREC] Prefer AMO* instructions over LR/SC when possible (#2028)
* [RV64_DYNAREC] Prefer AMO* instructions over LR/SC when possible

* fixes
2024-11-13 14:22:25 +01:00
ptitSeb 937e2cf853 [ARM64_DYNAREC] Improved 32/64bits imul/mul opcodes flags handling 2024-11-13 13:31:32 +01:00
xctan 82bf71ee19 [RV64_DYNAREC] Added more MMX opcodes for vector (#2026)
* [RV64_DYNAREC] Added 0F F8-FB PSUBB/W/D/Q opcodes

* [RV64_DYNAREC] Added 0F E8 PSUBSB opcode

* [RV64_DYNAREC] Added 0F D8-D9 PSUBUSB/W opcodes

* [RV64_DYNAREC] Added 0F F1-F3 PSLLW/D/Q opcodes

* [RV64_DYNAREC] Added 0F E9 PSUBSW opcode

* [RV64_DYNAREC] Added 0F EB POR opcode

* [RV64_DYNAREC] Added 0F DB PAND opcode

* [RV64_DYNAREC] Added 0F DF PANDN opcode

* [RV64_DYNAREC] Added 0F EF PXOR opcode

* [RV64_DYNAREC] Optimized rvv MMX PSLLW/D/Q
2024-11-13 11:04:43 +01:00
xctan eb9e7b9fee [RV64_DYNAREC] Added more MMX opcodes for vector (#2024)
* [RV64_DYNAREC] Added 0F D1-D3 PSRLW/PSRLD/PSRLQ opcode

* [RV64_DYNAREC] Added 0F EC PADDSB opcode

* [RV64_DYNAREC] Added 0F DC-DD PADDUSB/PADDUSW opcode

* [RV64_DYNAREC] Added 0F FC-FE PADDB/PADDW/PADDD opcodes

* [RV64_DYNAREC] Added 0F ED PADDSW opcode

* [RV64_DYNAREC] Added 0F 7F MOVQ opcode

* [RV64_DYNAREC] Fixed some typos

* [RV64_DYNAREC] Optimized RVV MMX PSRLW/D/Q to a mask-less version
2024-11-13 10:08:16 +01:00
Yang Liu b02942c0b0 [RV64_DYNAREC] Made eflags emulation branchless with xtheadcondmov (#2019)
* [RV64_DYNAREC] Made eflags emulation branchless with xtheadcondmov

* more
2024-11-11 19:53:55 +01:00
Yang Liu 56e813ccb7 [RV64_DYNAREC] Added more MMX opcodes for vector (#2017)
* [RV64_DYNAREC] Added more MMX opcodes for vector

* fixed
2024-11-11 12:29:55 +01:00
Yang Liu cf5b94d471 [CORE][LA64] Check LASX and display its existence (#2016) 2024-11-10 17:41:31 +01:00
ptitSeb 5d941f702a Preserve errno on mmap / munmap speicifc memory traqking operations 2024-11-10 11:09:33 +01:00
ptitSeb b46925e7e0 [WRAPPER] Added wrapped libXaw with new wrapperhelper (for #1990) 2024-11-09 18:36:27 +01:00
ptitSeb e676756cda [DYNAREC] Small chnage o hotpage detection to make it less sensitive 2024-11-09 18:12:43 +01:00
ptitSeb 591958c59c [RCFILE] advertise that BOX64_DYNAREC_TEST=1 is applied 2024-11-09 18:12:09 +01:00
ptitSeb 63a80ff696 This should fix LA64 Static build 2024-11-09 17:55:31 +01:00
ptitSeb ee6e3a7a96 [WRAPPER] Added a bunch of libc wrapped functions (for #2010) 2024-11-09 16:13:18 +01:00
ptitSeb 1d607cb937 [ARM64_DYNAREC] A small optim for a specific case of 0F C6 opcode 2024-11-09 16:12:26 +01:00
ptitSeb c5ced39665 [DYNAREC] Only test page protection when needed (and using a fester way) (should address the performance regression of #2009) 2024-11-09 14:02:45 +01:00
Yang Liu 7b2e77807d [RV64_DYNAREC] Added mmx infra for vector (#2011) 2024-11-09 11:58:41 +01:00
ptitSeb 7a623ef19c Improved getcontext/setcontext ([BOX32] too) 2024-11-08 18:13:42 +01:00
ptitSeb f292be40b2 Improved syscall 56 2024-11-08 18:03:03 +01:00
Yang Liu 0166330c73 [RV64_DYNAREC] Fixed some GETEX_vector usage (#2008) 2024-11-08 10:53:43 +01:00
ptitSeb 3cc9d47032 Added some weird 67 and 64/65 prefixed opcodes ([ARM64_DYNAREC] too) 2024-11-07 17:40:48 +01:00
ptitSeb 128708db2d [ELFLOADER] Better handling of symbols with COPY / GLOB_DAT (should helps #1412, but doesn't seems to help #1860, wich is strange) 2024-11-07 17:14:19 +01:00
ptitSeb 3027ee9f3e Removed a debug leftover 2024-11-07 17:13:04 +01:00
ptitSeb 51c673e62d [BOX32][WRAPPER] Added 1 more sdl2 wrapped function (Crimsonland works now) 2024-11-07 15:52:39 +01:00
ptitSeb 56bd83f6fb Added 64/65 D8..D9 opcodes 2024-11-07 15:52:10 +01:00
ptitSeb 2473bb6902 Added 64/65 69 opcode ([ARM64_DYNAREC] too) 2024-11-07 15:03:55 +01:00
ptitSeb da0e153a05 [BOX32] Improve errno handling, and added a few more libc wrapped functions 2024-11-07 13:26:55 +01:00
Jim Huang 394e81af45 [RBTREE] Unify naming and prevent unintended symbol exposure (#2005)
Red-black tree operations now consistently use the 'rbtree_' prefix, and
internal functions remain unexposed. Tested on RV64GC, resulting in a
498-byte reduction in the .text section size.
2024-11-06 21:56:34 +01:00
rajdakin 6af8d70cc1 [WRAPPED32] Added an errno-aware calling convention (#2006) 2024-11-06 21:52:34 +01:00
ptitSeb 2dea11a9e3 [TRACE] Better for 32bits wait wrapped function 2024-11-06 19:13:08 +01:00
ptitSeb cd55c12e44 Added a few wrapped function and fixed some other (for Steam) 2024-11-06 16:09:38 +01:00
ptitSeb cb2cf7c9b1 A bit more trace for emited signals 2024-11-06 16:09:14 +01:00
ptitSeb 494786be26 Fixed a small typo 2024-11-06 16:08:50 +01:00
ptitSeb 27013d6a03 [TRACE] A few more details for some speicifc CALL variant 2024-11-06 16:07:21 +01:00
ptitSeb 3ba91a6513 [CMAKE] Fixed SD865 profile, as a77.a55 is not supported in current build chain 2024-11-06 11:53:20 +01:00
ptitSeb c547090ee0 Fixed a typo 2024-11-05 15:42:14 +01:00
ptitSeb f87b9c15d3 [ARM64_DYNAREC] Fixed some issue with frintts uses 2024-11-05 14:42:09 +01:00
ptitSeb 3d76bcde2e [ARM64_DYNAREC] Fixed newly added frrintts use 2024-11-05 14:26:33 +01:00
ptitSeb 1a6f49ce45 [ARM64_DYNAREC] Reworked a bit FASTROUND 2024-11-05 14:13:01 +01:00
ptitSeb 745a7fc034 Silenced a signal message 2024-11-05 13:59:31 +01:00
ptitSeb 6158a0ad45 Disabling memory bit test when pagesize is not 4K 2024-11-05 13:55:14 +01:00
Yang Liu a51f684c41 [WRAPPER] Wrapped 3 more symbols for libc (#2000) 2024-11-05 13:10:10 +01:00
Yang Liu 681e207af5 [RV64_DYNAREC] Added more SSE opcodes for vector (#1999) 2024-11-05 09:43:30 +01:00
ptitSeb f651b7bfb0 [WRAPPER] forgot to handle libfontconfig also 2024-11-04 16:04:59 +01:00
ptitSeb 6c53e12b49 [WRAPPER] merged android naming so no more ifdef is needed 2024-11-04 15:06:44 +01:00
ptitSeb 01c9157fce [ANDROID] Try to fix libfontconfig not loading properly 2024-11-04 13:45:38 +01:00
ptitSeb 3448e94171 Improve handling of memory protection, and excution bit 2024-11-04 11:43:27 +01:00
ptitSeb 08085be360 [DYNAREC] Reverted last 2 commit, will use CancelFillblock mecanism instead 2024-11-03 20:01:56 +01:00
ptitSeb 3809866d99 [LA64_DYNAREC] This should fix Loongarch dynarec 2024-11-03 19:29:54 +01:00
ptitSeb 52a05c9f67 [DYNAREC] Make sure the emu structure is up-to-date each time LinkNext is called 2024-11-03 19:16:35 +01:00
ptitSeb ba5aa0c83b [ARM64_DYNAREC] Fixed an issue with native flags and opcode using C Helper that use flags, like rcr and rcl 2024-11-03 17:13:12 +01:00
ptitSeb 939486fa05 Forgot that file in earlier commit 2024-11-02 09:34:34 +01:00
ptitSeb c8d98f6901 [RCFIEL] Add an option to force usage of native EGL/GLESv2 library 2024-11-02 09:28:34 +01:00
ptitSeb 38cfeeb558 [WRAPPER] Small rework on wrapper return values 2024-11-02 09:20:42 +01:00
Yang Liu cf9f8d0535 [RV64_DYNAREC] Added more opcodes for vector (#1992) 2024-11-01 19:36:23 +01:00
Yang Liu 9e43737e18 [RV64_DYNAREC] Added more opcodes for vector (#1991) 2024-11-01 18:07:18 +01:00
ptitSeb 5d03ad24c3 Added a few more gtk3/gdk3 symbols (probably gtk/gdk 4.+ symbol actually) 2024-11-01 14:37:18 +01:00
Yang Liu ac6721edac [RV64_DYNAREC] Added more opcodes for vector (#1989) 2024-11-01 11:33:52 +01:00
Yang Liu 126cf27972 [RV64_DYNAREC] Added more opcodes for vector (#1987) 2024-10-31 17:38:16 +01:00
ptitSeb 0a677c7f83 Fixed a typo (for #1986) 2024-10-31 15:29:23 +01:00
ptitSeb 63e35941e2 Small (probably cosmetic) fix for CloneEmu helper function 2024-10-31 10:43:02 +01:00
ptitSeb 3ae6992641 [RCFILE] Added a profile for AlienIsolation linux version 2024-10-31 10:42:25 +01:00
ptitSeb a243532730 Added 65 6C..6F opcodes ([ARM64_DYNAREC] too) (for #1985) 2024-10-31 10:04:11 +01:00
zymayunyan ed99f5e6d2 [rebree]The name of rbtree is set error. (#1984) 2024-10-31 09:21:52 +01:00
Yang Liu 7d1bf95d93 [RV64_DYNAREC] Added more opcodes for vector (#1983) 2024-10-30 19:53:04 +01:00
Yang Liu 93cbf59e9e [Rv64_DYNAREC] Added more opcodes for vector (#1982) 2024-10-30 16:51:55 +01:00
ptitSeb e8f9796752 Fixed a small memory invalid read with my_execv 2024-10-30 16:33:14 +01:00
Yang Liu adb423d96b [RV64_DYNAREC] Added more opcodes for vector (#1981) 2024-10-30 13:10:47 +01:00
ptitSeb 74acad3628 [WRAPPER] Wrapped remaining 2 function to libbrotidec (for #1860) 2024-10-30 11:23:30 +01:00
ptitSeb 541adff4d4 Improved clone wrapped function compatibility 2024-10-30 11:12:51 +01:00
ptitSeb 39189a746b Generate a SIGILL on unimplemented opcode 2024-10-30 11:06:17 +01:00
ptitSeb f82e938ae8 [WRAPPER] Added more crypto3 and ssl3 function, and fixed some issue with hidden callback (for #1860) 2024-10-30 11:05:43 +01:00
Yang Liu 34520c0b4f [RV64_DYNAREC] Added more opcodes for vector (#1980) 2024-10-30 11:02:09 +01:00
Yang Liu 121148da72 [RV64_DYNAREC] Added more opcodes for vector (#1979) 2024-10-29 22:04:07 +01:00
Yang Liu 1e34db98a8 [RV64_DYNAREC] Added more opcodes for vector (#1978) 2024-10-29 21:01:14 +01:00
ptitSeb 9f821d6406 [WRAPPER] Reworked ssl3 and crypto3 with new wrapperhelper (for #1860) 2024-10-29 16:55:15 +01:00
rajdakin 70a6d96748 [WRAPPERHELPER] Added pragma once support, fixed a preprocessor bug, fixed the wrapperhelper Makefile (#1977) 2024-10-29 16:31:05 +01:00
ptitSeb 4a440b6f0a [ARM64_DYNAREC] Make sure neg on 16bits is correctly computed 2024-10-29 15:19:38 +01:00
ptitSeb fdfc5c4a41 [ARM64_DYNAREC] Fixed a potential issue with native flags used while some intermediary opcode doesn't support it 2024-10-29 15:19:11 +01:00
ptitSeb 6699c0ee7f [RCFILE] Update setup and install generic profile to not use native flags 2024-10-29 14:13:53 +01:00
Yang Liu 8807b1aa3c [INTERP] Fixed overflow checking for convertion opcodes (#1976) 2024-10-29 14:11:13 +01:00
ptitSeb 2aff4239cc [BOX32] Added an option to also add binfmt integration for box32 (for #1973) 2024-10-29 14:10:05 +01:00
ptitSeb d99d18759b [ARM64_DYNAREC] Also use Native Carry flags directly when possible 2024-10-29 13:09:51 +01:00
Yang Liu 68c3be3e16 [RV64_DYNAREC] Fixed 66 0F C2 CMPPD opcode for scalar and more (#1975)
* [RV64_DYNAREC] Fixed 66 0F C2 CMPPD opcode for scalar

* more minor fixes
2024-10-29 11:16:08 +01:00
Yang Liu f148b106a5 [RV64_DYNAREC] Fixed MAXSS and MAXSD for vector (#1974) 2024-10-28 23:10:17 +01:00
Yang Liu 9ffabf4c85 [RV64_DYNAREC] Added more opcodes for vector (#1972) 2024-10-28 22:34:49 +01:00
Yang Liu aebfd61539 [RV64_DYNAREC] Added more opcodes for vector (#1970) 2024-10-28 20:16:47 +01:00
Yang Liu 8dee79d380 [RV64_DYNAREC] Added more opcodes for vector (#1969) 2024-10-28 17:32:52 +01:00
Yang Liu d3c1ea5b0f [RV64_DYNAREC] Added more opcodes for vector (#1968) 2024-10-28 14:55:58 +01:00
Yang Liu 2835a2f87d [RV64_DYNAREC] Added more opcodes for vector (#1966) 2024-10-27 22:31:20 +01:00
ptitSeb 062a098ac5 [VULKAN] Fixed a typo in a vulkan extension 2024-10-27 08:44:00 +01:00
Yang Liu 5563103453 [RV64_DYNAREC] Implemented the first AVX128 opcode for scalar only (#1962) 2024-10-26 17:50:24 +02:00
Yang Liu a1d62eb92b [RV64_DYNAREC] Refined fpu_{push,pop}cache for vector (#1960) 2024-10-26 17:06:45 +02:00
ptitSeb 138a021fad [WRAPPER] Added some ssl3 and crypto3 wrapped functions (for #1860) 2024-10-25 17:25:01 +02:00
ptitSeb bdf0e95a12 [WRAPPER] Added wrapped libbrotlidec with new warpperhelper (for #1860) 2024-10-25 16:01:28 +02:00
ptitSeb 90674b825a [BOX32] Added 1 more sdl2 wrapped function (for #1957) 2024-10-25 10:48:51 +02:00
Yang Liu b3bc09f898 [RV64_DYNAREC] Added 1 more 66 0F opcode for vector (#1956) 2024-10-24 16:09:23 +02:00
ptitSeb 320459c2c6 Make BOX64_IGNOREINT3 also ignore other privilged instructions 2024-10-24 15:24:54 +02:00
Yang Liuandxctan 8d14c10b8c [RV64_DYNAREC] Optimized horizontal opcodes (#1955)
Co-authored-by: xctan <[email protected]>
2024-10-24 09:00:01 +02:00
Chi-Kuan Chiu 2c2b252dac [Box64] Fix compilation issues (#1938) (#1952)
Fixed compilation errors related to variable declarations within
switch-case statements without enclosing braces. This adjustment
ensures compatibility with older versions of compiler.

Resolves: #1938
2024-10-22 22:08:49 +02:00
ptitSeb 8efd1e3ae0 [ARM64_DYNAREC] Added AVX.F3.0F 53 opcode 2024-10-22 14:43:34 +02:00
ptitSeb e7adc6b7f9 [BOX32] Added 1 more sdl2 wrapped function 2024-10-22 09:24:06 +02:00
ptitSeb fc7d204d4b [ARM64_DYNAREC] More work around native flags handling 2024-10-20 21:47:21 +02:00
ptitSeb 2153e7098c [ARM64_DYNAREC] Fixed edgecase on MINSS/MAXSS when comparing 0.0 and -0.0 2024-10-20 14:57:31 +02:00
ptitSeb 29beabd683 [ARM64_DYNAREC] Added BOX64_DYNAREC_NATIVEFLAGS to disable the use of native flags, as there is still a bug or two in that mode (for #1947) 2024-10-20 13:21:08 +02:00
ptitSeb 80c346060f [ARM64_DYNAREC] Some small improvment to a few shift opcode, to use flagless jump when possible 2024-10-20 11:23:55 +02:00
ptitSeb 4e10cd654f Improved 0F 0D opcode ([ARM64_DYNAREC] too) (FF7RI now have sound) 2024-10-19 15:23:26 +02:00
ptitSeb a12653a25d [TRACE] Improved 32bits trace for FF 92 opocde 2024-10-19 15:22:52 +02:00
ptitSeb f683ae95c3 [BOX32][WRAPPER] Added a few more SDL2 32bits wrapped functions 2024-10-19 13:54:28 +02:00
ptitSeb 6bdeb18253 [BOX32] Fixed to a couple of wrapped libc functions 2024-10-19 12:40:33 +02:00
ptitSeb 8f1f23c991 [BOX32][TRACE] Better trace for a sscanf variant 2024-10-19 12:39:29 +02:00
ptitSeb 42345af443 [BOX32][WRAPPER] Added 32bits wrapped regex libc functions 2024-10-19 11:05:40 +02:00
ptitSeb a5797da100 [BOX32][WRAPPER] Added some more libc wrapped function, and 32bits globalsymbol infrastructure 2024-10-19 10:38:11 +02:00
ptitSeb 0821e6acc2 [BOX32][WRAPPER] Added a few symbols to libSDL2 2024-10-18 18:59:15 +02:00
ptitSeb 0fb87c7926 [WRAPPER] Added 1 missing symbol to libSDL2 2024-10-18 18:58:58 +02:00
ptitSeb b578487d01 [BOX32] A few more fixes to libX11 wrapping 2024-10-18 16:44:47 +02:00
ptitSeb cdf81eb1d7 Now x86_64 bash can be installed as box64-bash and will be automaticly used if present 2024-10-18 14:53:13 +02:00
ptitSeb 97491658c6 Fixed box32 hash table un-init crashing on regular box64 ([BOX32] and improved a bit hash selection patter) 2024-10-18 14:51:58 +02:00
ptitSeb b2b3653d67 [ARM64_DYNAREC] Fixed a regression with native flag commit (might help #1947) 2024-10-18 12:09:03 +02:00
ptitSeb de102bec5e [VULKAN] Added 2 more extensions 2024-10-18 11:38:06 +02:00
ptitSeb 3598f2855f [BOX32] A few more X11 wrapped functions and fixes 2024-10-18 10:23:08 +02:00
ptitSeb f36a479d0f [ARM64_DYNAREC][TRACE] Update LR on jumpnext on trace build so debug info in case of jump to NULL are accurate 2024-10-18 10:22:43 +02:00
ptitSeb 5363c013e6 [WRAPPER] Added gtk_marshal to gtk2 (for #1943) 2024-10-17 15:59:50 +02:00
ptitSeb b609328ac1 [WRAPPER] Reworked libcups wrapping with new wrapperhelper 2024-10-17 15:49:26 +02:00
ptitSeb 65c2b103b1 [ARM64_DYNAREC] Added directmapping of x86 flags to N, V and Z arm64 flags 2024-10-17 15:36:13 +02:00
ptitSeb 22a89ba914 Added 1 more wrapped symbol to gtk2 (for #1943) 2024-10-17 13:07:44 +02:00
ptitSeb fda9b6f75d [WRAPPER] Reworked libharfbuzz wrapping with new wrapperhelper 2024-10-17 12:57:52 +02:00
ptitSeb b29e9b706e [WRAPPER] Added alternative libname for libFLAC 2024-10-16 12:39:57 +02:00
Yang Liu bd145ad6b2 [RV64_DYNAREC] Added a few more opcodes for vector (#1941) 2024-10-15 14:47:25 +02:00
Yang Liu fc71ec9785 [RV64_DYNAREC][LA64_DYNAREC] Fixed various issues (#1940)
* [RV64_DYNAREC] Fixed more issues for vector

* more fixes and optims

* more

* more

* more

* more
2024-10-14 14:11:57 +02:00
ptitSeb cce43790d2 [NTERPRETER] Added 64 F6 opcodes (for #1932) 2024-10-13 18:57:19 +02:00
ptitSeb 1e31e1fff8 [BOX32] Fixed dlvsym for RTLD_NEXT, like dlsym 2024-10-13 18:50:44 +02:00
ptitSeb af2a0c9747 [BOX32] Some more 32bits wrapped symbols 2024-10-13 18:39:13 +02:00
ptitSeb d30488da87 [BOX32] Added some more 32bits wrapped function to libc 2024-10-13 17:44:14 +02:00
ptitSeb 59ba2fc7ab [BOX32][WRAPPER] Hacked some support for libGLX_nvidia.so.0 2024-10-13 17:43:51 +02:00
ptitSeb 1936052e79 [WRAPPER] Hacked some support for libGLX_nvidia.so.0 2024-10-13 17:43:27 +02:00
ptitSeb 103ec5d72a [BOX32] Added some posix_file_action wrapped function, and fixed posix_spawn/exec function argument handling 2024-10-13 14:46:21 +02:00
ptitSeb 9139ec3e5c [WRAPPER] Reworked libgnutls wrapping with new wrapperhelper 2024-10-13 13:16:09 +02:00
Yang Liu 7430463b33 [CORE] Refactored %pid trace file handling (#1933) 2024-10-13 13:08:18 +02:00
ptitSeb 6f2d067f3a [INTERPRETER] Added 64/65 85 opcode ([ARM64_DYNAREC] too) (for #1932) 2024-10-13 11:35:20 +02:00
ptitSeb d31b9c9caa [BOX32] Allow internal memory to be in 32bits space if needed 2024-10-13 11:20:25 +02:00
ptitSeb 2670d37542 [RCFILE] Added a profile 2024-10-13 11:19:37 +02:00
ptitSeb 617fd69bcc [BOX32] Reworked alignment for 32bits stacks 2024-10-13 11:19:19 +02:00
ptitSeb 5fcd9d45a3 [BOX32] Added a few 32bits wrapped function libSDL2 2024-10-13 10:01:06 +02:00
ptitSeb b6cd19b78b [BOX32] More work on libX11 and friends, using more shadow structure like Screen and Visual (help wine, probably other too) 2024-10-12 18:40:31 +02:00
Yang Liu 6a3a19da68 [RV64_DYNAREC] Fixed more issues for vector (#1928)
* [RV64_DYNAREC] Fixed emitter for xtheadvector

* MOVSD can be unaligned

* fixed unaligned issues
2024-10-12 12:46:08 +02:00
ptitSeb efd103004c [BOX32] Improved X11 event handling 2024-10-12 10:45:21 +02:00
Yang Liu 18e033cdd8 [RV64_DYNAREC] Fixed 66 0F 38 17 PTEST opcode for vector (#1927) 2024-10-11 21:27:51 +02:00
Yang Liu 2a4ecc1d28 [RV64_DYNAREC] Wrapped icuuc75 (#1926) 2024-10-11 21:27:17 +02:00
Yang Liu c0c91678ba [RV64_DYNAREC] Fixed an issue in CVTTSD2SI for vector (#1925) 2024-10-11 18:34:40 +02:00
ptitSeb 7a531ed272 [BOX32] Fixed some issues with X11 and XRandR 32bits wrapping 2024-10-11 13:25:28 +02:00
ptitSeb 93e3fcb386 [BOX32][TRACE] Better for XRRSetScreenSize 2024-10-11 13:20:14 +02:00
Yang Liu 143fc90a4c [RV64_DYNAREC] Split 660f.c to speedup compilation a bit (#1924) 2024-10-11 12:25:13 +02:00
ptitSeb f65feaf9da [BOX32] Added 2 more wrapped function to libc 2024-10-11 11:03:57 +02:00
ptitSeb a17b0effa1 [BOX32] Added 2 more 32bits wrapped functions 2024-10-11 10:44:07 +02:00
ptitSeb b0d5c7a1a5 [BOX32] Added 1 more 32bits wrapped function 2024-10-11 10:26:47 +02:00
Yang Liu 9c4a407fdc [RV64_DYNAREC] Added more opcodes for vector (#1923)
* [RV64_DYNAREC] Added more opcodes for vector

* fix
2024-10-11 09:36:59 +02:00
Yang Liu 67b2151e3c [RV64_DYNAREC] Added more opcode for vector and some fixes too (#1920) 2024-10-10 20:58:45 +02:00
ptitSeb b8024469da [ARM64_DYNAREC] Added a small optim for CALL 0 / POP reg type of sequence 2024-10-10 20:55:24 +02:00
ptitSeb 7f5c826bb1 [BOX32][TRACE] Fixed trace for memcmp, strncasecmp and strncmp 2024-10-10 20:54:40 +02:00
ptitSeb acad3f3963 [BOX32] Actually fixed dlsym on RTLD_NEXT 32bits call 2024-10-10 20:32:29 +02:00
ptitSeb 1f6ce24eaa [BOX32] Added and fixed some 32bits functions for libX11 and friends 2024-10-10 19:20:29 +02:00
ptitSeb 4a82f21cc3 [BOX32] Fixed 32bits dlsym on RTLD_NEXT not working 2024-10-10 19:20:29 +02:00
Yang Liu 0cf707599d [RV64_DYNAREC] Added more opcodes for vector (#1919) 2024-10-10 18:40:02 +02:00
ptitSeb e2e6bdc4cb [BOX32][WRAPPER] Added 32bits wrapped libXss (with new wrapperhelper) 2024-10-10 17:23:49 +02:00
ptitSeb 8136186554 [WRAPPER] Reworked libXss with new wrapperhelper 2024-10-10 17:11:00 +02:00
Yang Liu 9b733041af [RV64_DYNAREC] Added more opcodes for vector (#1918) 2024-10-10 17:08:50 +02:00
ptitSeb 9e01876747 [BOX32] Improved pthread_mutex handling 2024-10-10 15:57:28 +02:00
ptitSeb ee909b8c08 [BOX32] More 32bits SDL-1.2 wrapped functions 2024-10-10 15:57:08 +02:00
ptitSeb fdf1982982 [BOX32] Fixed getifaddrs 32bits wrapped function 2024-10-10 15:53:32 +02:00
Yang Liu 88ccd7f537 [RV64_DYNAREC] Added 1 more opcode for vector, some fixes too (#1917) 2024-10-10 15:30:41 +02:00
ptitSeb c6cd9ceb75 Fixed some command line handling regression 2024-10-10 15:11:52 +02:00
ptitSeb ce735357d6 [BOX32] More 32bits wrapped functions 2024-10-10 14:57:26 +02:00
Yang Liu 887dee83eb [RV64_DYNAREC] Added more boilerplate for vector (#1916) 2024-10-10 12:15:48 +02:00
ptitSeb fd73a2bc8b [BOX32] Morewrapped SDL2 function, and improved handling of SDL_PixelFormat 2024-10-10 09:46:32 +02:00
ptitSeb 21b5f90a33 Small changed to command line argument handling 2024-10-10 08:37:59 +02:00
ptitSeb d1c5cd7b0a [BOX32][TRACE] Small improvment to SDL_RWFromFile trace 2024-10-10 08:35:58 +02:00
ptitSeb 656a36061a [BOX32] More X11 wrapping fixes 2024-10-09 21:03:41 +02:00
ptitSeb 05384f581f [BOX32] Improved again, X11 and XImage handling 2024-10-09 15:56:07 +02:00
ptitSeb 84f3c104b2 [BOX32] Improved handlong of XImage 2024-10-09 11:48:22 +02:00
ptitSeb 761f7e40de [BOX32] Fixed 32bits libc syscall 240 2024-10-09 10:23:27 +02:00
Yang Liu b760c21414 [BOX32] Fixed fcntl flock macros definitions (#1915) 2024-10-09 10:01:26 +02:00
ptitSeb bb651298c4 [BOX32] Added better handling of fcntl (should help Wine when futex_waitv syscall is not available) 2024-10-08 20:48:13 +02:00
ptitSeb 8850a11072 [BOX32] Added some more libSDL2 wrapped function (now linux limbo works, with gamepad) 2024-10-08 20:29:40 +02:00
ptitSeb 499338e80d Fixed non-Box32 builds 2024-10-08 20:06:00 +02:00
ptitSeb c12f8fa254 [BOX32] Fixed some X11 function so wine launch (and added BOX64_X11SYNC to help debug X11 programs) 2024-10-08 19:44:20 +02:00
ptitSeb 7ae36b8667 [BOX32] More 32bits wrapped functions 2024-10-08 17:38:01 +02:00
ptitSeb 591e2db712 [BOX32] Refactored X11 wrapping, and add a few more functions 2024-10-08 16:34:20 +02:00
Yang Liu 8414563ad0 [RV64_DYNAREC] Added more opcodes and small optimizations (#1914)
* [RV64_DYNAREC] Added more opcodes and small optimizations

* more

* only applies to and32c
2024-10-08 13:58:32 +02:00
ptitSeb 85fc57faa3 Improve debugging trace of rb_tree 2024-10-08 13:11:42 +02:00
ptitSeb c8e10a004b [BOX32][DYNAREC] Allocate Dynarec memory in higher prereserve regions 2024-10-08 12:56:45 +02:00
ptitSeb e1fac2404c Removed wine prereserve hack on munmap now that prereserve is better handled 2024-10-08 12:21:19 +02:00
Yang Liu 65adf2a860 [RV64_DYNAREC] Fixed CVTSS2SD and CVTSD2SS opcodes (#1913) 2024-10-08 10:53:18 +02:00
ptitSeb dea6906ae9 [WRAPPER] Reworked libresolv with new wrapper helper ([STATICBUILD] fixed potential issue with static build) 2024-10-08 10:47:44 +02:00
ptitSeb 22ccae3301 Small adjustment in 32bits custom memory hinter 2024-10-08 10:40:09 +02:00
ptitSeb 58d58b0af7 [BOX32] More adjustments to x86 structures packing & alignment (or not) 2024-10-08 09:59:44 +02:00
ptitSeb ce5daaa835 Small change in custom Aligned Memory Allocator 2024-10-07 22:56:47 +02:00
ptitSeb 8fe0681681 Some cosmetic changes and more macro, to ease future testings on custom malloc 2024-10-07 18:39:35 +02:00
ptitSeb 3987e644a8 Added 66 6A opcode ([ARM64_DYNAREC] too) (for #1911) 2024-10-07 17:26:40 +02:00
ptitSeb f073415510 [BOX32] More work on 32bits wrapped functions 2024-10-07 17:17:55 +02:00
Yang Liu 4c69bcd97a [DYNAREC] Optimized CALL/RET RAS for out of dynablock jumps (#1909) 2024-10-07 16:57:47 +02:00
ptitSeb 05aac0879e [BOX32][WRAPPER] Reworked 32bits libGL with new wrapperhelper 2024-10-07 13:32:45 +02:00
ptitSeb cb5dafe8db [BOX32][WRAPPER] Reworked 32bits libasound with new wrapperhelper 2024-10-07 11:14:43 +02:00
ptitSeb 82c7d45c4b [BOX32] Added a couple of 32bits function to libc 2024-10-07 10:45:31 +02:00
ptitSeb f81677278f Reworked mmap allocator and wine prereserve handling ([BOX32] fix handling of wine prereserve) 2024-10-07 09:25:04 +02:00
ptitSeb 2ef6011c7a [ARM64_DYNAREC] Added 64 88 opcode 2024-10-07 08:53:15 +02:00
ptitSeb 6e0b5358fb [BOX32][WRAPPING] Added 32bits wrapped libXi (with new wrapperhelper) 2024-10-06 16:44:33 +02:00
ptitSeb e783e3c794 [BOX32] Added a few more 32bits libc symbols 2024-10-06 15:19:20 +02:00
ptitSeb 8965d9bd70 [BOX32][WRAPPER] Added 32bits libuuid (with new wrapperhelper) 2024-10-06 15:16:57 +02:00
ptitSeb 37fe9bad6d [WRAPPER] Reworked wrapped libXi with new wrapperhelper 2024-10-06 15:09:18 +02:00
ptitSeb a4daf4c228 [BOX32][WRAPPER] Added 32bits wrapped libXcomposite (with new wrapperhelper) 2024-10-06 14:48:10 +02:00
ptitSeb ae080c3ad3 [BOX32] Forgot a few more x86 structure to properly align 2024-10-06 14:31:51 +02:00
ptitSeb ad0c08c2de [BOX32] Proper alignment for x86 structures 2024-10-06 14:27:19 +02:00
ptitSeb 7b93791c3f [BOX32] Addes 3 more x86 libs for convenience 2024-10-06 14:03:30 +02:00
Yang Liu 172df2cd0c [DYNAREC] Tweaking indirect jumps for CALL/RET to use the return address stack (#1907) 2024-10-06 12:19:55 +02:00
ptitSeb b395cd7ccc [BOX32] More work on various wrapper, and some bug fixes 2024-10-06 12:14:53 +02:00
ptitSeb 8ec6b15dc2 [BOX32] More work on 32bits X11 wrapping (not 12 Labor of Hercules 6 works from Steam, but not Steam itself) 2024-10-05 18:42:51 +02:00
ptitSeb 2a2f82a745 [BOX32] Added many more 32bits wrapped function (some using wrapperhelper) 2024-10-05 16:36:31 +02:00
ptitSeb 13a7801421 [BOX32][WRAPPER] Added 32bits libXinerama, with new wrapperhelper 2024-10-05 14:30:29 +02:00
ptitSeb 1a5cd1c1ff [WRAPPER] Reworked libXinerama with new wrapperhelper 2024-10-05 14:23:53 +02:00
ptitSeb 224974f218 [WRAPPERHELPER] Removed double line added by mystake 2024-10-05 14:22:59 +02:00
ptitSeb b96556f80f [BOX32][WRAPPER] Reworked 32bits libX11, with new wrapperhelper 2024-10-05 14:17:48 +02:00
ptitSeb c29be5b945 [BOX32][WRAPEPR] Reworked 32bits libfontconfig with new wrapperhelper 2024-10-05 09:54:44 +02:00
ptitSeb 21b60db107 [BOX32][WRAPPER] Added more 32bits wrapped function to libfreetype 2024-10-05 09:38:01 +02:00
ptitSeb baa3f573ae [BOX32] Added some more wrapped function and a profile (PixelJunk Shooter linux version now Works) 2024-10-04 20:57:24 +02:00
Yang Liu 0243e93e97 [RV64] Allowed disabling more extensions (#1904) 2024-10-04 20:13:25 +02:00
ptitSeb 778bbc6d08 [BOX32][WRAPPER] Reworked 32bits libXext with new wrapperhelper 2024-10-04 18:22:43 +02:00
ptitSeb 6ae502f181 [BOX32] Initalized libX11 if used without loading (becauseit's loaded indirectly with SDL2 for example) 2024-10-04 18:18:18 +02:00
ptitSeb 088720db22 [BOX32][WRAPPER] Added wraped mostly empty 32bits libXext 2024-10-04 17:37:07 +02:00
ptitSeb 3d6ecc064f [WRAPEPR] Reworked libXext wrapping with new wrapperhelper 2024-10-04 16:56:37 +02:00
ptitSeb 333bf19c00 [ARM64_DYNAREC] Worked on CF IRET opcode 2024-10-04 16:19:24 +02:00
ptitSeb 25599b91b2 [INTERPRETER] Worked on CF IRET opcode 2024-10-04 16:19:03 +02:00
ptitSeb 18305a1994 [BOX32][WRAPPER] Fixed 32bits mktime 2024-10-04 15:52:34 +02:00
ptitSeb e6f56bf5fa Fixed x86_64 build 2024-10-04 14:24:02 +02:00
ptitSeb 681c6f4e5e [TRACE] Btter trace for ioctl 2024-10-04 13:12:37 +02:00
ptitSeb 11f1c3c4ff Return the correct errno when mmap can't allocated hinted memory address 2024-10-04 13:04:28 +02:00
ptitSeb 9f4eb36c99 [BOX32][WRAPPER] More wrapped function to libc, and many fixes some existing ones 2024-10-04 12:28:11 +02:00
Yang Liu cbbafafb46 [RV64_DYNAREC] Added more opcodes for xtheadvector (#1899) 2024-10-03 19:38:26 +02:00
ptitSeb 9e853e487d [BOX32] Added more 32bits wrapped function and reworked 32bits memory allocator 2024-10-03 19:36:42 +02:00
ptitSeb 0e91ad3ed3 [BOX32] Fixed scanf type function when grabing long/ptr type of data 2024-10-03 13:51:56 +02:00
ptitSeb c5e894aab2 [BOX32] More check for low alignment in memalign wrapped functions 2024-10-03 13:50:38 +02:00
rajdakin 49aaeb3080 [WRAPPER] Fixed RV64 isSimpleWrappers (#1898) 2024-10-03 12:49:18 +02:00
Yang Liu 1c7ac8c761 [RV64_DYNAREC] Added more opcodes for xtheadvector and fixed more issues (#1897)
* [RV64_DYNAREC] Added 1 more opcode for xtheadvector

* Disabled more opcodes does not apply to xtheadvector

* Added 1 more opcode

* Added 1 more opcode

* fix
2024-10-03 12:36:04 +02:00
ptitSeb e2492a1426 [BOX32][WRAPPER] Added full wrapped support for 32bits libudev0 and libudev1 2024-10-03 12:26:38 +02:00
ptitSeb f750391c2e [BOX32] Added rolling log print on Stack corrupted call 2024-10-03 12:26:11 +02:00
ptitSeb 95d65a02bc [TRACE] Fixed StopEmu on trace build when trace is not enabled 2024-10-03 12:25:17 +02:00
ptitSeb 2685037c82 [WRAPPER] Improved libudev1 wrapped logf function 2024-10-03 12:24:34 +02:00
ptitSeb 61c46994cd [WRAPPER] Reworked libudev1 wrapping with new wrapperhelper 2024-10-03 11:51:17 +02:00
ptitSeb 8b8e6501bc [BOX32][WRAPPER] Added a few more libX11 32bits wrapped functions 2024-10-03 11:36:36 +02:00
ptitSeb c4184ef733 [BOX32] Added workaround for posix_memalign when used with align of 4 2024-10-03 11:36:12 +02:00
ptitSeb 6a5049b22c [BOX32][TRACE] Some more improved trace 2024-10-03 11:35:41 +02:00
Yang Liu 6cbcfc7ab8 [DYNAREC] Added a new missing mode for fallback opcodes (#1896) 2024-10-02 20:44:04 +02:00
rajdakin 564d06e84c [WRAPPERHELPER] Forgot to add the Makefile (#1895)
* [WRAPPERHELPER] Forgot to add the Makefile

* [WRAPPERHELPER] Also sped up the build
2024-10-02 20:42:45 +02:00
Yang Liu 8398799e1c [CI] Added xtheadvector testing (#1894) 2024-10-02 17:50:47 +02:00
Yang Liu c43d34d0cf [RV64_DYNAREC] Added preliminary xtheadvector support (#1892)
* [RV64_DYNAREC] Added preliminary xtheadvector support

* [RV64_DYNAREC] Fixed more unaligned issue
2024-10-02 09:53:29 +02:00
ptitSeb a188f4ebfe [BOX32][WRAPPER] Added a bunch of wrapped 32bits functions, and fixed a few existing ones (Now Witcher 2 Linux boot and can enter tutorial, before crashing) 2024-09-30 21:06:56 +02:00
ptitSeb e59063a13c [BOX32] Added 2 more 32bits syscalls 2024-09-30 18:02:15 +02:00
ptitSeb 2f95534bd0 [BOX32] Set default FS to 0 for 32bits apps 2024-09-30 18:01:51 +02:00
ptitSeb 2b0c8d45fa [BOX32][WRAPPER] Added 32bits wrapping for SDL2_image 2024-09-30 17:41:47 +02:00
ptitSeb c88cf6359e [BOX32] Keep low memory free by default 2024-09-30 17:41:08 +02:00
ptitSeb 62405c79c3 [DYNAREC] Start with dynarec instead of interpreter 2024-09-30 17:40:40 +02:00
ptitSeb 28dedd66b3 [BOX32][WRAPPER] Added a few more wrapped functions to libGL, libasound and libX11 2024-09-30 16:35:11 +02:00
ptitSeb f26146bc23 [BOX32][WRAPPER] nl_langinfo signature needs t as return type 2024-09-30 15:40:07 +02:00
ptitSeb 2a0489a21c [BOX32] Handling of BOX64_MAXCPU for 32bits apps 2024-09-30 15:37:53 +02:00
ptitSeb 0980c4438a [BOX32][WRAPPER] More work on SDL2 Wrapping(but TheStanleyParable still don't have mouse input working) 2024-09-30 15:37:11 +02:00
ptitSeb f7c93b68d8 [BOX32] Fixed main Elf init not always called 2024-09-30 14:00:33 +02:00
ptitSeb f7e769f8c4 [BOX32] Enable futex robust_list hack for all 32bits software for now 2024-09-30 13:59:30 +02:00
ptitSeb 7f1ce6ebfd [BOX32][WRAPPER] Manualy changed wctype_t to h in libc wrapping 2024-09-30 12:59:57 +02:00
rajdakin 4715ef2633 [WRAPPERHELPER] Added box32 and line number support in the wrapperhelper (#1890) 2024-09-30 12:31:45 +02:00
rajdakin 703d19b256 Various box32 wrapped libs and script fixes (#1889)
* [WRAPPED32] Fixed the rebuild_wrappers_32 script, fixed some libc signatures

* [WRAPPED32] Added back xdr functions

* [WRAPPED32] Forgot to regenerate wrappers
2024-09-30 12:26:45 +02:00
ptitSeb f7d7fbb9b0 Revert a change ffrom previous build and pushed missing BOX32 generated files too 2024-09-29 22:30:40 +02:00
Pablo Labs a6baf1f370 [ANDROID][BOX32] Fix __libc_init, Fix Some Warnings (#1887)
* [ANDROID][BOX32] Fix __libc_init, Fix Some Warnings

* Fix More Warnings

* Revert fillALProcWrapper() change
2024-09-29 22:21:40 +02:00
ptitSeb 874238f61e [BOX32][WRAPPER] Added more SDL2 and freetype function, and fixed missing fonts in many games ([BOX64] also fixed some SDL2 signature on RWops) 2024-09-29 21:10:54 +02:00
Yang Liu 9968963b97 [RV64_DYNAREC] Eliminate redundant vsetvli by tracking its usage (#1886) 2024-09-29 15:15:20 +02:00
ptitSeb 5b68e46bb7 [BOX32] Added 3 more event type to SDL2 event conversion 2024-09-29 11:34:32 +02:00
Yang Liu 9a83521ad6 [RV64_DYNAREC] Minor optimization on vector_vsetvli (#1885) 2024-09-29 10:39:28 +02:00
Yang Liu 2a7eabfb1c [RV64_DYNAREC] Refined RISC-V vector emitter (#1884) 2024-09-29 10:38:49 +02:00
Pablo Labs b4a0ae20c9 [ANDROID][BOX32] Fix Android Build, and add correct libc, libm, libdl library names on library_list_32.h (#1883)
* [ANDROID][BOX32] Fix Android Build, and add correct libc, libm, libdl library names on library_list_32.h

* Fix Various Warnings
2024-09-29 00:45:20 +02:00
ptitSeb 87493a9bc9 [BOX32] Added 1event type for SDL2_Event conversions 2024-09-28 16:09:14 +02:00
ptitSeb 0f9dac511c [BOX32][WRAPPER] Added some more 32bits libc functions 2024-09-28 15:58:29 +02:00
ptitSeb 11724fd2ad [BOX32][WRAPPER] Added 32bits wrapped/hacked libtcmallocminimal 2024-09-28 15:19:08 +02:00
ptitSeb c0955d33de [BOX32][WRAPPER] Added some minimum 32bits wrpping for fontconfig, and some fixes for iconv wrapped function signature 2024-09-28 15:13:13 +02:00
ptitSeb bc5e686fde [WRAPPER] Reworked libfontconfig with new wrapperhelper 2024-09-28 13:51:22 +02:00
ptitSeb 541489da4d [BOX32][WRAPPER] Some fixes to libexpat 32bits wrapping and more other 32bits functions 2024-09-28 13:48:08 +02:00
ptitSeb 79200d4df6 [BOX32] Fixed wrapping for glShaderSourceARB 2024-09-28 12:32:01 +02:00
ptitSeb 578bae3c37 [BOX32][WRAPPER] Added some more 32bits wrapped function, and fixed one from SDL2 2024-09-28 12:27:00 +02:00
ptitSeb 37490d1a44 [BOX32] Added 2 more 32bits syscalls 2024-09-28 11:59:12 +02:00
ptitSeb 3919bb2e7d [BOX32][WRAPPER] Added 32bits wrapped libexpat and another batch of wrapped function for 32bits libfreetype and SDL2 2024-09-28 11:17:26 +02:00
ptitSeb 93e8434a87 [WRAPPER] Reworked wrapping of libexpat with new wrapperhelper 2024-09-28 10:20:21 +02:00
ptitSeb 97a1983c59 [BOX32][WRAPPER] Added a bunch of 32bits functions to SDL2 and libc 2024-09-28 10:15:55 +02:00
Yang Liu 42e60bc7c5 [BOX32][WRAPPER] Wrapped more SDL2 functions (#1881) 2024-09-27 19:00:08 +02:00
ptitSeb 93dc8fce10 [BOX32][TRACE] Better trace for recv 2024-09-27 17:27:17 +02:00
ptitSeb 34d4cde7c4 [BOX32][WRAPPER] Added 2 more 32bits wrapped function to freetype 2024-09-27 11:11:58 +02:00
xctan 66788af44d [RV64_DYNAREC] Refined RISC-V vector disassembler (#1880)
* [RV64_DYNAREC] Refined RISC-V vector disassembler

* [RV64_DYNAREC] Formated generated code
2024-09-27 09:03:24 +02:00
Yang Liu 1a8df98cf2 [ARM64_DYNAREC] Small optim on 0F C7 /1 inst name (#1878) 2024-09-26 19:46:26 +02:00
Yang Liu 0fb0ac7994 [LA64_DYNAREC] Added unaligned support to CMPXCHG8B (#1877) 2024-09-26 19:45:40 +02:00
ptitSeb 24f278c961 [BOX32][WRAPPER] Added some more 32bits wrapped functions 2024-09-26 15:21:52 +02:00
ptitSeb d45001e4c9 [BOX32][WRAPPER] Added 32bits empty wrapped libXxf86vm 2024-09-26 13:29:35 +02:00
ptitSeb 95a0e669a2 [WRAPPER] Reworked wrapped libXxf86vm with new wrapperhelper 2024-09-26 13:29:08 +02:00
ptitSeb b80e4c552a [BOX32] Minor changes to 32bits freetype wrapping 2024-09-26 13:20:07 +02:00
Yang Liu 933dc0f5c8 [LA64_DYNAREC] Fixed emit_add16 LBT implementation (#1875) 2024-09-26 10:04:20 +02:00
Yang Liu 6a3904fc48 [BOX32][WRAPPER] Refined SDL2 display mode wrapping (#1874)
* [BOX32][WRAPPER] Refined SDL2 display mode wrapping

* review
2024-09-26 09:24:32 +02:00
Yang Liu b045dbde0f [BOX32][WRAPPER] Added preliminary wrapper for SDL2 (postal1 works) (#1872)
* [BOX32][WRAPPER] Added preliminary wrapper for SDL2 (postal1 works)

* Handle more events
2024-09-26 08:17:15 +02:00
ptitSeb b85ebc73c9 [BOX32][WRAPPER] Improved 32bits wrapping for libfreetype (still not 100% ok) 2024-09-25 19:46:55 +02:00
ptitSeb 7d76fc4945 [WRAPPER] Added 1 GLX extension ([BOX32] too) 2024-09-25 15:46:58 +02:00
ptitSeb 90332ecf6e [BOX32] Removed a warning 2024-09-25 14:51:56 +02:00
ptitSeb 0c4c89f3ca [BOX32] Fixed some locale conversion (fixed FTL.x86 not going ingame) 2024-09-25 14:47:25 +02:00
Yang Liu 62177d2ca3 [BOX32][WRAPPER] Fixed null checking in my32_SDL_SetVideoMode (#1868) 2024-09-25 13:07:26 +02:00
ptitSeb 144830bc05 [BOX32][WRAPPER] Added some more 32bits wrapped function, and fixed a few more 2024-09-25 12:29:46 +02:00
Yang Liu 24a5917b44 [LA64_DYNAREC][BOX32] Improved some 66 prefix opcodes (#1867) 2024-09-25 09:06:22 +02:00
ptitSeb b38c5f095c [BOX32][WRAPPING] More fixes with intermediate structure conversions 2024-09-24 22:37:11 +02:00
ptitSeb d7ad7f0c70 [BOX32][WRAPPING] Fixed some issue with intermediate structure conversions 2024-09-24 22:26:44 +02:00
Yang Liu dc391439ba [RV64_DYNAREC][BOX32] Added more opcodes (#1866)
* [RV64_DYNAREC][BOX32] Added more opcodes

* more
2024-09-24 21:58:47 +02:00
Yang Liu e44c43deeb [RV64_DYNAREC][BOX32] Improved some 66 prefix opcodes (#1865) 2024-09-24 21:10:50 +02:00
Yang Liu c795faf167 [LA64_DYNAREC][BOX32] Added more opcodes (#1864) 2024-09-24 21:10:10 +02:00
ptitSeb dad0913dcb [BOX32][WRAPPER] Added some more 32bits wrapped function, and fixed a few x11/glX ones too 2024-09-24 21:04:58 +02:00
ptitSeb e5db9aa874 [ARM64_DYNAREC] Fixed some issue with a few 16bits opcodes on 64bits operations 2024-09-24 21:04:57 +02:00
Yang Liu 2d0b60898c [RV64_DYNAREC] Added more opcodes for vector (#1863)
* [RV64_DYNAREC] Added more opcodes for vector

* [RV64_DYNAREC] Added more opcodes for vector

* [RV64_DYNAREC] Added more opcodes
2024-09-24 17:03:11 +02:00
ptitSeb c25fc8cc24 [BOX32][WRAPPER] Added a few 32bits function to libxrandr 2024-09-24 16:50:18 +02:00
ptitSeb bddeac4b45 [BOX32] Silently enlarge thread stack size that are too small for platform 2024-09-24 16:49:52 +02:00
ptitSeb 1aa42a6779 [BOX32][TRACE] Fixed semop traces 2024-09-24 16:49:19 +02:00
ptitSeb 73b3aec3ed [ARM64_DYNAREC] Fixed reset of rex on 67 prefixed opcodes 2024-09-24 15:17:56 +02:00
ptitSeb 9568cbac0a [ARM64_DYNAREC] Added F1 opcode 2024-09-24 14:49:45 +02:00
ptitSeb a60c742fa4 [ARM64_DYNAREC] Added CA/CB ocpodes 2024-09-24 14:46:34 +02:00
ptitSeb 6313a31668 [INTEPRETER] Added a check on CS for CA/CB opecodes 2024-09-24 14:46:17 +02:00
ptitSeb 15a4be2db1 [ARM64_DYNAREC] Added 66 0F BF opcode (and cosmetic fix on interpreter) 2024-09-24 14:31:59 +02:00
ptitSeb 0c71d8d4e6 [ARM64_DYNAREC] Added 64 A8 opcode 2024-09-24 14:26:02 +02:00
ptitSeb 4409374c47 [ARM64_DYNAREC] Added 67 A9 opcode, and fixed 67 opcode with ignored REX prefix 2024-09-24 14:20:22 +02:00
ptitSeb 4299e0a3a3 [BOX32][WRAPPER] Added more 32bits wrapped functions 2024-09-24 14:13:45 +02:00
Yang Liu c4af15c2e2 [RV64_DYNAREC] Allowed disabling V extension (#1862) 2024-09-24 11:44:16 +02:00
Yang Liu eacde4008e [RV64_DYNAREC] Fixed 66 0F 38 2B PACKUSDW opcode (#1861) 2024-09-24 11:43:21 +02:00
ptitSeb 358e24ace5 [BOX32][WRAPPER] Added 32bits empty libfreetype 2024-09-24 10:18:10 +02:00
ptitSeb 7317472b5f [BOX32][WRAPPER] More 32bits wrapped functions, and a few fixes on threads handling 2024-09-23 19:45:13 +02:00
ptitSeb 9271684e5a [BOX32][WRAPPER] One more 32bits wrapped libX11 function 2024-09-23 15:12:24 +02:00
ptitSeb 929d462d05 [BOX32] Addeda few more 32bits wrapped x11 functions 2024-09-23 14:23:02 +02:00
ptitSeb e0ce06483c [NON4K][ELFLOADER] more Elfloader work for non-4k pagesize OS ([BOX32] too) 2024-09-23 14:13:28 +02:00
ptitSeb 95e78088d6 [NON4K] Fixed some typos ([BOX32] too) 2024-09-23 14:01:45 +02:00
ptitSeb dd72a4542e [BOX32][NON4K] Try to fix elfloader when elf wants to load at an address not-compatible with pagesize 2024-09-23 13:54:48 +02:00
ptitSeb 5fe0a68b46 [NON4K] Try to fix elfloader when elf wants to load at an address not-compatible with pagesize 2024-09-23 13:52:11 +02:00
ptitSeb 61486749f8 [BOX32][WRAPPER] More 32bits wrapped function to libX11 2024-09-23 13:42:09 +02:00
Yang Liu 31f574ed36 [RV64_DYNAREC] Added more opcodes for vector (#1857) 2024-09-23 12:42:59 +02:00
ptitSeb d9ff07b605 [BOX32] Improved semaphore wrapping 2024-09-23 11:39:07 +02:00
ptitSeb dbdb3d6af6 [WRAPPER] Reworked wrapped libwayland-client with new wrapperhelper 2024-09-23 10:39:30 +02:00
ptitSeb 4c0a213840 [BOX32][WRAPPER] Added 32bits wrapped openal 2024-09-23 10:19:42 +02:00
ptitSeb aa65bad62b [WRAPPER] Reworked wrapped libopenal with new wrapperhelper 2024-09-23 10:10:14 +02:00
ptitSeb 60c469ed06 [BOX32][WRAPPER] Added a couple of 32bits libx11 functions 2024-09-22 20:34:25 +02:00
ptitSeb cf87ae2e71 [WRAPPING] Fixed some (very) old issue with SDL2 RWops wrapping 2024-09-22 20:20:54 +02:00
Yang Liu ea443cfa21 [RV64_DYNAREC] Added more opcodes for vector (#1855) 2024-09-22 19:22:36 +02:00
ptitSeb 5e49e3cfaa [BOX32][WRAPPER] Added some more libX11 and libc 32bits wrapped function, and empty 32bits wrapped libXfixes, libXcursor, libXrender and libXrandr 2024-09-22 17:11:07 +02:00
ptitSeb 8574c575f5 [WRAPPER] Reworked wrapping of libXcurse, libXfixes, libXrender and libXrandr with new wrapperhelper 2024-09-22 17:10:03 +02:00
ptitSeb d2aecc0412 [BOX32][wrapper] Added some basic 32bits X11 wrapping, fixed 32bits sem_XXX wrapping, and more 32bits wrapped functions 2024-09-22 16:24:48 +02:00
Yang Liu 710d537f39 [RV64_DYNAREC] Added more opcodes for vector (#1853) 2024-09-22 15:36:25 +02:00
Yang Liu 9e44c65391 [RV64_DYNAREC] Added more opcodes for vector (#1852) 2024-09-22 11:24:08 +02:00
Yang Liu c36491cfb6 [RV64_DYNAREC] Added more opcode for vector and reinitialize sew after external call (#1851) 2024-09-22 08:36:18 +02:00
ptitSeb c2be0268b1 [BOX32][ELFLOADER] Fixed PROTECTED symbol that were not loaded correctly 2024-09-21 15:52:02 +02:00
ptitSeb 4cda6dbcfb [ELFLOADER] Fixed PROTECTED symbol that were not loaded correctly 2024-09-21 15:51:51 +02:00
ptitSeb e34afea346 [BOX32] Added some more 32bits wrapped functions 2024-09-21 14:55:42 +02:00
ptitSeb 1ea71c89a8 [BOX32] Fixed wrapping of __ctype_b, __ctype_tolower and __ctype_toupper 2024-09-21 14:22:21 +02:00
ptitSeb 856ffea797 [BOX32][TRACE] Better trace for a few more 32bits string functions 2024-09-21 14:21:49 +02:00
ptitSeb 9efae57162 [BOX32] Added 32bits wrapped libGLU 2024-09-21 12:35:26 +02:00
rajdakin 09d4cb7b38 [WRAPPERHELPER] Fixed wrapperhelper (#1850) 2024-09-21 12:29:28 +02:00
ptitSeb fb4f580922 [BOX32] Added some more 32bits wrapped functions (Chicken Invaders 3 works, but need SDL12COMPAT_OPENGL_SCALING=0) 2024-09-21 12:20:26 +02:00
Yang Liu 15842f3464 [RV64_DYNAREC] Added more opcodes for vector (#1848) 2024-09-20 18:42:04 +02:00
rajdakin e18846fac5 [WRAPPERHELPER] Fixed some bugs, added partial multiarch support (#1847) 2024-09-20 17:06:25 +02:00
Yang Liu 4aeb8ea1b0 [LA64_DYNAREC] Fixed a typo in GETGB (#1846) 2024-09-20 16:04:00 +02:00
ptitSeb 6a415b54d0 [WRAPPER] Reworked libX11 with new wrapperhelper 2024-09-20 15:28:13 +02:00
rajdakin 5abdfd9751 [WRAPPERHELPER] Added predefined mark-simple and conversions (#1845) 2024-09-20 14:32:26 +02:00
ptitSeb ab65619b99 [WRAPPER] Added an entry in gitignore for wrapperhelper 2024-09-20 12:52:54 +02:00
ptitSeb 88629f7aa6 [WRAPPER] Reworked libXft with new wrapperhelper (should help #1841) 2024-09-20 12:51:59 +02:00
ptitSeb fb11af5859 [WRAPPER] Added hack for parser helper to __attribute inline and noreturn 2024-09-20 12:49:01 +02:00
rajdakin 550b72200d Improve the wrapper helper (#1844)
* [WRAPPERHELPER] Fixed some issues, added better macros

* [WRAPPERHELPER] Fixed type_t_equal_lax
2024-09-20 12:40:06 +02:00
Yang Liu cd9d19a2bb [RV64_DYNAREC] Added more opcodes and fixed more issues for vector (#1842)
* [RV64_DYNAREC] Added 66 0F 6D PUNPCKHQDQ opcode

* [RV64_DYNAREC] Added more opcode

* [RV64_DYNAREC] Added more opcodes for vector

* [RV64_DYNAREC] Added more opcodes

* [RV64_DYNAREC] Added more opcodes

* [RV64_DYNAREC] Added more opcode

* More fixes
2024-09-20 11:30:11 +02:00
ptitSeb ca9e43d0f0 [WRAPPER] Added 1 wrapped function to libX11 (for #1204 and #1841) 2024-09-20 10:36:29 +02:00
ptitSeb 04d2f90ab3 Added Syscall 165 (for #1672) 2024-09-20 10:27:18 +02:00
LiZhuoheng 906cdb1584 [RV64_DYNAREC] Added 62 opcode (#1840) 2024-09-20 08:21:12 +02:00
Yang Liu 1978ec8b71 [RV64_DYNAREC] Fixed more issues catched on real machine (#1839) 2024-09-19 20:08:22 +02:00
ptitSeb 28f32a3ca6 [BOX32][WRAPPER] Added minimum 32bits libasound support 2024-09-19 18:57:32 +02:00
Yang Liu 3b7a448b07 [RV64_DYNAREC] Added more 66 0F opcodes for vector (#1838) 2024-09-19 17:07:59 +02:00
ptitSeb 8f0c1efc6f [WRAPPER] Reworked libasound with new wrapperhelper 2024-09-19 14:30:36 +02:00
ptitSeb c10b673fef Fixed a comment on x87 tags 2024-09-19 14:20:21 +02:00
ptitSeb bfd9f79267 [WRAPPER] Some rework on a few wrapped function foor glib2, libxcb and libxcb-private 2024-09-19 13:22:28 +02:00
ptitSeb f7c596317b [TRACE] Fixed a potential segfault when trying to trace a function from a dlopenn'd lib 2024-09-19 13:20:45 +02:00
ptitSeb e4debaf4ba [TRACE] Some better trace for a few function call 2024-09-19 13:20:02 +02:00
ptitSeb 4eeba053d5 Fixed some x87 tag handling 2024-09-19 13:19:12 +02:00
Yang Liu 7263a2e7ab [RV64_DYNAREC] Added more opcodes for vector (#1837) 2024-09-19 12:06:07 +02:00
Yang Liu ef7f25481c [RV64_DYNAREC] Added more opcodes for vector (#1836) 2024-09-19 10:43:23 +02:00
Yang Liu 35d17abeb0 [RV64_DYNAREC] Fixed more unaligned issues for vector (#1835) 2024-09-19 08:11:02 +02:00
Yang Liu 33472d3a8e [RV64_DYNAREC] Fixed some found issues in vector (#1834)
* [RV64_DYNAREC] Fixed 66 0F 63/6B PACKSSWB opcode

* [RV64_DYNAREC] Fixed 66 0F 3A 0F PALIGNR opcode

* [RV64_DYNAREC] GETGX_empty_vector should come after GETEX_vector

* [RV64_DYNAREC] Fixed unaligned memory access

* [RV64_DYNAREC] Fixed more unaligned issue

* Fix CI
2024-09-18 20:27:45 +02:00
ptitSeb e60ddf7ecd [WRAPPER] Reworked libGLU with new wrapper helper 2024-09-18 11:52:00 +02:00
ptitSeb 579332db7d [WRAPPER] Reworked libEGL with new wrapperhelper 2024-09-18 11:38:25 +02:00
ptitSeb b34c031139 [WRAPPER] Reworked libgobject-2.0 with new wrapperhelper 2024-09-18 11:31:29 +02:00
ptitSeb 46bc2e7183 [WRAPPER] Reworked wrapped libpsl.so.5 with new wrapperhelper 2024-09-18 11:00:49 +02:00
ptitSeb 26ddbf9466 [WRAPPER] Reworked wrapping glib-2.0 (stil with new wrapperhelper) 2024-09-18 10:55:00 +02:00
ptitSeb b67dc452b2 [WRAPPER] Reworked wrapped libgio-2.0 2024-09-18 10:09:59 +02:00
Yang Liu b37b6addac [RV64_DYNAREC] Added more opcodes for vector (#1833)
* [RV64_DYNAREC] Added more opcodes for vector

* review
2024-09-18 09:23:54 +02:00
ptitSeb a2dfe70cd8 [WRAPEPR] Reworked wrapping of libgdk3 2024-09-17 19:10:10 +02:00
ptitSeb 20a2b4e051 [WRAPPER] Reworked gtk3 wrapping 2024-09-17 18:36:03 +02:00
ptitSeb d7c3c3fcf9 Save flags and defered flags when runing EmuCall ([DYNAREC] Same for DynaCall) 2024-09-17 16:39:54 +02:00
ptitSeb 7d77a4b31f [DYNAREC] Track if a dynablock is for 32bits code (for future use) 2024-09-17 16:33:59 +02:00
Yang Liu 59217ccbbe [RV64_DYNAREC] Added more 66 0F opcodes for vector (#1832) 2024-09-17 13:31:47 +02:00
Yang Liu f674953b87 [RV64_DYNAREC] Added more 66 0F opcodes for vector (#1831) 2024-09-17 09:35:15 +02:00
Yang Liu b8798c580f [RV64_DYNAREC] Added more opcodes for vector (#1830) 2024-09-16 19:38:37 +02:00
Yang Liu 2b58e8a253 [RV64_DYNAREC] Added more 66 0F opcodes for vector (#1829) 2024-09-16 19:13:21 +02:00
ptitSeb f744513941 Fixed non-box32 builds 2024-09-16 19:03:50 +02:00
ptitSeb e8ecbbdc6a [BOX32][TRACE] Improved some trace and function calls for 32bits process 2024-09-16 17:53:24 +02:00
ptitSeb 1f7c69e19e [BOX32] Added 1 more wrapped 32bits libc function 2024-09-16 17:52:47 +02:00
ptitSeb de4044d5b1 [BOX32] Fixed an issue with using 32bits OpenGL with SDL1.2 2024-09-16 17:42:22 +02:00
ptitSeb 1503241c7a [BOX32] Added some more 32bits wrapped function, and fixing some SDL ones 2024-09-16 17:25:06 +02:00
ptitSeb 37a1261693 [DYNAREC] Forgot some files in previous commit 2024-09-16 16:18:19 +02:00
ptitSeb 446d57122c [DYNAREC] Make sure jump address is wrapped on 32bits address space 2024-09-16 16:10:29 +02:00
ptitSeb 1e8807ac0a [BOX32][TRACE] Added a warning when executing 32bits code in 64bits address space 2024-09-16 16:09:11 +02:00
ptitSeb 40ac1bca84 [BOX32] Partial handling of wrapped dl_iterate_phdr 2024-09-16 15:31:46 +02:00
ptitSeb bff3b935fb Better handling of argv[0] 2024-09-16 15:30:39 +02:00
ptitSeb 9faa9f41e0 [ARM64_DYNAREC] Fixed most CD xx opcodes 2024-09-15 15:22:35 +02:00
ptitSeb 9fa43f2386 Added a hack so program that wprintf to the console actualy work if box64 already printed something 2024-09-14 17:36:45 +02:00
ptitSeb f2397256e2 [BOX32][WRAPPER] Added more 32bits sdl1 and libc symbols 2024-09-14 16:46:13 +02:00
ptitSeb e5ad7c36ec [BOX32][ELFLOADER] Fixed some issue with symbol resolver 2024-09-14 16:45:44 +02:00
ptitSeb 3b8ba5dfa6 Added 66 F3 0F BD opcode ([ARM64_DYNAREC] Too) 2024-09-14 15:21:15 +02:00
ptitSeb 2e1b58a876 [BOX32] Added a few libc 32biyts wrapped functions 2024-09-14 11:37:22 +02:00
ptitSeb de7baa0b41 [BOX32] Added (mostly untested) wrapped libGL and minimum SDL1 (SDLgears and zsnes works) 2024-09-14 10:26:38 +02:00
ptitSeb b361a0d2ff Fixed flags for AVX.0F38 F2 opcode ([ARM64_DYNAREC] too) 2024-09-14 08:46:23 +02:00
Yang Liu 0acd849f18 [RV64_DYNAREC] Added 1 more opcode for vector and some refactor and fixes too (#1824) 2024-09-13 12:16:09 +02:00
ptitSeb ed4ff15682 [BOX32][TRACE] More improved trace for some 32bits functions call 2024-09-13 12:09:35 +02:00
ptitSeb de276ddfa9 [BOX32][TRACE] Better trace for 32bits call to strtol and strtoul 2024-09-13 11:19:47 +02:00
ptitSeb 192347ea3a [BOX32] More small 32bits signature adjustments 2024-09-13 11:19:12 +02:00
ptitSeb d618cfdf0e [BOX32][TRACE] Better trace for 32bits strncasecmp calls 2024-09-13 11:15:44 +02:00
ptitSeb 0f0762a24c [BOX32] Added one more wrapped 32bits libc function 2024-09-13 11:12:41 +02:00
ptitSeb 89a49db558 [BOX32] Adjusted some 32bits wrapped functions 2024-09-13 11:08:40 +02:00
ptitSeb 1ee51a54de [BOX32][TRACE] Better trace for some 32bits wrapped function calls 2024-09-13 11:08:10 +02:00
ptitSeb 68f394a38b [TRACE] Better trace for 32bits FF 52 opcode 2024-09-13 11:07:31 +02:00
ptitSeb 32c94ac31a [BOX32] Fixed 32bits wrapped localeconv (for #1780) 2024-09-13 10:58:10 +02:00
ptitSeb af476e0d10 [BOX32] Fixed gethostbyname 32bits wrapped function (for #1780 but still crashing) 2024-09-13 10:47:47 +02:00
JunChi1022 b504d07afe [DYNAREC] fix page calculation error (#1822) 2024-09-12 19:04:28 +02:00
Yang Liu 9544fbdff9 [RV64_DYNAREC] Refactored vector SEW tracking (#1820) 2024-09-12 19:03:00 +02:00
Yang Liu 431365d1f8 [RV64_DYNAREC] Fixed a typo on vector_sew initialization (#1819) 2024-09-12 14:14:54 +02:00
ptitSeb 693b4adb4b [STATIC] Forgot this definition 2024-09-12 14:07:15 +02:00
ptitSeb 1a637cb1d8 Fixed a typo 2024-09-12 14:01:53 +02:00
ptitSeb 0d952641ed [STATIC] Try to fix static build 2024-09-12 13:56:52 +02:00
ptitSeb 418e2a00ce [BOX32] Simplified 32bits old pthread cond functions 2024-09-12 10:32:33 +02:00
ptitSeb d1d2de33e6 [WRAPPER] Added handling of old pthread cond functions 2024-09-12 10:32:11 +02:00
ptitSeb ab84faa3ca [WRAPPER] Added 1 wrapped function to glibc2 2024-09-12 10:31:29 +02:00
ptitSeb fc7f83c60b [BOX32][WRAPPER] Added support for old pthread_kill (fixing hanging steamcmd) 2024-09-11 18:01:23 +02:00
ptitSeb af028c9bad [WRAPPER] Small fixes for x86_64 build when using old pthread_kill 2024-09-11 18:00:45 +02:00
ptitSeb 29daae551c [BOX32] Improved 32bits unsupported syscall warning, and added syscall 240 2024-09-11 16:55:42 +02:00
ptitSeb e1a91ea420 [BOX32] Improved trace for 32bits pthread_setname_np 2024-09-11 16:54:17 +02:00
ptitSeb bd60ed8df0 [BOX32] Improved hash<->64bits handling 2024-09-11 16:53:51 +02:00
Yang Liu 6b6d20732e [RV64_DYNAREC] Added more 0F opcodes for vector (#1817) 2024-09-11 14:26:50 +02:00
Yang Liu 4d60b75240 [RV64_DYNAREC] Added more 0F opcodes for vector and optimized some opcodes too (#1816)
* [RV64_DYNAREC] Optimized 66 0F 67 PACKUSWB opcode

* [RV64_DYNAREC] Optimized 66 0F 6C PUNPCKLQDQ opcode

* [RV64_DYNAREC] Added some 0F opcodes for vector

* review
2024-09-11 10:25:04 +02:00
Yang Liu fc9900c8f6 [RV64_DYNAREC] Added more 66 0F opcodes for vector (#1815)
* [RV64_DYNAREC] Added more 66 0F opcodes for vector

* [RV64_DYNAREC] Fixed PACKUSWB for vlen >= 256
2024-09-10 21:11:58 +02:00
Aidan 629346b6a7 [SDORYON1] Oryon1 (Snapdragon Elite) support (#1786) 2024-09-10 19:57:36 +02:00
ptitSeb e95be7cd3f Improved legendary stability 2024-09-10 19:21:15 +02:00
ptitSeb 1bfb50f29a [WRAPPER] Updat generated wrapper files 2024-09-10 19:20:43 +02:00
rajdakin 8187c35ea8 [WRAPPERS] Fixed some wrong wrappings (#1814) 2024-09-10 17:46:10 +02:00
rajdakin 0d6028d837 [WRAPPERHELPER] Added per-arch override, always include 'stdc-predef.h', better parsing (#1813) 2024-09-10 17:25:37 +02:00
ptitSeb 2127eaea22 [BOX32] Put back pthread_t behind hash, but ease hash range to have more native values 2024-09-10 16:55:25 +02:00
ptitSeb 7794a623aa [BOX32] Fix and simplified 32bits threads handling 2024-09-10 15:10:28 +02:00
ptitSeb 0443edc034 [BOX32] Fixed wrapping 32bits version of __cxa_finalize 2024-09-10 15:09:45 +02:00
ptitSeb a7f8dbac56 [WRAPPER] Minors adjustments to pulse audio wrapping 2024-09-10 11:25:07 +02:00
Yang Liu b0ec124329 [RV64_DYNAREC] Added 66 0F D4 PADDQ opcode for vector and fixes SEW cache transform (#1812)
* [RV64_DYNAREC] Added 66 0F D4 PADDQ opcode for vector

* [RV64_DYNAREC] Transform SEW cache after fpu cache
2024-09-10 10:52:04 +02:00
ptitSeb b40121c9b0 [VULKAN] Added missing wrapper for vkCreateSamplerYcbcrConversionKHR 2024-09-10 10:43:54 +02:00
ptitSeb cc9984a082 Fixed alignement of thread funcitons (fixed regression for #1810) 2024-09-10 10:32:45 +02:00
Yang Liu c22758d794 [RV64_DYNAREC] Added more 66 0F opcodes for vector (#1811) 2024-09-10 08:58:22 +02:00
ptitSeb 1b48cd157a [RCFILE] Slightly changed how BOX64_ARGS behave, and added BOX64_INSERT_ARGS 2024-09-09 19:45:48 +02:00
ptitSeb 362402ffbf Improved wrapped function clone handling of CLONE_NEWUSER flag 2024-09-09 17:11:29 +02:00
ptitSeb 5ce868b100 When showing opcode on SEGFAULT/SIGBUS, show if it's x86 or x64 2024-09-09 17:10:04 +02:00
ptitSeb 823d1cc004 [DYNAREC] Simplified a bit getX64Address utility function 2024-09-09 17:07:16 +02:00
ptitSeb 2ce5beae56 [WRAPPER] Added H as paramterand, added 2 wrapped function from libatomic (for linux BeamNG) 2024-09-09 17:03:46 +02:00
ptitSeb 34fcbbd7b7 [TRACE] Better trace for F3 0F 1E FA opcode 2024-09-09 16:02:37 +02:00
ptitSeb bdde96be95 [ARM64_DYNAREC] Added 64 0F 28/29 opcodes 2024-09-09 16:02:04 +02:00
rajdakin 26b7a49d82 [WRAPPERHELPER] Fixed preprocessor logic, moved type validation to machine (#1808) 2024-09-08 22:26:35 +02:00
ptitSeb fa8a5a2033 [WRAPPER] Added 2 wrapped function to libatomic 2024-09-08 17:25:58 +02:00
rajdakin c87a56ef37 [WRAPPERHELPER] Major enhancements in output quality, allow for generic type mapping (#1807) 2024-09-08 16:43:16 +02:00
rajdakin 2e04ff93ca [WRAPPED] Fixed some libc wrapped functions (#1806)
* [WRAPPED] Fixed some libc wrapped functions

* [WRAPPED] Fixed static build, added back

* [WRAPPED] Fixed unlimited wrapping

* [WRAPPED] Forgot to update
2024-09-08 15:10:45 +02:00
ptitSeb a9f96b9d62 Show x86opcode at segfault if segfault address is not pc 2024-09-08 15:06:54 +02:00
ptitSeb 8f855f5dde [ARM64_DYNAREC] Avoid computing flags if they are just recomputed at jump point 2024-09-08 14:18:03 +02:00
ptitSeb 6d3fa25d5f [ARM64_DYNAREC] Small optim for 0F C6 opcode 2024-09-08 14:03:47 +02:00
ptitSeb 57b7bcf8f4 [WRAPPING] Updated gtk3 wrapping (still more work to do) 2024-09-08 10:02:39 +02:00
rajdakin f30d75ae5d [WRAPPERHELPER] General improvements (#1804)
* [WRAPPERHELPER] Automatic headers detection, various bug fixes, added some cast support

* [WRAPPERHELPER] Keep comments untouched
2024-09-07 20:53:51 +02:00
ptitSeb e087e7782c [WRAPPER] Fixed some OpenGL function signatures 2024-09-07 19:06:04 +02:00
ptitSeb 17fa93035a Added some more wrapeed function to libusb1 (for #1802) 2024-09-07 15:48:22 +02:00
rajdakin f0d7582845 Upgraded the wrapper helper (#1803)
* [WRAPPERHELPER] Fixed unsigned comparison in macros, added macro expanding in include commands, added -I option

* [WRAPPERHELPER] Forgot the README
2024-09-07 15:20:17 +02:00
ptitSeb 75bdb32828 Added a small fix in signe handler ucntx construction 2024-09-07 11:59:34 +02:00
ptitSeb fd633d2cee Allow dynarec_dump=2 and forbid dynarec_test=2 (fixed a regression with command line params) 2024-09-07 09:40:50 +02:00
ptitSeb a6d7d83fb3 Added a workaround with syscall if statx function is not defined in libc 2024-09-07 09:20:45 +02:00
ptitSeb a450b9d12f [ARM64_DYNAREC] Improved AVX.66.0F38 8C opcode 2024-09-06 18:01:40 +02:00
ptitSeb 5ac3eeef11 Fixed name of opcode in comment 2024-09-06 18:00:00 +02:00
ptitSeb 9838c2ccff Fixed a typo 2024-09-06 17:59:38 +02:00
ptitSeb 16cee6feb2 Added 1 wrapped function libxkbcommon 2024-09-06 16:13:35 +02:00
rajdakin 21c86f9ac6 [WRAPPED] Update libc wrappers (#1800)
* [WRAPPED] Fixed some issues in libc_private.h and the wrapper generator

* [WRAPPED] Forgot to run the Python script

* [WRAPPED] Oops
2024-09-06 15:08:01 +02:00
rajdakin 6044feb7fd Wrapper helper (#1799)
* [WRAPPERHELPER] Added wrapperhelper v0.1, tested on libc

* [WRAPPED] Removed updates to libc from this branch

* [WRAPPERHELPER] Removed GPL header and added modified LGPL header, added notes about licensing issues
2024-09-06 15:07:38 +02:00
Yip Coekjan 7dc59ac342 Eliminate duplicate hash calculations for getSymbolInSymbolMaps (#1801) 2024-09-06 14:35:32 +02:00
ptitSeb 16f156be3f Added 1 wrapped function to libgdk3 2024-09-06 10:59:03 +02:00
rajdakin 64dd09becc [WRAPPED] Removed GOS, renamed GODW into GOWD (#1797) 2024-09-05 20:26:45 +02:00
ptitSeb 19dc18f7c5 Fixed a regression introduced with box32 that broke Bladur's Gate 3 (and probably a few other) 2024-09-05 19:12:19 +02:00
Yang Liu 4e63b82f5e [CI] Refactored CI (#1795)
* [CI] Enable Box32 tests on LA64

* upgrade QEMU

* [COSIM] Removed thread-safe tests

* Use regular cosim in CI

* [CI] Simplified "Test Box64"

* exclude certain tests when testing with cosim

* review

* box64.pod too
2024-09-05 11:07:27 +02:00
ptitSeb 6bc2abae3b [ARM64_DYNAREC] Added 67 66 0F 7E opcode 2024-09-04 21:04:20 +02:00
ptitSeb 6c7f306baa [ARM64_DYNAREC] Added AVX.66.0F 51 opcode 2024-09-04 20:56:23 +02:00
ptitSeb c56517b801 More work on Custom Mem speedup 2024-09-04 17:45:28 +02:00
ptitSeb b5e405b2b4 Added an rbtree is Custom Mem Manager to speedup customFree and customRealloc 2024-09-04 15:23:37 +02:00
ptitSeb 354f46f41b Some refactor (and small bugfixes) around Custom Mem Manager 2024-09-04 14:39:44 +02:00
Yang Liu b34a50b381 [X64LIBS] Changed x86/x64 libs install directory to prevent conflicts (#1791)
* [X64LIBS] Changed x86/x64 libs install directory to prevent conflicts

* Update pressure_vessel
2024-09-04 14:13:58 +02:00
ptitSeb a973c53ea2 [BOX32] This should fix NO_ALIGN box32 build 2024-09-04 11:28:11 +02:00
ptitSeb ee7b10f064 [BOX32] Small improvments on memory management 2024-09-04 11:00:43 +02:00
Yang Liu c1ad6b5829 [CI] Speedup CI by removing some unnecessary targets (#1790) 2024-09-04 09:59:27 +02:00
ptitSeb 9eaaaaa1e3 [BOX32] Added some more 32bits wrapped function to libc 2024-09-03 20:19:34 +02:00
ptitSeb 115707a0f1 [BOX32] Fixed a missing box_free 2024-09-03 20:19:34 +02:00
ptitSeb 3179357666 [BOX32] Better trace for 32bits posix_memalign 2024-09-03 20:19:34 +02:00
ptitSeb cb7433d70a [RCFILE] Fixed some missing box_free/box_strdup in rcfile 2024-09-03 20:19:34 +02:00
ptitSeb 62021fc291 [BOX32] Better log for 32bits pointer conversion error 2024-09-03 20:19:34 +02:00
ptitSeb ab3ff07c93 [BOX32] Fixed 32bits locale memory size 2024-09-03 20:19:34 +02:00
Yang Liu 22ab62a729 [WRAPPED] Added back some libc function wrappers (#1788) 2024-09-03 12:50:02 +02:00
ptitSeb ff7a8bfdae [BOX32] Various small fixes 2024-09-02 09:53:36 +02:00
Yang Liu 27ed109394 [BOX32] Fixed build with mold (#1785) 2024-09-01 20:58:10 +02:00
rajdakin ea807eda04 [WRAPPED] Merged types D/K and Y/y in 64bits wrapped libs (#1784)
* [WRAPPED] Merged types D/K and Y/y in 64bits wrapped libs

* [WRAPPERS] Version bump

* [WRAPPED] Fixed wrapped glib2 on non-LD80BITS builds
2024-09-01 19:06:03 +02:00
JunChi1022 36321f809d [DYNAREC]: fix BICS encoding (#1783) 2024-09-01 17:58:18 +02:00
ptitSeb 254df70148 [BOX32] Better handling for FILE* 2024-09-01 17:44:32 +02:00
ptitSeb 759cef6e01 [BOX32] Fixes and hacks to get steamcmd shows the prompt 2024-09-01 17:09:54 +02:00
ptitSeb 02364151bc [BOX32] Some fixes to strtol/strtoul and read 32bits wrapped functions 2024-09-01 13:59:51 +02:00
ptitSeb 9178effd9f [BOX32] More wrapped function and a few fixes for steamclient.so (still crashing) 2024-09-01 13:07:47 +02:00
ptitSeb cce9e280ce [BOX32] New batch of 32bits wrapped functions for steamconsole.so 2024-08-31 17:30:22 +02:00
ptitSeb 5468d8b08e [BOX32] One more 32bits wrapped function for libvstdlib_s.so 2024-08-31 17:20:01 +02:00
ptitSeb 497f629761 [BOX32] Another batch of 32bits wrapped function, for libvstdlib_s.so this time 2024-08-31 15:59:48 +02:00
ptitSeb 6f08601479 [BOX32] Another batch of 32bits wrapped function, for libtier0_s.so 2024-08-31 14:52:45 +02:00
ptitSeb 6d6739ccea [BOX32] More 32bits wrapped functions 2024-08-31 11:39:55 +02:00
ptitSeb d2511e66fb [RCFILE] Added support fro cursor (for #1778) 2024-08-31 09:05:36 +02:00
Yang Liu e23eb14809 [RV64_DYNAREC] Added xthead* extensions to the new printer (#1781) 2024-08-31 07:47:28 +02:00
Yang Liu f5dbe2156c [RV64_DYNAREC] Refactored rv64_printer (#1779)
* [RV64_DYNAREC] Refactored printer

* Fixed one more issue
2024-08-30 20:32:15 +02:00
ptitSeb 723b94da05 [BOX32] More 32bits wrapped function and fixes 2024-08-30 18:54:16 +02:00
ptitSeb 7ecdced486 [BOX32] Added more 32bits wrapped function and fixes 2024-08-30 15:59:07 +02:00
ptitSeb 13b72df762 [BOX32] Define native_statvfs to avoid build errors 2024-08-30 13:50:37 +02:00
Yang Liu 95b38b7f79 [CI] Added 60s timeout per test (#1777) 2024-08-30 13:24:15 +02:00
ptitSeb 3fb5052223 [BOX32] More 32bits wrapped functions and fixes 2024-08-30 13:22:48 +02:00
Yang Liu 62b93a0785 Wrapped 1 more function for libxcb (#1776) 2024-08-30 12:30:23 +02:00
ptitSeb 371b45c420 [BOX32] Added detection of steam and steamcmd 2024-08-30 10:13:42 +02:00
ptitSeb 4dcf14d026 [ARM64_DYNAREC] Added 67 F3 0F 38 F6 opcode (for #1775) 2024-08-30 10:02:49 +02:00
ptitSeb 854ee95d69 Added 67 F3 0F 38 F6 opcode (for #1775) 2024-08-30 09:58:42 +02:00
ptitSeb 9ac536a1dd [BOX32] More fixes to ctype_b_loc and added a few more wrapped functions 2024-08-29 18:17:57 +02:00
Yang Liu 9820bee5e7 [BOX32][LA64_DYNAREC] Added preliminary box32 support (#1773) 2024-08-29 17:16:39 +02:00
ptitSeb b02302a5cf [BOX32] Fixed 32bits localtime_r wrapped function 2024-08-29 16:32:14 +02:00
ptitSeb 9633ad35a8 [BOX32] Added more 32bits wrapped function and more fixes 2024-08-29 16:30:39 +02:00
ptitSeb 4bd6294862 [TRACE] Added one 32bits jump decoding dest address 2024-08-29 16:30:09 +02:00
ptitSeb 63e525697f [BOX32][TRACE] Improve function trace log 2024-08-29 16:29:21 +02:00
ptitSeb 4cdd46819f [TRACE] Improved trace on symbol name 2024-08-29 11:10:45 +02:00
Yang Liu 0450371e28 [RV64_DYNAREC] Fixed a falsy optimization, better EMIT macro (#1769) 2024-08-28 23:06:29 +02:00
Yang Liu d9e5f8183f [RV64_DYNAREC] Optimized jump_to_next using XTheadBb instructions (#1768)
* [RV64_DYNAREC] Optimized jump_to_next using XTheadBb instructions

* fixed some bad bad typos
2024-08-28 23:05:02 +02:00
Yang Liu abbaf9b593 [BOX32][RV64_DYNAREC] Fixed more issues and enable CI for box32 (#1767)
* [BOX32][RV64_DYNAREC] Fixed more issues

* fix

* fix

* enable Ci for box32

* add some comments
2024-08-28 19:48:22 +02:00
ptitSeb 126c59b4a4 [BOX32] More wrapped 32bits functions, and some fixes too 2024-08-28 18:35:24 +02:00
ptitSeb b7be225846 [BOX32] More 32bits wrapped functions 2024-08-28 17:12:00 +02:00
ptitSeb 041eb4e69d [BOX32] Adding some more 32bits wrapped functions 2024-08-28 15:03:16 +02:00
ptitSeb 04157f2502 [ARM64_DYNAREC] Not using simpleWrapper when dynarec_test is on 2024-08-28 15:02:48 +02:00
Yang Liu 189222cb66 [BOX32][RV64_DYNAREC] Added preliminary box32 support to RV64 (#1766)
* [BOX32][RV64_DYNAREC] Added preliminary box32 support to RV64

* fix

* fix fix

* fix
2024-08-28 14:01:50 +02:00
ptitSeb 6835c4aaf5 [BOX32] Fixed some error log in elfloader32 2024-08-28 12:44:53 +02:00
Yang Liu 875a2ef3a9 [RV64_DYNAREC] Added a fast path for some 16bit opcodes (#1765) 2024-08-27 20:23:42 +02:00
ptitSeb bfbf18688b [ARM64_DYNAREC] Small refactor around get_segdata usage 2024-08-27 18:57:36 +02:00
Yang Liu 9de694c46b [RV64_DYNAREC] Added a fast path for some 8bit opcodes (#1763)
* [RV64_DYNAREC] Added a fast path for some 8bit opcodes

* fix

* more

* more
2024-08-27 18:55:11 +02:00
KreitinnSoftware 220c5ee47d [CTEST] Use BOX64_LD_LIBRARY_PATH instead of default LD_LIBRARY_PATH (#1764) 2024-08-27 18:34:58 +02:00
ptitSeb 99f2207fd4 [ARM64_DYNAREC] Mark new upper YMM part as new, so the can be unwind too (for #1759) 2024-08-27 10:57:51 +02:00
KreitinnSoftware 50623f32f6 Revert "[ANDROID] Not use 'libbsd.so' as needed lib and don't define NEEDED_L…" (#1762)
This reverts commit a7c61d8e20.
2024-08-27 08:37:40 +02:00
b5105a1e57 Added preliminary Box32 support (#1760)
* Improve the ReserveHigMemory helper function

* [BOX32] Added some wrapping infrastructure

* [BOX32] More wrapped 32bits lib infrastructure

* [BOX32] Added callback and tls 32bits handling

* [BOX32] Added more 32bits, around wrappers and elfs

* [BOX32] Added the 32bits version of myalign

* [BOX32] More wrapped libs and 32bits fixes and imrpovments

* [BOX32] Added some 32bits tests

* [BOX32] Try to enable some Box32 build and test on the CI

* [BOX32] Disable Box32 testing on CI platform that use qemu

* [BOX32] Another attempt to disable Box32 testing on CI platform that use qemu

* [BOX32] Small fix for another attempt to disable Box32 testing on CI platform that use qemu

* [BOX32] Yet another fix for another attempt to disable Box32 testing on CI platform that use qemu

* [BOX32] Fixed a typo in CI script

* [BOX32] Better scratch alighnment and enabled more tests

* [BOX32] Added (partial) wrapped 32bits librt

* [BOX32] Added mention of Box32 in README

* [BOX32] Added phtread handling, and numerous fixes to 32bits handling. [ARM64_DYNAREC] Fixed access to segment with negative offset

* [BOX32] Added system libs and cpp testing, plus some more fixes

* [BOX32] Fix previous commit

* [BOX32] Better stack adjustment for 32bits processes

* [BOX32] Added getenv wrapped 32bits function and friends

* [BOX32] Don't look for box86 for a Box32 build

* [BOX32] Don't do 32bits cppThreads test for now on CI

* [BOX32] Enabled a few more 32bits tests

* [BOX32] For ld_lib_path for both CppThreads tests

* [BOX32] [ANDROID] Some Fixes for Android Build

* [BOX32] Still need to disable cppThread_32bits test on CI for some reason

* [BOX32] [ANDROID] Don't show PreInit Array Warning (#1751)

* [BOX32] [ANDROID] One More Fix for Android Build That I forgotten to … (#1752)

* [BOX32] [ANDROID] One More Fix for Android Build That I forgotten to push before

* [BOX32] [ANDROID] Try to Create __libc_init

* [BOX32] [ANDROID] Try to disable NEEDED_LIBS for now (libdl is not wrapped)

* [BOX32] Updated generated files

* [BOX32] Added 32bits context functions

* [BOX32] Added 32bits signal handling

* [BOX32] Added some missing 32bits elfloader functions

* [BOX32] Fix build on x86_64 machine

* [BOX32] Better fix for x86_64 build

* [BOX32] Actually added missing libs, and re-enabled cppThreads_32bits test

* [BOX32] Added wrapped 32bits libdl

* [BOX32] Try to re-enabled Box32 test on CI for ARM64 builds

* [BOX32] fine-tuning Box32 test on CI for ARM64 builds

* [BOX32] More fine-tuning to Box32 test on CI for ARM64 builds

* [BOX32] Enabled Box32 test on CI for LA64 and RV64 builds too

* [BOX32] re-Disabled Box32 test on CI for LA64 and RV64 builds, not working for now

* [BOX32] Temporarily disabled cppThreads_32bits test on CI

---------

Co-authored-by: KreitinnSoftware <[email protected]>
Co-authored-by: KreitinnSoftware <[email protected]>
2024-08-26 17:45:13 +02:00
WANG Guidong 9beb745765 [RV64_DYNAREC] Fix some typos in docs and dynarec/rv64 (#1758)
* [Typo] fix some typo in docs and dynarec/rv64

* [Typo] fix some typo in docs and dynarec/rv64

* [Typo] fix some typo in dynarec/rv64

* [Typo] fix some typo in dynarec/rv64

* [Typo] fix some typo in docs
2024-08-26 08:19:06 +02:00
KreitinnSoftware 0b1dd757be [EMU] [ARM64_DYNAREC] Fix Some Warnings on Clang Compilers (#1757) 2024-08-26 08:15:55 +02:00
KreitinnSoftware a7c61d8e20 [ANDROID] Not use 'libbsd.so' as needed lib and don't define NEEDED_LIBS_234 for Android Too, Use BOX64_LD_LIBRARY_PATH instead of LD_LIBRARY_PATH on CTEST (#1754)
* [ANDROID] Not use 'libbsd.so', 'libpthread.so' as needed libs and don't define NEEDED_LIBS_234 for Android Too

* [ANDROID] Use 'libpthread.so' again

* [CTEST] Try to use BOX64_LD_LIBRARY_PATH instead of LD_LIBRARY_PATH
2024-08-25 19:53:09 +02:00
Yang Liu 4988fb27dc [RV64_DYNAREC] Fixed more issues in the vector infrastructure (#1755)
* [RV64_DYNAREC] Fixed SEW transformation for vector

* more tweaks

* more fixes

* More fixes

* more fixes

* re-enable vector extension by default
2024-08-25 19:52:50 +02:00
ptitSeb db1f0825ce Merge pull request #1750 from ksco/fix
[RV64_DYNAREC] Fixed various issues in vector infra
2024-08-24 21:03:55 +02:00
Yang Liu c7b2a5f2df More fixes 2024-08-25 02:24:57 +08:00
Yang Liu b9cbd29bc4 Try to fix SSE type transformation 2024-08-24 19:27:57 +08:00
Yang Liu 84b53ecb42 [RV64,LA64_DYNAREC] Remove useless #if directives 2024-08-20 13:49:01 +08:00
ptitSeb 66da28a02f Merge pull request #1746 from ksco/disable_vector
[RV64_DYNAREC] Disable vector extension by default until it's ready
2024-08-19 14:36:26 +02:00
Yang Liu 15f6bbebe1 [RV64_DYNAREC] Disable vector extension by default until it's ready. 2024-08-19 20:10:02 +08:00
ptitSeb 2daef545dd Forgot to expose adx extension in cpuinfo virtual file 2024-08-19 10:57:03 +02:00
ptitSeb aac6b3d02d Forgot to expose f16c, xsave and randr extensions in cpuinfo virtual file 2024-08-19 10:46:13 +02:00
ptitSeb fda0e9a4cb Merge branch 'box32' into main 2024-08-18 16:02:27 +02:00
ptitSeb f1da5d433a [RV64_DYNAREC] Set the log level to Info for the LOCK CMPXCHG16B warning, to avoid breaking winetricks 2024-08-18 15:57:14 +02:00
ptitSeb dead2003fa [HACK] Patch Heroic 2.15.1 to avoid some internal memory manager test, until a better solution is found (heroic is still a bit unstable) 2024-08-18 10:46:15 +02:00
Yang Liu 44dfa53d45 warn only once 2024-08-18 10:46:15 +02:00
Yang Liu 769a9f65a9 Slightly improved LOCK CMPXCHG16B opcode 2024-08-18 10:46:15 +02:00
Yang Liu 5b78159cb5 [RV64_DYNAREC] Added a warning on LOCK CMPXCHG16B opcode 2024-08-18 10:46:15 +02:00
ptitSeb c384d53d75 [HACK] Patch Heroic 2.15.1 to avoid some internal memory manager test, until a better solution is found (heroic is still a bit unstable) 2024-08-18 10:16:38 +02:00
ptitSeb 683e44baf9 [BOX32] Added 32bits elf reloc type rel handling 2024-08-17 16:59:55 +02:00
ptitSeb c845d0cf81 [BOX32] Added 32bits elf alloc and load 2024-08-17 15:59:09 +02:00
Yang Liu 243a4deae7 warn only once 2024-08-17 15:57:48 +02:00
Yang Liu fe80d6305c Slightly improved LOCK CMPXCHG16B opcode 2024-08-17 15:57:48 +02:00
Yang Liu a0e7113397 [RV64_DYNAREC] Added a warning on LOCK CMPXCHG16B opcode 2024-08-17 15:57:48 +02:00
ptitSeb d47b1b0e56 [BOX32] Added 32bits elf header parser and dumper 2024-08-17 14:25:04 +02:00
ptitSeb fa87b0fcef [BOX32] prepare elfheader_t structure for 32bits elfs 2024-08-17 12:24:26 +02:00
Yang Liu 0f1bce0f32 [RV64_DYNAREC] Added more opcodes (#1740)
* [RV64_DYNAREC] Added more opcodes

* more opcodes

* more
2024-08-16 18:47:21 +02:00
Yang Liu bc0b5b1181 [LA64_DYNAREC] Port recent RV64 fixes (#1739) 2024-08-16 18:47:21 +02:00
Yang Liu 38833b9cf4 Added more curl function wrapper (#1738) 2024-08-16 18:47:21 +02:00
Yang Liu dda4f48397 [RV64_DYNAREC] Added 66 0F 3A 63 PCMPISTRI opcode (#1735) 2024-08-16 18:47:21 +02:00
Yang Liu bb712b1ad5 Added 1 more gtk3 function wrapper (#1737) 2024-08-16 18:47:21 +02:00
Yang Liu 6ddb5b3477 [RV64,LA64_DYNAREC] Small change when handling long CC INT 3 opcode (#1736) 2024-08-16 18:47:21 +02:00
Yang Liu c4253b73fa [RV64_DYNAREC] Added more opcodes (#1740)
* [RV64_DYNAREC] Added more opcodes

* more opcodes

* more
2024-08-16 18:16:20 +02:00
Yang Liu 3c1f6c2436 [LA64_DYNAREC] Port recent RV64 fixes (#1739) 2024-08-16 12:10:17 +02:00
Yang Liu 83484cfb60 Added more curl function wrapper (#1738) 2024-08-16 12:09:26 +02:00
Yang Liu a106082397 [RV64_DYNAREC] Added 66 0F 3A 63 PCMPISTRI opcode (#1735) 2024-08-16 12:09:00 +02:00
Yang Liu 6498248cef Added 1 more gtk3 function wrapper (#1737) 2024-08-16 12:08:53 +02:00
ptitSeb b2f94b274c [BOX32] Start differentiate 64bits from 32bits in elf parser 2024-08-16 10:56:47 +02:00
ptitSeb 34b85b3560 Detect 32bits elf before loading 2024-08-16 10:52:36 +02:00
Yang Liu 7bb30efb50 [RV64,LA64_DYNAREC] Small change when handling long CC INT 3 opcode (#1736) 2024-08-15 20:14:33 +02:00
ptitSeb 7df2b6b252 Added BOX32 option to CMakeList.txt 2024-08-15 15:50:16 +02:00
ptitSeb 017d13a7b0 [ARM64_DYNAREC] Small change when handling lone CC INT 3 opcode 2024-08-15 15:46:19 +02:00
ptitSeb 513647b272 Added syscalls 444-446 2024-08-15 15:45:50 +02:00
ptitSeb 280b1576c3 [ARM64_DYNAREC] Added AVX.66.0F38 A6 opcode 2024-08-15 14:07:51 +02:00
ptitSeb 2dfd449561 [ARM64_DYNAREC] Added 67 90..97 opcodes 2024-08-15 14:00:34 +02:00
ptitSeb 65b1b9256a Fixed falsly detection of needed memory hack 2024-08-15 14:00:02 +02:00
ptitSeb 7866f116df [TRACE] Better trace for libc syscall 2024-08-15 13:59:18 +02:00
ptitSeb 4544e1556a Added syscalls 122-124 2024-08-15 13:58:46 +02:00
Yang Liu 8c7d96ad63 [RV64_DYNAREC] Fixed extcacheUnwind regression (#1734) 2024-08-15 10:17:27 +02:00
ptitSeb bd23e1f7fc [RCFILE] Fine tuned profile for on of the EALauncher process 2024-08-12 21:23:30 +02:00
ptitSeb 99187a2d22 Added (fake) syscall 175 to libs syscall 2024-08-12 21:22:23 +02:00
Yang Liu 8974caf162 [RV64_DYNAREC] Fixed 0F BA /5 BTS opcode (#1733) 2024-08-12 21:09:19 +02:00
xctan f364c03964 [RV64_DYNAREC] More fixes (#1732)
* [RV64_DYNAREC] Fixed pending flag type in emit_sar16

* [RV64_DYNAREC] Fixed imm12 overflow in geted

* [SYSCALL] Added fake sys_init_module
2024-08-12 20:11:19 +02:00
ptitSeb 730eb1f472 [ARM64_DYNAREC] Some small improvments to ROR/ROL/RCR/RCL opcodes 2024-08-11 14:56:13 +02:00
ptitSeb 3760be946f [WRAPPER] Wrapped libdrm_amdgpu.so.1 2024-08-10 20:04:56 +02:00
Yang Liu 7db74b84cf [RV64_DYNAREC] Fixed flags for shrd/shld with constant 0 shift (#1730) 2024-08-10 10:51:56 +02:00
xctan 4c0a25db2a [RV64_DYNAREC] Fixed ROL/ROR RCX, CL (#1729) 2024-08-10 10:51:44 +02:00
ptitSeb 67af8c2bad Added 67.AVX.0F.66 D6 opcode ([ARM64_DYNAREC] too) 2024-08-10 09:58:42 +02:00
ptitSeb 92531929f3 Added 64bits 67 F3 0F 7F opcode ([ARM64_DYNAREC] too) 2024-08-10 09:50:11 +02:00
ptitSeb 0256a6332c [ARM64_DYNAREC] Fixed flags for surd/shld with constant 0 shift 2024-08-10 09:40:05 +02:00
ptitSeb bd4454d8ad [ARM64_DYNAREC] Fixed pending flags for large 8 & 16 bit const shifts 2024-08-10 09:34:09 +02:00
xctan 4187581be5 [RV64_DYNAREC] Fixed pending flags for large 8 & 16 bit const shifts (#1728) 2024-08-10 09:17:02 +02:00
Yang Liu 2a07636623 [RV64_DYNAREC] Fixed more register conflicts (#1726) 2024-08-09 20:16:52 +02:00
ptitSeb 8893344b76 Fix non-Dynarec build 2024-08-09 18:17:16 +02:00
ptitSeb f0ea65dc36 [DOCS] Added entry in USAGE.md for newly introduced BOX64_ARGS 2024-08-09 17:44:05 +02:00
ptitSeb 53756ee966 Improved Steam wine compatibility, not perfect, but better (thanks Hugo for the args) 2024-08-09 17:41:01 +02:00
xctan 8a2ee1ed59 [RV64_DYNAREC] Fixed OF generation in emit_sar16c (#1724) 2024-08-09 17:31:13 +02:00
ptitSeb 9bc9c10fb3 [ARM64_DYNAREC] Added AVX.66.0F38 9A opcode 2024-08-09 14:30:32 +02:00
Yang Liu 4407a17551 [RV64_DYNAREC] Fixed fpu_flags handling and enabled cosim in CI (#1722)
* [RV64_DYNAREC] Fixed fpu_flags handling

* repeat until-pass
2024-08-09 13:31:58 +02:00
xctan c7d6395aa6 [RV64_DYNAREC] Fixed misused BNE_NEXT in emit_ro{l,r}32 (#1723) 2024-08-09 13:29:37 +02:00
Yang Liu 649a65b8ee [RV64_DYNAREC] Fixed FNSTSW opcode (#1721) 2024-08-09 12:03:20 +02:00
Yang Liu 949b64ca53 [DYNAREC_RV64] Removed TODOs on GETEX and GETEM macros (#1720) 2024-08-09 12:02:14 +02:00
xctan cef906b24d [RV64_DYNAREC] Fixed register conflict in the GETSEB marco (#1719) 2024-08-09 09:25:27 +02:00
xctan 040c2c3d1b [RV64_DYNAREC] Fixed register conflict with GETEB macro (#1718) 2024-08-08 17:29:56 +02:00
Yang Liu 91ed6a83c1 [INTERP] Fixed some undefined behaviour (#1717) 2024-08-08 17:05:00 +02:00
Yang Liu d8ac8a5f1c [LA64_DYNAREC] Fixed flag generation in IMUL/MUL opcode (#1716) 2024-08-08 08:27:35 +02:00
xctan 18954abf54 [RV64_DYNAREC] Fixed flag generation in IMUL/MUL opcode (#1715) 2024-08-08 08:25:05 +02:00
ptitSeb ed7ee12e7e [GTK] Added wrapped GstVideoBufferPool 2024-08-07 15:11:31 +02:00
ptitSeb 42d99d2b2a [ARM64_DYNAREC] Added AVX.F3.0F38 F7 opcode 2024-08-07 10:26:17 +02:00
ptitSeb d24f13cd73 Small optimisation on xsave / xrstor helper 2024-08-07 10:13:43 +02:00
ptitSeb e8fad11128 [ARM64_DYNAREC] Added F0 20 opcode 2024-08-04 09:48:18 +02:00
ptitSeb 27a8d19f31 Added 3 syscalls 2024-07-30 16:00:32 +02:00
ptitSeb 387a3eeba3 [DYNAREC] Remove BARRIER_NEXT macro 2024-07-29 22:47:43 +02:00
Ilya114 3a3578aecc Update README_UK.md (#1709) 2024-07-28 09:21:46 +02:00
ptitSeb a8784eff9f [RCFILE] Added support for generic names in RCFiles 2024-07-25 15:10:40 +02:00
ptitSeb b26ae5886d Added 67 66 0F EF opcode ([ARM64_DYNAREC] too) 2024-07-23 17:40:56 +02:00
ptitSeb e6696f8d23 Added 67 66 0F FE opcode ([ARM64_DYNAREC] too) 2024-07-23 17:13:24 +02:00
Yang Liu 2989afdf84 [RV64_DYNAREC] Fixed more issues in the vector infrastructure (#1706) 2024-07-23 13:30:06 +02:00
Yang Liu 9c1b015689 [RV64_DYNAREC] Fixed vector infra (#1705) 2024-07-22 21:45:54 +02:00
Yang Liu 3b1fbef95c [DYNAREC] Fixed CI failures for RV64 and LA64 (#1702)
* [DYNAREC] Fixed CI failures for RV64 and LA64

* comment out android tests for now
2024-07-22 09:19:27 +02:00
ptitSeb 2e6acc86e1 Improved exception/int 3 handling 2024-07-21 20:32:17 +02:00
ptitSeb c6e981a363 Better X11 callback in list handling 2024-07-21 18:49:02 +02:00
ptitSeb 43de5afcf6 Improved TF handling 2024-07-21 10:52:58 +02:00
ptitSeb fb40035957 [ARM64_DYNAREC] Add a test about arm64 addresses in pass3, and abort if wrong 2024-07-21 09:39:07 +02:00
ptitSeb 93549259a0 [DYNAREC] Fixed a typo in an error message 2024-07-21 09:38:31 +02:00
ptitSeb f39d3ea43e Leave low memory for wine if it's loaded 2024-07-21 09:38:00 +02:00
Yang Liu 7ad169c7a8 [LA64_DYNAREC] Added more opcodes (#1701) 2024-07-20 14:19:24 +02:00
Yang Liu 052bba4578 [LA64_DYNAREC] Added more opcodes (#1700) 2024-07-20 10:04:07 +02:00
Yang Liu d1eb01e535 [RV64_DYNAREC] Added more 66 0F 38 opcodes for vector (#1699) 2024-07-19 16:05:52 +02:00
Yang Liu 3e20a60c37 [RV64_DYNAREC] Added vector SEW cache (#1698)
* [RV64_DYNAREC] Added vector SEW cache

* handling reset_n
2024-07-19 11:34:45 +02:00
ptitSeb 984c136349 [RCFILE] Re-organized box64.box64rc and add EA/Origin launcher progress profiles 2024-07-18 17:53:59 +02:00
Yang Liu 81f92d8f62 [RV64_DYNAREC] Added 66 0F 38 00 PSHUFB for vector (#1697) 2024-07-18 11:39:48 +02:00
Yang Liu 427051d04c [RV64_DYNAREC] Added more 66 0F opcodes for vector (#1696) 2024-07-18 08:58:05 +02:00
Yang Liu c1a14f93d8 [RV64_DYNAREC] Show missing opcodes in vector implementation (#1695) 2024-07-18 08:13:44 +02:00
Yang Liu f07ee85078 [RV64_DYNAREC] Added vlen detection (#1694) 2024-07-18 08:12:40 +02:00
Yang Liu 51b118d516 [LA64_DYNAREC] Added more opcodes and fixed more issues (#1692) 2024-07-17 19:50:13 +02:00
ptitSeb d5ec4692d3 [INTERPRETER] Fixed some issue with INT opcodes and STEP logic 2024-07-17 12:05:04 +02:00
ptitSeb a62336d433 Added 1 more wrapped function to gstaudio 2024-07-17 10:09:34 +02:00
Yang Liu abb2cbeeaa [LA64_DYNAREC] Added more opcodes (#1690) 2024-07-17 08:15:41 +02:00
ptitSeb 33381857ff Change (again) how Wine prereserved memory is allocated and freed 2024-07-16 22:53:47 +02:00
Yang Liu f1abd95ed0 [LA64_DYNAREC] Added more opcodes (#1688) 2024-07-16 22:50:02 +02:00
Yang Liu 43b155e8b4 [LA64_DYNAREC] Fixed CMPSD (#1687) 2024-07-16 22:49:14 +02:00
Yang Liu 6ee5415ea4 [LA64_DYNAREC] Fixed some opcodes (#1686) 2024-07-16 21:38:19 +02:00
ptitSeb 886ae378c5 Changed how TRAPNO 12 is triggered 2024-07-16 17:24:49 +02:00
Yang Liu 60d886c052 [RV64_DYNAREC] Fixed GETGXSS_empty on upper bits handling (#1685) 2024-07-16 12:57:14 +02:00
Yang Liu d700cc1f55 [RV64_DYNAREC] Clear high 32bits when write back as single (#1684) 2024-07-16 08:57:53 +02:00
Yang Liu 5c212e92c3 [LA64_DYNAREC] Remove xMASK and fixed 86 XCHG opcode (#1683) 2024-07-16 08:18:14 +02:00
Yang Liu 1dde4ee959 [ARM64_DYNAREC] Fixed OR Ew, Gw (#1682) 2024-07-16 08:16:01 +02:00
xctan 9fe450f2dc [RV64_DYNAREC] Fixed some bugs for VMP (#1679)
* [RV64_DYNAREC] Fixed reg x3 conflict with the GETEW macro

* [RV64_DYNAREC] Fixed (LOCK) XCHG Eb, Gb again

* [RV64_DYNAREC] Fixed register conflict in (LOCK) XCHG Eb, Gb
2024-07-16 08:15:33 +02:00
Panda b84e5f25f2 build: fix PKGBUILD-rk3xxx pkgname was set to box86 (#1681) 2024-07-16 08:10:35 +02:00
Yang Liu b52ff061b4 [LA64_DYNAREC] Added 2 more opcodes (#1680) 2024-07-15 23:44:56 +02:00
kaixindeken b7ae79514f Fix hidden error in PR 1677 (#1678)
* Fix most of tiff5 and ltdl7 functions

* Adding missing file

* delete libltdl7 wrapped

* re-wrapped libtiff5 and list all symbols
2024-07-15 18:32:27 +02:00
ptitSeb a90c7af708 Added BOX64_SHAEXT to hide sha cpu extension ([RCFILE] And added a profile using it) 2024-07-15 13:43:53 +02:00
ptitSeb 176e092a6c Added missing generated files 2024-07-15 10:42:04 +02:00
kaixindeken 94ccde160a Wrapped libtiff5 and libltdl7 (#1677)
* Wrapped libtiff5

* no types generated

* libtiff5 added missing defs types undefs files

* wrapped libltdl7

* rerun actions

* add more wrapped function for tiff5 and ltdl7

* remove unused functions
2024-07-15 08:23:14 +02:00
ptitSeb d8746c6c70 Something is wrong, emulated gnutls.so.30 doesn't seems to work fine for now 2024-07-14 15:35:02 +02:00
ptitSeb 4ff4ca72d3 Wrapped lots of new function t be abble to run emulated libgnutls.so.30 2024-07-14 11:18:08 +02:00
ptitSeb 47055f92df [RCFILE] Update a profile, with a workaround, until fixed 2024-07-14 11:17:20 +02:00
Yip Coekjan 7a4a44292c Wrap sqlite3_exec for libsqlite3 (#1674) 2024-07-13 12:52:24 +02:00
ptitSeb 98270a8601 Fix signal stack handling on reentrant signal when using SigAltStack 2024-07-13 11:35:42 +02:00
ptitSeb 182ca255f7 [TRACE] Fixed some issue with function name printing 2024-07-13 10:10:45 +02:00
ptitSeb 3d33713c2b Fixed some issue on tracking when protecting memory with PROT=0 2024-07-13 10:07:39 +02:00
ptitSeb ebf698fdb6 Removed debug leftover 2024-07-12 17:35:47 +02:00
ptitSeb 9d089f9b18 Fixed flaky signal handler on 32bits code (mainly for Wine with new Wow64) 2024-07-12 17:29:15 +02:00
ptitSeb c976833f46 Added 1 syscall (for #1672) 2024-07-12 09:58:34 +02:00
ptitSeb 1819b7563a Revert "[Wrapped] Added sqlite3_exec (#1671)" (#1673)
This reverts commit 548a21a5ec.
2024-07-12 08:52:07 +02:00
kaixindeken 548a21a5ec [Wrapped] Added sqlite3_exec (#1671) 2024-07-12 07:24:49 +02:00
Ivan Melnikov ad1dce7fb1 [RV64_DYNAREC] Cleanup for removed rv64_lock_cas_dq (#1670)
Since rv64_lock_cas_dq is removed, we should also remove its
global symbol declaration and its prototype. Otherwise, we
get and undefined symbol reference, which breaks ELF checks
that some distros employ.

Fixes: 9dbd7fc7e0
2024-07-11 16:57:56 +02:00
ptitSeb 302a358476 [ARM64_DYNAREC] Added handling of FASTNAN=0 to MULSS opcode 2024-07-11 16:47:24 +02:00
ptitSeb 74dd9f2778 Boosted number of X11 callback to 100 2024-07-11 16:18:26 +02:00
ptitSeb 495262f902 Fixed a nasty bug on memory permission tracking 2024-07-11 12:16:31 +02:00
ptitSeb d10a078473 [STATICBUILD] removed Android staticbuild 2024-07-10 16:37:46 +02:00
ptitSeb 8d9fd7cb0e [STATICBUILD] build 2024-07-10 16:09:21 +02:00
ptitSeb 8bd8a923ba [STATICBUILD] Go green now 2024-07-10 16:00:31 +02:00
ptitSeb 764a0c31e5 [STATICBUILD] This is getting old already, turn to green now! 2024-07-10 15:25:49 +02:00
ptitSeb 1ea0382055 [STATICBUILD] Removed libbsd build dependancy 2024-07-10 15:20:27 +02:00
ptitSeb bd673dc791 [STATICBUILD] Yet another attempt to fix CI build 2024-07-10 14:58:37 +02:00
ptitSeb 4fa00ba283 [STATICBUILD] Another attempt to fix CI build 2024-07-10 14:39:06 +02:00
ptitSeb deef011dbf [STATICBUILD] Attempt to fix CI build 2024-07-10 14:31:47 +02:00
ptitSeb afeecf9d9f [STATICBUILD] Fixed some more errors 2024-07-10 12:49:55 +02:00
ptitSeb e792f00363 This should fix regular build 2024-07-10 12:22:54 +02:00
ptitSeb f7d9dd4824 [STATICBUILD] Try to fix staticbuild and add it to the CI (for #1377) 2024-07-10 12:15:27 +02:00
josch dfc60e8bf1 fix some spelling (#1668) 2024-07-10 11:06:02 +02:00
ptitSeb 655e752c07 [STATICBUILD] Fixed a warning (for #1377) 2024-07-10 10:40:11 +02:00
rajdakin ebdbd1767a [DYNAREC] Fixed ymm0_purge for some instructions (#1664)
* [DYNAREC] Fixed `ymm0_purge` for the first instruction of a block

* [DYNAREC] Also consider barriers as having a pred with `ymm0_out = 0`
2024-07-10 09:45:57 +02:00
Yip Coekjan 4eca49697a Remove the flags adjustment in GO_TRACE for RISC-V 64 (#1663) 2024-07-10 09:45:40 +02:00
Yang Liu 7fa2371bbd [LA64_DYNAREC] Added more opcodes and a minor fix too (#1662)
* [LA64_DYNAREC] Added more opcodes and a minor fix too

* saturation is considered necessary
2024-07-10 09:45:27 +02:00
ptitSeb 60c41cadba Fixed some X11 wrapping (for Interrogation: You will be deceived linux version #1414) 2024-07-10 09:44:12 +02:00
ptitSeb 97769b63ad [RCFILE] Added profile for Death Stranding 2024-07-10 09:43:01 +02:00
ptitSeb bc482e29b0 Started a new dev. cycle 2024-07-10 09:42:00 +02:00
ptitSeb 62695ceed4 Bumped version to v0.3.0 2024-07-09 11:02:43 +02:00
rajdakin 605d5a29c0 Fixes (#1659)
* Replaced some tabs with spaces

* Fixed some signedness warnings

* Added more debug info

* Fixed an improper alignment

* [WRAPPEDWAYLAND] Added return statements to wrappers

* [EMU] [AVX] Fixed some issues

* [ARM DYNAREC] Fixed some minor warnings

* [ARM DYNAREC] Removed unused macro arguments

* [EMU] Fixed a noisy warning

* [ARM DYNAREC] Removed "empty body" warnings

* [EMU] Fixed an opcode in dynarec, non-cosim builds

* [LA64 DYNAREC] Minor warning fixes

* [LA64 DYNAREC] Fixed empty body warnings

* [LA64 DYNAREC] Added parenthesis around assignments in if statements

* [LA64 DYNAREC] Fixed missing parenthesis in macro definitions

* [RV64 DYNAREC] Fixed minor warnings

* [RV64 DYNAREC] Fixed wrong/missing parentheses

* [WRAPPER] Fixed the WaylandClient callback signatures
2024-07-09 08:21:21 +02:00
Yang Liu fdc7e9d1e4 [LA64_DYNAREC] Fixed ADC/SBC usage (#1658) 2024-07-08 21:46:46 +02:00
ptitSeb dcc7ad45bc Added x64 version of libcrypto.so.1.0.0 and libssl.1.0.0 2024-07-08 18:18:04 +02:00
rajdakin 265f153449 [WRAPPED] Added NSS_Init (#1657) 2024-07-08 17:48:23 +02:00
ptitSeb ba9aa3657c Fixed wrapping of some rare opengl functions 2024-07-08 17:45:28 +02:00
ptitSeb 115d666fff [ARM64_DYNAREC] Small optim on some ROL/ROR opcodes 2024-07-08 17:45:27 +02:00
Yang Liu 42ce1a3b61 [LA64_DYNAREC] Added more opcodes (#1656) 2024-07-08 15:17:16 +02:00
Yang Liu a7b912393c [LA64_DYNAREC] Added more opcodes (#1654) 2024-07-08 14:26:28 +02:00
Yip Coekjan e82f17842e Mask rs2 when using bext instruction if rex.w is not set (#1653) 2024-07-08 13:55:32 +02:00
ptitSeb 4838c86ca9 Fixed deb packaging 2024-07-08 10:33:15 +02:00
ptitSeb d6b9fd2860 [VULKAN] Added 1 more extension 2024-07-07 20:17:19 +02:00
Yang Liu 60dac1aa29 Set last_ip to an unclean state at the end of CALL (#1650) 2024-07-07 17:39:54 +02:00
ptitSeb 8dd071bcfa [ARM64_DYNAREC] Fixed a warning 2024-07-07 17:30:35 +02:00
ptitSeb d92d693df3 [ARM64_DYNAREC] Added AVX.66.0F38 B6 opcode 2024-07-07 11:45:02 +02:00
ptitSeb d16bd5104e [ARM64_DYNAREC] Added AVX.F2.0F D0 opcode 2024-07-07 11:29:17 +02:00
ptitSeb d7e8da6321 [ARM64_DYNAREC] Fixed reflect cache for ymm0 2024-07-07 11:28:54 +02:00
ptitSeb aec3fd524a [VULKAN] Added 1 more extension 2024-07-07 10:39:35 +02:00
ptitSeb 14b0323bf6 [ARM64_DYNAREC] Reworked ymm0 propagation 2024-07-07 10:37:51 +02:00
Haichen Wu b482847779 [INTERPRETER] Added 64 66 8D opcode (#1648) 2024-07-06 08:12:16 +02:00
ptitSeb 8c5752de23 [ARM64_DYNAREC] Made AVX/AVX2 enabled by default, but only for ARM64 Dynarec configs 2024-07-05 21:57:20 +02:00
ptitSeb 267bffb0ec [ARM64_DYNAREC] More improvment on YMM handling 2024-07-05 18:53:32 +02:00
ptitSeb 0546216228 [ARM64_DYNAREC] Added Calling Convention as comment in emitter, for reference 2024-07-05 17:21:20 +02:00
ptitSeb a46ea2c07f Cosmetic change 2024-07-05 17:20:48 +02:00
ptitSeb ed4e1ee0ba Put a limit on how much the hardware counter can be shifted 2024-07-05 17:19:11 +02:00
Yip Coekjan 6ac3716594 Should not follow symlinks on file path resolution (#1644) 2024-07-05 11:02:09 +02:00
ptitSeb 42bad3ea6b Added 1 more wrapped funciton to libcups (for #1629) 2024-07-05 09:53:39 +02:00
ptitSeb f9c4eda1fc [VULKAN] Fixed a typo 2024-07-05 09:08:07 +02:00
KreitinnSoftware 688665e730 [VULKAN] Add Wrapped VK_KHR_android_surface (#1643) 2024-07-05 00:23:45 +02:00
ptitSeb a676255231 [VULKAN] Added 1 more extension 2024-07-04 22:48:04 +02:00
ptitSeb d227edeefd Cosmetic change 2024-07-04 20:09:02 +02:00
ptitSeb 34c3e2dab3 [ARM64_DYNAREC] Improved 0F C7 /6 opcode 2024-07-04 20:08:11 +02:00
Yang Liu 2c0bbc06b7 [DYNAREC] Fixed IMUL sign extension issue (#1639) 2024-07-04 18:47:45 +02:00
Yip Coekjan 299551428f Impl sys_getpgrp & sys_getpgid (#1637) 2024-07-04 18:42:22 +02:00
ptitSeb d0ac9c2a5a Fixed 2 warning 2024-07-04 16:36:16 +02:00
Yip Coekjan a69368e855 Wrap some functions for libc (#1635) 2024-07-04 16:31:26 +02:00
Yang Liu 84b0e2f113 [LA64_DYNAREC] Fixed F2 0F 70 PSHUFLW opcode (#1634) 2024-07-04 12:39:57 +02:00
Yang Liu eb695d5553 [RV64_DYNAREC] Added preliminary RVV infra and PXOR opcode for demonstration (#1632)
* [RV64_DYNAREC] Added preliminary RVV infra and PXOR opcode for demonstration

* keep sse_cache_s uint8_t as suggested

* use xor to do the wrap

* revert

* better fallback
2024-07-04 12:39:05 +02:00
LiZhuoheng b5946f3752 [RV64_DYNAREC] modify DF default /4 opcode (#1633)
* [RV64_DYNAREC] modify DF default /4 opcode

* [RV64_DYNAREC] added DF default /4 opcode
2024-07-04 07:59:54 +02:00
LiZhuoheng 371435afd0 [RV64_DYNAREC] Added DF default /4 opcode (#1631)
* [RV64_DYNAREC] Added DF default /4 opcode

* replace tabs to spaces
2024-07-03 14:44:47 +02:00
ptitSeb 0ba46403c6 Detect UnityPlayer.dll to apply strongmem=1 automatically (can be disabled with BOX64_UNITYPLAYER=0) 2024-07-03 11:19:55 +02:00
Diego q cac43a1f5f Updated box64.box64rc (#1630)
added two baldi games, one horror game, 2d superhot, and one game i had to fix for a friend
2024-07-03 08:18:27 +02:00
Yip Coekjan 7771a67abe Add missing func declarations: get_first_jump_addr (#1627) 2024-07-02 15:59:45 +02:00
Yip Coekjan 9cd8812d8b Handle .relr.dyn section (#1626) 2024-07-02 13:47:48 +02:00
ptitSeb 4b0b3fc98a [DYNAREC] Improved cache coherency and internal jump handling, [ARM64_DYNAREC] Improved YMM register tracking 2024-07-02 10:34:37 +02:00
ptitSeb c6afd44c1c Added one more wrapped function to gnutls 2024-07-02 09:29:14 +02:00
Yang Liu dbb84245a0 Wrapped libsqlite3 (#1625)
* Wrapped libsqlite3

* More functions
2024-07-01 18:58:17 +02:00
ptitSeb 15a7c4d8dd [DYNAREC] Reset fpu scratch after Instruction epilog 2024-07-01 15:21:51 +02:00
Yang Liu a842938cfe Wrapped more functions (#1624)
* Wrapped more gtk functions

* Wrapped 1 more gdk3 function

* Wrapped more gnutls functions

* Added generated files
2024-07-01 14:39:54 +02:00
ptitSeb 3f83038061 [DYNAREC] Keep internal jmp table to the end 2024-07-01 10:39:30 +02:00
ptitSeb 01568f8fd3 [ARM64_DYNAREC] Fixed some regression on internal jumps 2024-07-01 10:33:41 +02:00
ptitSeb 1ee4d5aaf4 [ARM64_DYNAREC] Added 64/65 70-7F/EB opcodes 2024-06-30 15:50:16 +02:00
ptitSeb f9b74642a2 {ARM64_DYNAREC] Small optimisation on F3 0F BC/BD opcodes 2024-06-28 18:51:16 +02:00
ptitSeb 401e3a7282 [ARM64_DYNAREC] Fixed printer for DUP opcode 2024-06-28 18:49:32 +02:00
ptitSeb 32b2b388c8 [ARM64_DYNAREC] Added AVX.66.0F38 91/93 opcodes 2024-06-28 10:35:59 +02:00
ptitSeb 013643782f [ARM64_DYNAREC] Fixed AVX.66.0F3A 06/46/21 opcodes 2024-06-28 10:35:11 +02:00
Yang Liu cb064f9e5a [RV64_DYNAREC] Added vector instructions emitter (#1621) 2024-06-27 08:44:11 +02:00
Yang Liu 52c97c47ab [RV64_DYNAREC] Detect vector extension (#1619) 2024-06-27 08:43:49 +02:00
ptitSeb 5f06d066e7 [ARM64_DYNAREC] Improved comment 2024-06-26 11:10:44 +02:00
liuli a7a211fc85 small fix for ROR and ROL (#1618) 2024-06-26 07:23:13 +02:00
KreitinnSoftware 5540601918 Compile Dynarec With ARMv8-A ASM Flags without Hardware Profile on Android Builds Too (#1617) 2024-06-26 07:22:11 +02:00
ptitSeb 22f99601d9 [INTERPRETER] Added 64/65 F3 0F 58 opcode 2024-06-25 18:12:32 +02:00
ptitSeb 2fe2e52249 [ARM64_DYNAREC] Small fixes to 0F C7 /6 opcode 2024-06-25 14:48:03 +02:00
Yang Liu 6caa598dd7 [RV64_DYNAREC] Fixed regression on D9 E5 FXAM opcode (#1616) 2024-06-25 14:19:17 +02:00
ptitSeb aeeb9b719a [COSIM] Added range handling in BOX64_DYNAREC_TEST ([RCFILE] too) 2024-06-24 20:32:16 +02:00
ptitSeb 36f1808615 [INTERPRETER] opcode F1 is valid alson in 64bits 2024-06-24 18:41:10 +02:00
ptitSeb 0ce5f34f8c [INTERPRETER] Added 32bits F1 opcode 2024-06-24 17:58:40 +02:00
ptitSeb 579ae99d1b [ARM64_DYNAREC] Added 0F C7 /6 opcode, with hardware support if present 2024-06-24 17:34:02 +02:00
ptitSeb fa702c0240 Improved CPUID a bit more, adding RDRAND (helps geekbench6 avx2 version) 2024-06-24 16:07:10 +02:00
ptitSeb 34bc807bd5 [ARM64_DYNAREC] Fixed AVX.66.0F38 90/92 opcodes 2024-06-24 16:05:57 +02:00
ptitSeb 71d49badcc Fixed AVX.66.0F38 90-93 opcodes (certain special cases) 2024-06-24 16:05:26 +02:00
ptitSeb 3dfcc278e0 [ARM64_DYNAREC] Minor fix on printer for SMOV/UMOV 2024-06-24 16:04:29 +02:00
ptitSeb e312fa392d [ARM64_DYNAREC] Reworked ymm_zero handling on internal jump 2024-06-23 20:38:54 +02:00
ptitSeb bda28e5882 [TRACE] Print offset in function in hex 2024-06-23 20:38:11 +02:00
ptitSeb 68c2abc429 [DYNAREC] Try to limit UpdateFlags on internal jumps 2024-06-23 20:26:43 +02:00
ptitSeb b0727d6f2b [ARM64_DYNAREC] Some small optims to a few AVX opcodes 2024-06-23 20:23:04 +02:00
ptitSeb c66be063aa Small improvment to 0F BC/BD opcodes ([ARM64_DYNAREC] too) 2024-06-23 20:22:02 +02:00
ptitSeb 1f0165f895 [ARM64_DYNAREC] Fixed printer for MOVI_64 2024-06-23 20:20:58 +02:00
ptitSeb b1ae5dc2b6 [ARM64_DYNAREC] Small optim on 0F BC/BD opcodes 2024-06-23 12:04:42 +02:00
ptitSeb df228f8829 [ARM64_DYNAREC] Fixed an issue with fpuCacheTransform (possible regression) 2024-06-22 20:33:06 +02:00
ptitSeb dc2d54edf2 Added 66 F2/F3 A4 opcode ({DYNAREC] too) 2024-06-22 18:05:03 +02:00
ptitSeb d39c554541 [ARM64_DYNAREC] Small improvement to 0F 5D/5F opcodes 2024-06-22 13:26:58 +02:00
ptitSeb 314b2a5583 [COSIM] Imprroved F2 0F prefixed opcodes 2024-06-22 13:26:14 +02:00
ptitSeb ce30c1179e Improved handling of cpuid leaf 0x80000006 2024-06-22 11:40:35 +02:00
ptitSeb cbb3126b28 [COSIM] Improved handling of AVX.66.0F38 3E/2F opcodes 2024-06-22 11:40:11 +02:00
ptitSeb a3413ba96d [ARM64_DYNAREC] Improved AVX.66.0F38 2E/2F to avoid segfault when mask is null 2024-06-21 21:22:43 +02:00
ptitSeb 2b625e4aa5 Small fix for a signature of a gnutls function 2024-06-21 21:18:49 +02:00
ptitSeb df74626ca2 [RCFILE] Improved hendling of BOX64_NODYNAREC 2024-06-21 21:17:49 +02:00
Yang Liu 10373ca6fc [RCFILE] Added Goat Simulator profile (#1609) 2024-06-21 14:03:25 +02:00
Yang Liu 3dcd08bd4a Wrapped pthread_cond_signal with aligned cond like others (#1608) 2024-06-21 13:08:53 +02:00
Yang Liu a945daf96d [RV64_DYNAREC] Added unaligned support for F0 /5 LOCK SUB opcode (#1607) 2024-06-20 16:20:36 +02:00
Michael Büchler 22116dabc3 Add missing wrappings for winewayland.so (#1599)
* Add missing wrappings for winewayland.so

These were missing on wine-9.9 built with `--enable-win64` and
`--with-wayland=yes` on Ubuntu 24.04 "noble".

Does not work at this point! Now there is a SIGILL during/after mapping
winewayland.so due to a missing zxdg_output_v1 listener.

* wrappedwaylandclient: add zxdg_output_v1 listener

This is used by wine's waylandclient.so. Tested with wine-9.9 regedit
and winecfg.
2024-06-20 08:24:48 +02:00
ptitSeb 5494d95b6b Added a few more symbols, used by latest steam for linux (for #1603) 2024-06-19 21:30:20 +02:00
theofficialgman 9ab686b3e0 switch to maintained Pi-Apps-Coders apt repo (#1605)
closes https://github.com/ptitSeb/box64/issues/1576
2024-06-19 18:39:03 +02:00
ptitSeb 5b24440e8c [ARM64_DYNAREC] Fixed AVX.F2.0F3A F0 opcode 2024-06-19 10:33:49 +02:00
salt431 44deff987c Update arm64_immenc.c (#1602)
combine if (!bitmask || !~bitmask) to (bitmask == 0 || bitmask == ~0ULL) to reduce overhead.

use bitwise operators instead of + operators.
2024-06-19 08:55:01 +02:00
Yang Liu 7273ac0d34 [RV64_DYNAREC] Fixed potential issue of jump_to_next (#1600) 2024-06-18 18:35:35 +02:00
ptitSeb ceb9834a27 [RCFILE] Better profile for Kingdom Rush Origin linux version 2024-06-18 18:23:31 +02:00
ptitSeb 4eebf25f1c Added BOX64_RESERVE_HIGH in rcfile handling 2024-06-18 17:25:32 +02:00
ptitSeb 865ef2ff6e Added 1 more wrapped symbol to libmpg123 2024-06-18 16:59:54 +02:00
ptitSeb 8138ba6ecb [ARM64_DYNAREC] Added a warning if allocating a scratch register after some YMM 2024-06-18 16:23:32 +02:00
ptitSeb f1c0b52677 [ARM64_DYNAREC] Fixed AVX.66.0F 6B opcode 2024-06-18 16:22:57 +02:00
ptitSeb a4cb62d6d6 [ARM64_DYNAREC] Restaured a better way to handle ymm register, now that the traking is improved 2024-06-18 15:58:57 +02:00
ptitSeb e4062c6031 [ARM64_DYNAREC] Fixed AVX.66.0F3A 19/39 opcodes 2024-06-18 15:24:30 +02:00
ptitSeb 08844f31c9 [ARM64_DYNAREC] Better tracking of used ymm (seems redundent with ymm0_sub) 2024-06-18 15:23:46 +02:00
ptitSeb 4dfdba001b [TRACE] Cosmetic change on ymm printout 2024-06-18 15:22:52 +02:00
LiZhuoheng 8dbf982ebe Added more wrapped functions to gmp and idn2 (#1598) 2024-06-18 11:35:09 +02:00
Yang Liu 031255a946 [RV64_DYNAREC] Improved 0F AE opcodes (#1596) 2024-06-18 10:01:54 +02:00
Yang Liu 8dfbe80b41 [LA64_DYNAREC] Added more opcodes (#1597) 2024-06-18 10:01:12 +02:00
Yang Liu 2bcc997e4b [RV64_DYNAREC] Fixed and refined F0 81,83 LOCK prefix opcodes (#1595) 2024-06-18 09:59:33 +02:00
LiZhuoheng 263e79be53 Added more wrapped functions (#1593) 2024-06-18 07:21:25 +02:00
ptitSeb d031a8b423 [ARM64_DYNAREC][COSIM] Do not test atomic operatin, they don't support double execution very well by nature 2024-06-17 22:15:48 +02:00
ptitSeb 7bec96e4b2 [COSIM] Some improvment to avoid segfault in edge cases 2024-06-17 22:15:03 +02:00
Yang Liu 6bb1bacfba Fixed some symbols not found error for libc and libresolv wrapping (#1591) 2024-06-17 18:40:16 +02:00
Yang Liu 95a4aaf8fd [LA64_DYNAREC] Added more opcodes (#1590) 2024-06-17 18:39:01 +02:00
ptitSeb 387c64b74c Fixed usage of getcpu, only enablign that for recent enough glibc (should help #1586) 2024-06-17 16:02:26 +02:00
ptitSeb 4d068eee26 This should fix slatest steam on linux not starting 2024-06-15 09:58:00 +02:00
Yang Liu ece732ba41 [DYNAREC_RV64] Fixed 16bit LOCK ADD issue (#1584) 2024-06-15 09:02:16 +02:00
Yang Liu 8f40dc1a8c Fixed some vulkan wrapper functions (#1585)
* Fixed some vulkan wrapper functions

* Forgot to submit generated files
2024-06-15 09:01:33 +02:00
ptitSeb c9a6d4c05a [ARM64_DYNAREC] Added AVX.66.0F38 8C/9C/9F/BE opcodes 2024-06-14 11:26:49 +02:00
ptitSeb a66b4e257a [ARM64_DYNAREC] Added AVX.F2.0F 7C/F0 opcodes 2024-06-14 11:25:50 +02:00
ptitSeb 3796805d98 [ARM64_DYNAREC] Added faked F3 0F AE /5 unsupported opcode 2024-06-14 11:24:59 +02:00
ptitSeb a3d09e95d5 Fixed an issue with BOX64_RDTSC_1GHZ being always active 2024-06-13 15:51:15 +02:00
ptitSeb 626846c37b [ANDROID] This should fix android build 2024-06-13 11:32:58 +02:00
ptitSeb 8bf1ac6577 [ARM64_DYNAREC] Added AVX.66.0F 7C opcode 2024-06-13 10:49:49 +02:00
ptitSeb 58c0bce4cf More work on RDTSC emulation 2024-06-13 10:22:33 +02:00
LiZhuoheng 3a82dc6aad Added more wrapped function to libunistring2 (#1582)
* Added more wrapped function to libunistring2

* add wrapper.c
2024-06-13 07:46:27 +02:00
ptitSeb e42b9e2866 [WAYLAND] Wrapped one more listener 2024-06-12 20:10:46 +02:00
ptitSeb 8a85acff32 Better wrapping for libwayland-client, removed the x64 versions of the libs, using wrapped one instead 2024-06-12 19:41:06 +02:00
ptitSeb b450ea24a2 Added the new x64 libs 2024-06-12 16:05:47 +02:00
ptitSeb 4fa92dc069 Removed wrapped libwayland-client and libwayland-cursor, the wrapping is wrong, and use native libs instead 2024-06-12 16:01:01 +02:00
LiZhuoheng 61a80c9b2d Wrapped libhogweed6 (#1579) 2024-06-12 15:27:37 +02:00
ptitSeb bcfd0f7ea3 Added one structure to libwayland-clinet and auto bridges all current interfaces 2024-06-11 18:02:02 +02:00
ptitSeb c404b3e0ab Fixed libudev.so.0 wrapping, removed functions from libudev.so.1 2024-06-11 16:41:44 +02:00
ptitSeb b246133b3b [ARM64_DYNAREC] Added AVX.0F 77 256bits opcode 2024-06-11 15:07:10 +02:00
ptitSeb 5b28d7bc03 [INTERPRETER] Added AVX.0F 77 256bits opcode 2024-06-11 15:06:50 +02:00
ptitSeb 8adaefcdb9 Remove and obsolete comment 2024-06-11 15:06:19 +02:00
ptitSeb e64b4d5c04 [ARM64_DYNAREC] Fixed AVX.66.0F E1-E3 opcodes and Added AVX.66.0F C6 and AVX.0F 17 opcodes 2024-06-11 13:33:24 +02:00
ptitSeb 59caccfeae [ARM64_DYNAREC] Added AVX.66.0F38 02/0B opcodes 2024-06-11 10:32:53 +02:00
ptitSeb bbd3333b5f [ARM64_DYNAREC] Fixed another issue with Ymm value when updating flags on internal jump 2024-06-11 10:21:52 +02:00
ptitSeb 1ce7f32b5d [ARM64_DYNAREC] Added AVX.66.0F38 5A opcode 2024-06-11 10:12:24 +02:00
ptitSeb 95f18dbf15 [ARM64_DYNAREC] Fixed another issue with Ymm0 mask and reset_cache on internal jump 2024-06-11 10:11:55 +02:00
LiZhuoheng 9ed2e3bbf2 Wrapped libunistring2 (#1577) 2024-06-11 08:02:11 +02:00
ptitSeb 8b3cd23045 [ARM64_DYNAREC] Added AVX.66.0F38 90/92 opcodes and added AVX.66.0F38 04 opcode 2024-06-10 15:18:06 +02:00
ptitSeb 072241eb10 [ARM64_DYNAREC] Fixed AVX.66.0F3A 00/01 opcodes 2024-06-10 15:17:03 +02:00
ptitSeb 84a8500323 [ARM64_DYNAREC] Fixed 256bits version of AVX.66.0F D1/D2/D3 opcodes 2024-06-10 15:15:57 +02:00
ptitSeb a8911fc979 [ARM64_DYNAREC] Cosmetic change 2024-06-10 15:14:55 +02:00
Diego q 04ba0b2f67 Update README.md (#1573)
Added Strong memory mode to the hint under unity games because freezing is also a common issue on PI-4 and PI-5 for games, also added the mention of PI-5 on the hint because the issues aren't limited to the PI-4 and also apply to the Pi-5
2024-06-09 22:49:35 +02:00
Diego q d1e5bc5c19 Update README.md (#1572)
Usage link was broken so i fixed it
2024-06-09 21:23:36 +02:00
ptitSeb 38364ef07f [COSIM] Fixed 66 48 xx type of opcodes 2024-06-09 17:45:36 +02:00
ptitSeb b25d8db994 [ARM64_DYNAREC] Fixed an issue when not purging Ymm0 on internal jump with less Ymm0 2024-06-09 17:12:06 +02:00
ptitSeb 989ed95891 [ARM64_DYNAREC] Fixed AVX.66.0F38 28 opcode 2024-06-09 17:05:33 +02:00
ptitSeb d15ffc48a3 [ARM64_DYNAREC] Fixed AVX.66.0F 7F opcode 2024-06-09 16:56:15 +02:00
ptitSeb 06df8c7bed [DYNAREC] Another fix for YMM Zero'd upper reg tracking 2024-06-09 14:51:41 +02:00
ptitSeb 950241d52f [ARM64_DYNAREC] Added AVX.66.0F38 41/8E/9B, AVX.66.0F3A 06 and AVX.66.0F F6 opcodes 2024-06-08 21:31:11 +02:00
ptitSeb a147c12f72 [ARM64_DYNAREC] Another fix for YMM selection on High registry pressure cases 2024-06-08 16:51:51 +02:00
ptitSeb 874828c2ac [ARM64_DYNAREC] Added AVX.66.0F 50/C2, AVX.66.0F3A 0D, AVX.66.0F38 16/28/29/2B/36/AC/BA and AVX.F2.0F 51 opcodes 2024-06-08 15:21:55 +02:00
ptitSeb 3369e5e755 Remove a warning on known unhandled arch_prctl commands 2024-06-08 15:19:46 +02:00
ptitSeb 9b3930ea62 [ARM64_DYNAREC] Small optim on 66 0F 50 opcode 2024-06-08 15:19:01 +02:00
ptitSeb 987d0db806 [INTERPRETER] Fixed AVX.66.0F 50 opcode not handling vex.l 2024-06-08 15:18:34 +02:00
ptitSeb 97530e4095 [ARM64_DYNAREC] Added AVX.66.0F E6, AVX.66.0F38 98 and fixed AVX.F2.0F E6 opcodes 2024-06-08 11:53:35 +02:00
ptitSeb 4c285d4d8a [ARM64_DYNAREC] Fixed an issue when purging an YMM that is used in the same opcode 2024-06-08 11:52:00 +02:00
ptitSeb cd5fbc1492 Added 2 wrapped function to libglib2 2024-06-08 09:50:10 +02:00
ptitSeb 2e379300a6 [RCFILE] Added a few more profiles 2024-06-07 20:02:57 +02:00
ptitSeb 65c19d073c Only expose xsave extension if avx is used 2024-06-07 17:04:14 +02:00
ptitSeb eb013f3492 [DYNAREC] This should fix RV64 and LA64 builds 2024-06-07 14:30:36 +02:00
ptitSeb b2fd651abe [ARM64_DYNAREC] Fixed YMM cache handling, espcially in high pressure regs cases 2024-06-07 13:34:22 +02:00
xctan d4b02e6a3f [RV64_DYNAREC] Fixed sign extension of 8-bit immediate in 66 opcodes (#1568) 2024-06-07 11:37:29 +02:00
ptitSeb 537cb65f26 [ARM64_DYNAREC] Added BMI.0F38 F2, F3/1 opcodes 2024-06-07 10:25:14 +02:00
ptitSeb f61367fc9a [ARM64_DYNAREC] That's just cosmetic... 2024-06-07 10:24:15 +02:00
LiZhuoheng 46e0505336 Wrapped libnettle8 (#1567) 2024-06-07 10:22:03 +02:00
xctan 75004d0b56 [RV64_DYNAREC] Fixed some opcodes caught by cosim (#1561)
* [RV64_DYNAREC] Fixed emit_shrd16c

* [RV64_DYNAREC] Fixed BSWAP Gw

* [RV64_DYNAREC] Fixed 32 bit RCL/RCR Ed, 1

* [RV64_DYNAREC] Fixed 32 bit BTR

* [RV64_DYNAREC] Fixed 32 bit SHLD

* [RV64_DYNAREC] Fixed 32 bit SHLD again

* [RV64_DYNAREC] Fixed 16 bit constant SHLD again

* [RV64_DYNAREC] Fixed 16-bit BTC

* [RV64_DYNAREC] Fixed 32-bit rotates using Zbb extension

* [RV64_DYNAREC] Fixed 16-bit SHLD opcode

* [RV64_DYNAREC] Fixed the mask of LAHF opcode

* [RV64_DYNAREC] Fixed LAHF again and handled OF2 before cosim

* [RV64_DYNAREC] Fixed XADD Eb, Gb when Eb == Gb

* [RV64_DYNAREC] Fixed XADD Ew, Gw when Ew == Gw

* [RV64_DYNAREC] Fixed zero extension of 32 bit Ed operand

* [RV64_DYNAREC] Fixed XADD Eb, Gb again for AH, BH, CH, DH

* [RV64_DYNAREC] Fixed various 16-bit immediate extension
2024-06-06 17:32:49 +02:00
ptitSeb 0dc5761ca6 [INTERPRETER] Added suport for F16C extension (linked to AVX flag) ([ARM64_DYNAREC] too) 2024-06-06 16:48:05 +02:00
ptitSeb df47fb5be8 Disable F16C for now, it's not ready yet 2024-06-06 13:59:09 +02:00
ptitSeb 0cedc70eb3 [ARM64_DYNAREC] Added a new small batch of AVX/BMI2 opcodes 2024-06-06 13:47:47 +02:00
ptitSeb 1612687acf [ARM64_DYNAREC] Fixed VCMPSS opcode 2024-06-06 13:47:14 +02:00
LiZhuoheng 67d587cd9b Wrapped libtasn1-6 (#1563) 2024-06-06 09:48:31 +02:00
LiZhuoheng 9e97e96b87 Wrapped libp11-kit (#1562) 2024-06-06 08:12:34 +02:00
ptitSeb 79c1ad1431 [ARM64_DYNAREC] Added a few more AVX opcodes 2024-06-05 20:40:26 +02:00
ptitSeb c0ebe09521 Added an AVX test (not on Android, needs to be build there) 2024-06-05 19:44:25 +02:00
ptitSeb b568cc529e [ARM64_DYNAREC] Added a bunch of AVX ocpodes and some fixes too 2024-06-05 19:44:02 +02:00
ptitSeb dc8e24c7b7 [INTERPRETER] Fixed VCMP opcode familly, that needs more cases on than con-vex CMP familly 2024-06-05 15:03:44 +02:00
ptitSeb ba411303e9 [DYNAREC] Improved handling of the Ymm0 attribute 2024-06-05 10:44:31 +02:00
ptitSeb 8848bc2e7f [ARM64_DYNAREC] Small optim for AVX.66.0F D7 opcode 2024-06-05 09:51:03 +02:00
Yang Liu f7798f361a [LA64_DYNAREC] Fixed LOCK DEC opcode (#1560) 2024-06-04 18:53:32 +02:00
ptitSeb 6a25427cb6 [DYNAREC] Small improvment to Dynarec infrastructure 2024-06-04 11:11:17 +02:00
ptitSeb a6c283f4ce [ARM64_DYNAREC] Added AVX.0F 16/50/53/C2 opcodes 2024-06-03 22:11:12 +02:00
Yang Liu 48bb907d2d [LA64_DYNAREC] Added more opcodes (#1558) 2024-06-03 22:04:28 +02:00
Yang Liu c2ce5d5557 [LA64_DYNAREC] Fixed emit_or16 (#1559) 2024-06-03 22:04:12 +02:00
ptitSeb 0d30fe90f8 [ARM64_DYNAREC] Added AVX.66.0F 5A/5C-5F/D0-D3 2024-06-03 21:29:14 +02:00
ptitSeb c434cef45e [ARM64_DYNAREC] Cosmetic change 2024-06-03 21:28:16 +02:00
ptitSeb d01970f731 [ARM64_DYNAREC] Added AVX.66.0F3A 02/08-09/0E/14/20/40/4A-4B opcodes 2024-06-03 20:28:32 +02:00
ptitSeb bb9beb75d1 [INTERPRETER] Fixed name in comment of an opcode 2024-06-03 20:28:32 +02:00
xctan ad3a9e6c55 [RV64_DYNAREC] Added more MMX opcodes and some optimizations too (#1557)
* [RV64_DYNAREC] Added 0F 38 0B PMULHRSW opcode

* [RV64_DYNAREC] Added 0F E4 PMULHUW opcode

* [RV64_DYNAREC] Added 0F F4 PMULUDQ opcode

* [RV64_DYNAREC] Added 0F F6 PSADBW opcode

* [RV64_DYNAREC] Added 0F 38 08 PSIGNB opcode

* [RV64_DYNAREC] Optimized 66 0F 38 08 PSIGNB opcode

* [RV64_DYNAREC] Added 0F 38 0A PSIGND opcode

* [RV64_DYNAREC] Optimized 66 0F 38 0A PSIGND opcode

* [RV64_DYNAREC] Added 0F 38 09 PSIGNW opcode

* [RV64_DYNAREC] Optimized 66 0F 38 09 PSIGNW opcode

* [RV64_DYNAREC] Added 0F F2 PSLLD opcode

* [RV64_DYNAREC] Added 0F F3 PSLLQ opcode

* [RV64_DYNAREC] Added 0F F1 PSLLW opcode

* [RV64_DYNAREC] Fixed 0F F1/F2 PSLLW/PSLLD opcode

* [RV64_DYNAREC] Added 0F E1 PSRAW opcode

* [RV64_DYNAREC] Added 0F D2 PSRLD opcode

* [RV64_DYNAREC] Added 0F D3 PSRLQ opcode

* [RV64_DYNAREC] Added 0F D1 PSRLW opcode

* [RV64_DYNAREC] Added 0F F8 PSUBB opcode

* [RV64_DYNAREC] Added 0F FA PSUBD opcode

* [RV64_DYNAREC] Added 0F FB PSUBQ opcode

* [RV64_DYNAREC] Added 0F E8 PSUBSB opcode and optimized 0F E9 PSUBSW opcode

* [RV64_DYNAREC] Added 0F D8 PSUBUSB opcode
2024-06-03 17:42:23 +02:00
ptitSeb 9a30b65180 [ARM64_DYNAREC] Added AVX.66.0F38 17/20-25/29/37-40/45-47/78-79/99/AA/AE-AF/BB-BD/F7 opcodes 2024-06-03 17:33:55 +02:00
ptitSeb cb548fe1fa [INTERPRETER] Fixed name in comment of an opcode 2024-06-03 17:31:17 +02:00
ptitSeb 0a8f049ced [ARM64_DYNAREC] Added AVX.66.0F38 19/1A and AVX.66.0F3A 22 opcodes 2024-06-03 14:43:21 +02:00
ptitSeb 890809069e [ARM64_DYNAREC] Fixed AVX.F2/F3.0F 5D/5F opcodes 2024-06-03 14:42:21 +02:00
ptitSeb ca9a6fe019 [ARM64_DYNAREC] Empty regs needs to be fetched last (again) 2024-06-03 13:54:49 +02:00
ptitSeb 94ccae727b [ARM64_DYNAREC] Fixed AVX Cache transform between internal jump points 2024-06-03 13:46:30 +02:00
ptitSeb 001e77952e [COSIM] Added more helpers to avoid segfault on rare cases 2024-06-03 13:45:55 +02:00
ptitSeb ac6a453833 [ARM64_DYNAREC] Empty register needs to be fetched last 2024-06-03 12:45:33 +02:00
ptitSeb 307915130c [INTERPRETER] Fixed VZEROUPPER opcode 2024-06-03 12:45:05 +02:00
Romain TISSERAND 3d225ef908 Try to fix mmap64 already defined error in custommem.c (#1552) 2024-06-03 08:07:11 +02:00
ptitSeb 1c9123637a [ARM64_DYNAREC] Added AVX.F3.0F 52, AVX.66.0F E4 and AVX.0F 52 opcodes 2024-06-02 20:31:32 +02:00
ptitSeb f1f690552f [ARM64_DYNAREC] Added AVX.66.0F38 08-0A/1C-1E/30-35/58/59/90/92/A8/A9/B8/B9 opcodes 2024-06-02 20:10:00 +02:00
ptitSeb 57dcf3401c [ARM64_DYNAREC] Remove parasite typo to fix build 2024-06-02 18:41:17 +02:00
ptitSeb 9e5df7957e [INTERPRETER] Added missing FMA opcodes, and fixed some existing ones 2024-06-02 17:26:26 +02:00
ptitSeb ca63389ea3 [INTERPRETER] Fixed opcode name in comment 2024-06-02 16:45:35 +02:00
ptitSeb 7b7ee070b9 [ARM64_DYNAREC] Added AVX.66.0F D6/E5/E7/F5 opcodes 2024-06-02 16:32:16 +02:00
ptitSeb 3aee16e9a0 [ARM64_DYNAREC] Added AVX.66.0F3A 00/01/04/05/0A/0B/46 opcodes 2024-06-02 15:18:04 +02:00
ptitSeb 06cb3624e2 [ARM64_DYNAREC] Fixed handling of YMM0 on forward jump 2024-06-02 13:56:13 +02:00
ptitSeb a1f83418b9 [COSIM] Fixed YMM handling in cosim, seems to work better now 2024-06-02 13:44:38 +02:00
ptitSeb e5a32ea129 [ARM64_DYNAREC] Added AVX.66.0F 60-63/67-6A/71 opcodes 2024-06-02 13:13:01 +02:00
ptitSeb eb209abe62 [ARM64_DYNAREC] Don't use fix scratch for x87 conversion, it might conflict with YMM handling 2024-06-02 13:12:06 +02:00
ptitSeb 13551fd410 [INTERPRETER] Small cosmetic changes on raz of ymm 2024-06-02 13:11:13 +02:00
ptitSeb 2493706315 [COSIM] Improved reliability with AVX (but there is still something wrong there) 2024-06-02 13:10:50 +02:00
ptitSeb b49273c079 [INTERPRETER] Added FMA cpu extension (linked to BOX64_AVX=2) 2024-06-02 11:26:16 +02:00
ptitSeb 7c1b161277 [ARM64_DYNAREC] Fixed YMM COSIM refreshing on each steps 2024-06-02 11:26:16 +02:00
ptitSeb d8a1dcc1b4 [COSIM] Fixed issue with YMM printing on difference 2024-06-02 11:26:16 +02:00
Yang Liu f44d60c58f [LA64_DYNAREC] Added more opcodes (#1549)
* [LA64_DYNAREC] Added more opcodes

* fastnan handling and fixed PALIGNR...
2024-06-02 10:25:57 +02:00
ptitSeb dc71840a5a [ARM64_DYNAREC] Added AVX.66.0F3A 21 and fixed a bunch of issues 2024-06-02 09:15:37 +02:00
ptitSeb 07b17cd0f6 [INTERPRETER] Small fixes for some rare case of AES with serc==dest 2024-06-02 08:41:29 +02:00
Yang Liu cf37e8ea83 [LA64_DYNAREC] Added more opcodes and fixed ADC opcode (#1548) 2024-06-01 20:08:33 +02:00
ptitSeb 5384489702 [ARM64_DYNAREC] Added AVX.F2.0F 58-5A/5C-5F opcodes 2024-06-01 19:38:28 +02:00
ptitSeb 1ad69d785f [ARM64_DYNAREC] Added AVX.66.0F C4/C5/D7 opcodes 2024-06-01 19:22:39 +02:00
ptitSeb ef3acd9f33 [ARM64_DYNAREC] Added BMI.F2.0F38 F7 opcode 2024-06-01 19:12:18 +02:00
ptitSeb 083b42fead [ARM64_DYNAREC] Added AVX.66.0F 10-17/29/29/2B/2E/2F/54-59/74-76/7E opcodes 2024-06-01 19:04:50 +02:00
ptitSeb c6814a6f97 [ARM64_DYNAREC] Added AVX.0F 28/29/2B/2E/2F/54-56/5A-5F opcodes, plus various small fixes 2024-06-01 18:03:24 +02:00
Yang Liu 9dbd7fc7e0 [INTERP] Rework on the 16b emulation for LA64 (#1547)
* [INTERP] Rework on the 16b emulation for LA64

* fix compiler issue
2024-06-01 17:14:23 +02:00
ptitSeb a79eff3b0d [ARM64_DYNAREC] Added AVX.F3.0F 10-12/16/2A/2C/2D/58-5F opcodes, plus a few other fixes 2024-06-01 15:32:37 +02:00
ptitSeb a89d7a2e2a [ARM64_DYNAREC] Added AVX.F2.0F 10-12/2A/2C/2D opcodes 2024-06-01 14:28:32 +02:00
ptitSeb 0336f6a987 [ARM64_DYNAREC] Added a few 67 prefixed opcodes 2024-06-01 13:33:20 +02:00
ptitSeb 6d68975ba5 [ARM64_DYNAREC] Added ADX RORX opcode 2024-06-01 13:17:50 +02:00
ptitSeb 2b07fd7c6a [ARM64_DYNAREC] Added AVX.66.0F3A 38/39 opcodes 2024-06-01 13:10:53 +02:00
ptitSeb f8cc423f3d [ARM64_DYNAREC] Added AVX.66.0F 72/7F/F8-FE 2024-06-01 12:37:37 +02:00
ptitSeb f4667fa3cf [ARM64_DYNAREC] Added AVX.F3.0F 7E opcode 2024-06-01 12:05:38 +02:00
Yang Liu d8f929755a Detects extensions even if dynarec is disable at runtime (#1546) 2024-06-01 11:55:45 +02:00
ptitSeb 031685e0a7 [ARM64_DYNAREC] Added AVX.66.0F38 00/DC-DF opcodes 2024-06-01 11:48:09 +02:00
ptitSeb 9f260eb86c [ARM64_DYNAREC] Fix issue with 66 0F 38 DC-DF when rare case of dest==src 2024-06-01 11:38:32 +02:00
ptitSeb 75878b24cd [ARM64_DYNAREC] Added AVX.F3.0F 7F opcode 2024-06-01 10:35:24 +02:00
ptitSeb fe0425eb80 [ARM64_DYNAREC] Added a couple of AVX.66.0F3A opcodes, and fixed some sse/avx function helpers 2024-06-01 09:49:35 +02:00
ptitSeb 453003da23 [ARM64_DYNAREC] Added some AVX.66.0F opcodes 2024-06-01 09:02:54 +02:00
Yang Liu eec08973bf [LA64_DYNAREC] Added LOCK CMPXCHG unaligned version (#1545) 2024-06-01 08:12:25 +02:00
Yang Liu c65f8da90f [RV64_DYNAREC] Fixed LOCK CMPXCHG unaligned version (#1544) 2024-06-01 07:52:03 +02:00
Yang Liu 2970ed5bfd [LA64_DYNAREC] Fixed 0F C2 CMPPS opcode (#1543) 2024-05-31 23:27:02 +02:00
ptitSeb bfebcba431 [ARM64_DYNAREC] Added a bunch of AVX/BMI2/ADX opcodes 2024-05-31 22:33:12 +02:00
ptitSeb dde85b761b [INTERPRETER] Added BMI1, BMI2 and ADX extensions 2024-05-31 15:59:11 +02:00
ptitSeb 34809e48d8 [ARM64_DYNAREC] Some fixes to AVX opcodes 2024-05-31 15:51:07 +02:00
xctan 6749c2d1a6 [RV64_DYNAREC] Added more MMX opcodes and some optimizations too (#1542)
* [RV64_DYNAREC] Added 0F 38 06 PHSUBD opcode

* [RV64_DYNAREC] Added 0F 38 07 PHSUBSW opcode

* [RV64_DYNAREC] Added 0F 38 05 PHSUBW opcode

* [RV64_DYNAREC] Added 0F C4 PINSRW opcode

* [RV64_DYNAREC] Added 0F 38 04 PMADDUBSW opcode

* [RV64_DYNAREC] Added 0F EE PMAXSW opcode

* [RV64_DYNAREC] Optimized SSE packed min/max

* [RV64_DYNAREC] Added 0F DE PMAXUB opcode

* [RV64_DYNAREC] Added 0F EA PMINSW opcode

* [RV64_DYNAREC] Added 0F DA PMINUB opcode

* [RV64_DYNAREC] Optimized 0F D9 PSUBUSW opcode

* [RV64_DYNAREC] Added 0F D7 PMOVMSKB opcode

* [RV64_DYNAREC] Optimized (66) 0F D7 PMOVMSKB opcode

* [RV64_DYNAREC] Switched to the simpler implementation for PMOVMSKB
2024-05-31 14:09:10 +02:00
ptitSeb 7eb24ff514 [ARM64_DYNBAREC] Added AVX.66.0F38 2C-2F opcodes 2024-05-30 21:26:10 +02:00
ptitSeb e367a2bcc9 [ARM64_DYNAREC] Added AVX.66.0F 64-66 opcodes 2024-05-30 20:25:01 +02:00
ptitSeb a02283264a [ARM64_DYNAREC] Fixed AVX.0F 12/13 opcodes 2024-05-30 20:24:34 +02:00
ptitSeb 7a7e9ee9af [ARM64_DYNAREC] Added AVX.0F 10-13 opcodes 2024-05-30 20:07:29 +02:00
ptitSeb b7f25a48c2 [ARM64_DYNAREC] Added AVX.0F 14/15/77/AE opcodes 2024-05-30 19:00:41 +02:00
ptitSeb 4477aa3159 [ARM64_DYNAREC] Added AVX.66.0F3A 15/16/17 opcodes 2024-05-30 18:40:07 +02:00
ptitSeb 4fd23c752c [ARM64_DYNAREC] Added AVX.66.0F 6B opcode 2024-05-30 18:21:16 +02:00
ptitSeb 60b625bc0f [ARM64_DYNAREC] Added AVX.66.F3A 19 opcodes and some various avx helper fixes 2024-05-30 18:13:01 +02:00
ptitSeb d1703b9bc0 [ARM64_DYNAREC] Added AVX.66.0F 5B/6F opcodes 2024-05-30 17:39:46 +02:00
ptitSeb eb9da7417f [RV64_DYNAREC] Fixed build 2024-05-30 17:16:28 +02:00
ptitSeb 782f497b20 [ARM64_DYNAREC] Added AVX.0F 58-59 opcodes, and fixed AVX.66.0F3A 18 opcode 2024-05-30 17:14:05 +02:00
ptitSeb 003a83b40b [ARM64_DYNAREC] Added AVX.66.0F38 18 and AVX.66.0F3A 0C opcodes 2024-05-30 16:53:39 +02:00
ptitSeb 2f8d28e7da [ARM64_DYNAREC] Added AVX.0F 57 opcode 2024-05-30 16:08:20 +02:00
ptitSeb fa591589c7 [ARM64_DYNAREC] Added AVX.66.0F3A 18 opcode 2024-05-30 15:47:19 +02:00
ptitSeb f0ea459c57 [ARM64_DYNAREC] That first avx opcode now is 256bits enabled 2024-05-30 15:17:13 +02:00
xctan f3d733c3ff [RV64_DYNAREC] Added more MMX opcodes and some optimizations too (#1539)
* [RV64_DYNAREC] Added 0F DF PANDN opcode

* [RV64_DYNAREC] Added 0F E0 PAVGB opcode

* [RV64_DYNAREC] Added 0F E3 PAVGW opcode

* [RV64_DYNAREC] Added 0F 74 PCMPEQB opcode

* [RV64_DYNAREC] Added 0F 76 PCMPEQD opcode

* [RV64_DYNAREC] Added 0F 64 PCMPGTB opcode

* [RV64_DYNAREC] Added 0F 66 PCMPGTD opcode and optimized 66 0F 66 PCMPGTD opcode

* [RV64_DYNAREC] Added 0F 65 PCMPGTW opcode

* [RV64_DYNAREC] Added 0F C5 PEXTRW opcode

* [RV64_DYNAREC] Added 0F 38 02 PHADDD opcode

* [RV64_DYNAREC] Optimized packed saturate add/sub

* [RV64_DYNAREC] Added 0F 38 03 PHADDSW opcode

* [RV64_DYNAREC] Added 0F 38 01 PHADDW opcode
2024-05-30 14:35:27 +02:00
LiZhuoheng 19ca78769f Wrapped libssh2 (#1538)
* Wrapped libssh2

* Add more libssh2 wrapped functions
2024-05-30 14:34:08 +02:00
ptitSeb 3e5784cbc5 [ARM64_DYNAREC] Added a fisrt 128bits only AVX opcode 2024-05-30 12:12:45 +02:00
xctan 98d9f36f9c Added more MMX opcodes and some optimizations too (#1537)
* [RV64_DYNAREC] Added 0F DD PADDUSW opcode and optimized 66 0F DD PADDUSW opcode

* [RV64_DYNAREC] Added 0F 3A 0F PALIGNR opcode

* [RV64_DYNAREC] Optimized 66 0F 3A 0F PALIGNR opcode
2024-05-30 10:54:48 +02:00
ptitSeb 22bc6872f4 [INTERPRETER] Last batch of avx/avx2 opcode 2024-05-29 16:36:43 +02:00
ptitSeb f6fe84afad [INTERPRETER] Added more avx/avx2 opcodes, and fixed vpxor 2024-05-29 15:14:26 +02:00
ptitSeb 4744534fc9 [INTERPRETER] Moar avx/avx2 opcodes 2024-05-29 12:09:21 +02:00
ptitSeb af05d7439f [INTERPRETER] yet more avx/avx2 opcodes 2024-05-29 10:53:38 +02:00
ptitSeb 6e22f4fd6d Added one xslt wrapped constant (for #1534) 2024-05-29 08:39:52 +02:00
ptitSeb 0e3d92148b Added a few libc wrapped function (for #1517 and #1531) 2024-05-29 08:26:18 +02:00
ptitSeb 06cf6d2ecc [INTERPRETER] and a bit more avx/avx2 opcodes 2024-05-28 22:42:12 +02:00
ptitSeb 7b5654eea4 [INTERPRETER] still more avx/avx2 opcodes 2024-05-28 22:09:50 +02:00
ptitSeb 503eb41939 [INTERPRETER] more and more avx/avx2 opcodes 2024-05-28 19:55:15 +02:00
ptitSeb a77db3c6a5 [INTERPRETER] Even more avx/avx2 opcodes, all the mov and more 2024-05-28 18:27:32 +02:00
ptitSeb 4e0889469a [INTERPRETER] Even more avx/avx2 opcodes, and a fix for android builds 2024-05-28 16:50:51 +02:00
xctan 7c5bf62fc0 [RV64_DYNAREC] Added more MMX opcodes and some optimizations too (#1535)
* [RV64_DYNAREC] Added 0F F7 MASKMOVQ opcode

* [RV64_DYNAREC] Added 0F 38 1C PABSB opcode

* [RV64_DYNAREC] Added 0F 38 1E PABSD opcode

* [RV64_DYNAREC] Added 0F 38 1D PABSW opcode

* [RV64_DYNAREC] Added 0F 63 PACKSSWB opcode

* [RV64_DYNAREC] Added 0F FC PADDB opcode

* [RV64_DYNAREC] Added 0F D4 PADDQ opcode

* [RV64_DYNAREC] Added 0F EC PADDSB opcode and optimized 66 0F EC PADDSB opcode

* [RV64_DYNAREC] Added 0F DC PADDUSB opcode and optimized 66 0F DC PADDUSB opcode
2024-05-28 15:04:41 +02:00
ptitSeb b79f86b8d1 [INTERPRETER] More avx/avx2 opcodes 2024-05-28 14:55:17 +02:00
ptitSeb b9f5929439 [INTERPRETER] More avx, avx2 and vaes opcodes 2024-05-28 10:42:41 +02:00
ptitSeb 3dc396a647 Fixed cpuid leaf d, component 2 (fixes wine 9.6+ not booting) 2024-05-27 16:50:26 +02:00
ptitSeb c358bf448f Fixed a warning 2024-05-27 14:58:34 +02:00
ptitSeb abd1d56d7f Correct hadnlign of upper 32bits value of mask for xsave/xrstor 2024-05-27 14:57:05 +02:00
ptitSeb 22b9c16351 [ARM64_DYNAREC] Added faked 0F C7 /4 opcode to get bigger dynablock 2024-05-27 14:56:27 +02:00
ptitSeb 0131958136 [INTERPRETER] Added more avx opcodes 2024-05-27 14:51:08 +02:00
ptitSeb 9f70767acf [ARM64_DYNAREC] Fixed some SHA1 opcode when source is same as dest 2024-05-27 13:45:35 +02:00
ptitSeb bdeb8d7ee2 [ARM64_DYNAREC] Some fixes to opcode when src is same as dest 2024-05-27 13:14:22 +02:00
ptitSeb de831ee5ac [INTERPRETER] Some fixes when opcode use with same reg as src and dest 2024-05-27 13:13:52 +02:00
ptitSeb da1cb42f2a [ARM64_DYNAREC] Fixed some pcmp[ei]stri flags 2024-05-27 13:07:01 +02:00
ptitSeb 2c366ef4bd Just clear AF flags on pcmp[i/e]stri helper 2024-05-27 13:06:28 +02:00
ptitSeb bc0f31407f [INTERPRETER] Added some more avx opcodes 2024-05-27 12:48:05 +02:00
ptitSeb 0d755e610b More avx infrastructure 2024-05-27 12:21:57 +02:00
ptitSeb 55ee7fcc33 [INTERPRETER] Some fixes and small refactor on avx handling 2024-05-27 11:13:15 +02:00
ptitSeb 10200d7b55 [INTERPRETER] Added avx (66 0F 38) 00 opcode 2024-05-27 10:23:56 +02:00
ptitSeb 1eab6a0c8e [INTERPRETER] Added avx (66 0F 3A) 0F opcode 2024-05-27 10:08:46 +02:00
ptitSeb fc2d50c7d3 [INTERPRETER] Added avx (F3 0F) 7F opcode 2024-05-27 10:02:33 +02:00
ptitSeb aaed0364bd [INTERPRETER] Added avx (66 0F 3A) 44 opcode 2024-05-27 09:53:49 +02:00
ptitSeb 9e0139f3c3 Small cleanup in my_cpuid 2024-05-27 09:53:29 +02:00
ptitSeb ec3c3b7eed [INTERPRETER] Added avx (66 0F) 6F ocpode 2024-05-27 09:11:50 +02:00
ptitSeb c67632722b [INTERPRETER] Added avx (66 0F) 6C/6D opcode and even more fixes to some avx opcodes 2024-05-26 16:48:26 +02:00
ptitSeb 580fbf47b2 [INTERPRETER] Added avx (66 0F) DB opcode and more fixes to some avx opcodes 2024-05-26 16:11:26 +02:00
ptitSeb 4bffdce8af [INTERPRETER] Added avx (66 0F) EB opcode and fixed other avx opcodes 2024-05-26 15:50:43 +02:00
ptitSeb f22e9bf1d2 [INTERPRETER] Added avx (66 0F) 64/65/66/72/73/EF opcodes 2024-05-26 15:20:52 +02:00
ptitSeb 95b516127a [INTERPRETER] Added avx (F3 0F) 6F and (66 0F) 70 2024-05-26 12:57:59 +02:00
ptitSeb da7474b1de Added 67 66 83 opcodes ([ARM64_DYNAREC] too) 2024-05-26 11:03:32 +02:00
ptitSeb 27aa9011ce Fixed xrstor helper 2024-05-26 10:42:16 +02:00
ptitSeb d09a48fd03 [INTERPRETER] my first avx opcode 2024-05-26 09:21:04 +02:00
Yip Coekjan b5c0a857ca Fix typo on box64 config file (#1533) 2024-05-25 15:02:32 +02:00
Yip Coekjan ab9f848dcd Fix unclosed item list (#1532) 2024-05-25 13:57:35 +02:00
ptitSeb 1b3350437c Added 67 66 0F D6 ([ARM64_dynarec] too) 2024-05-25 11:46:31 +02:00
ptitSeb 03749788e8 [TRACE] Group trace member of x64emu_t 2024-05-24 22:45:11 +02:00
ptitSeb 9a571cfb72 [RV64_DYNAREC] Fix dynarec build for RV64 2024-05-24 22:44:47 +02:00
ptitSeb 39303611ef more avx infrastructure 2024-05-24 20:17:35 +02:00
ptitSeb fcf0cf00d0 Added support for XSAVE/XRSTOR ([ARM64_DYNAREC] too) 2024-05-24 15:01:46 +02:00
Yang Liu 2ee846f48e Workaround on a race condition on SDL_GetThreadID (#1530) 2024-05-24 10:14:49 +02:00
Yang Liu 9c846a3e40 Redirect pthread_yield to sched_yield (#1529) 2024-05-24 09:40:31 +02:00
Yang Liu 712e8315f8 [LA64_DYNAREC] Added more opcodes (#1528) 2024-05-23 22:21:56 +02:00
ptitSeb 604ab22526 [ARM64_DYNAREC] Added 66 D9 /6 and 66 DD /4 /6 opcodes 2024-05-23 16:32:04 +02:00
ptitSeb 85d09df938 Some more x87 adjustment, but it still off a bit 2024-05-23 16:32:04 +02:00
Yang Liu 5ae93f8431 [LA64_DYNAREC] Added CMPXCHG8B and CMPXCHG16B opcodes (#1527) 2024-05-23 15:57:58 +02:00
ptitSeb 3aab8dd332 More fixes to x87 handling 2024-05-23 15:55:28 +02:00
Yang Liu bf9d297dcd [RV64_DYNAREC] Fixed LOCK XCHG byte opcode (#1526) 2024-05-23 12:04:09 +02:00
Yang Liu 080cc77208 [LA64_DYNAREC] Added more opcodes (#1525) 2024-05-23 10:51:07 +02:00
ZoHan 7ebd92be7d Wrapped libpsl5 (#1523)
* Wrapped libpsl5

* Recover files
2024-05-23 07:49:52 +02:00
ptitSeb 22b2f63917 [ARM64_DYNAREC] Small potential fix to D9 E5 opcode 2024-05-22 23:51:54 +02:00
ptitSeb 5bcfa34bea Fixed some x87 handling issues 2024-05-22 23:50:45 +02:00
Yang Liu 48c47423a4 [LA64_DYNAREC] Fixed more issues here and there (#1521)
* [LA64_DYNAREC] Fixed more issues here and there

* minor optim

* minor change
2024-05-22 23:00:13 +02:00
Yang Liu 229cae16d1 [LA64_DYNAREC] Fixed some non-lbt flags comutation issues (#1520) 2024-05-22 20:00:22 +02:00
Yang Liu 9edb89fc22 [LA64_DYNAREC] Fixed LOCK XCHG byte opcode fallback path (#1519)
* [LA64_DYNAREC] Fixed LOCK XCHG byte opcode fallback path

* fix
2024-05-22 18:22:08 +02:00
Yang Liu 3faabb478d [DYNAREC] Simplified emit_pf helper (#1518)
* [DYNAREC] Simplified emit_pf helper

* Remove unused function and outdated comments
2024-05-22 13:06:43 +02:00
ptitSeb 2c127fe69c [ARM64_DYANREC] Simplified emit_pf helper 2024-05-22 11:08:07 +02:00
ptitSeb 3765d9e6f7 Start of a new dev. cycle 2024-05-22 10:18:32 +02:00
1605 changed files with 166639 additions and 32832 deletions

No files matched your search

+2 -1
View File
@@ -12,6 +12,7 @@ MaxEmptyLinesToKeep: 2
IndentCaseLabels: true
AlignConsecutiveMacros: true
WhitespaceSensitiveMacros: ['QUOTE']
IfMacros: ['IFX', 'IFX2', 'IFXA', 'IFX_PENDOR0', 'IFXX', 'IFX2X', 'IFXN', 'UFLAG_IF', 'PASS2IF']
IfMacros: ['IFX', 'IFXORNAT', 'IFX2', 'IFXA', 'IFX_PENDOR0', 'IFXX', 'IFX2X', 'IFXN', 'UFLAG_IF', 'PASS2IF']
UseTab: Never
IndentPPDirectives: None
---
+148 -31
View File
@@ -27,16 +27,20 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [X64, OTHER_ARM, RISCV, RPI4ARM64, RPI5ARM64, RK3326, RK3399, RK3588, PHYTIUM, SD845, SD888, ADLINK, ARM64, ANDROID, TERMUX, LARCH64]
type: [Release, Trace]
platform: [X64, RISCV, RK3588, ARM64, ANDROID, TERMUX, LARCH64, ANDROID_GLIBC]
type: [Release, Trace, StaticBuild, Box32]
os: [ubuntu-latest]
include:
- platform: TEGRAX1
type: Release
os: ubuntu-20.04
- platform: TEGRAX1
type: Trace
os: ubuntu-20.04
exclude:
- platform: ANDROID
type: StaticBuild
- platform: TERMUX
type: StaticBuild
- platform: X64
type: StaticBuild
- platform: ANDROID
type: Box32
- platform: TERMUX
type: Box32
runs-on: ${{ matrix.os }}
steps:
@@ -46,8 +50,8 @@ jobs:
- name: "Environment preparation"
run: |
sudo apt-get update
if [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'OTHER_ARM' && ${{ matrix.platform }} != 'RISCV' && ${{ matrix.platform }} != 'LARCH64' ]]; then
sudo apt-get -y install git cmake make python3
if [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'RISCV' && ${{ matrix.platform }} != 'LARCH64' ]]; then
sudo apt-get -y install git cmake make python3 patchelf
if [[ ${{ matrix.platform }} == 'ANDROID' || ${{ matrix.platform }} == 'TERMUX' ]]; then
wget https://dl.google.com/android/repository/android-ndk-r26b-linux.zip
unzip android-ndk-r26b-linux.zip
@@ -57,6 +61,10 @@ jobs:
sudo cp -rf termux-docker/system/arm /system
sudo chown -R $(whoami):$(whoami) /system
sudo chmod 755 -R /system
elif [[ ${{ matrix.platform }} == 'ANDROID_GLIBC' ]]; then
sudo apt-get -y install git gcc-aarch64-linux-gnu
echo "BOX64_PLATFORM_MARCRO=-DARM64=1 -DARM_DYNAREC=1 -DBAD_SIGNAL=1" >> $GITHUB_ENV
echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
else
sudo apt-get -y install git gcc-aarch64-linux-gnu
echo "BOX64_PLATFORM_MARCRO=-D${{ matrix.platform }}=1" >> $GITHUB_ENV
@@ -84,7 +92,7 @@ jobs:
elif [[ ${{ matrix.platform }} == 'RISCV' ]]; then
echo BOX64_PLATFORM_MARCRO="-DRV64=ON" >> $GITHUB_ENV
echo "BOX64_COMPILER=riscv64-linux-gnu-gcc" >> $GITHUB_ENV
sudo apt-get -y install git gcc-riscv64-linux-gnu cmake make python3
sudo apt-get -y install git gcc-riscv64-linux-gnu cmake make python3 ninja-build
elif [[ ${{ matrix.platform }} == 'LARCH64' ]]; then
sudo mkdir /usr/local/larch
wget -O- -q https://github.com/loongson/build-tools/releases/download/2023.08.08/CLFS-loongarch64-8.1-x86_64-cross-tools-gcc-glibc.tar.xz | sudo tar -C /usr/local/larch --strip-components=1 --xz -xf -
@@ -109,17 +117,63 @@ jobs:
if [[ ${{ matrix.type }} == 'Release' ]]; then
echo BOX64_BUILD_TYPE=Release >> $GITHUB_ENV
echo BOX64_HAVE_TRACE=0 >> $GITHUB_ENV
echo BOX64_STATICBUILD=0 >> $GITHUB_ENV
echo BOX64_BOX32=0 >> $GITHUB_ENV
elif [[ ${{ matrix.type }} == 'StaticBuild' ]]; then
echo BOX64_BUILD_TYPE=Release >> $GITHUB_ENV
echo BOX64_HAVE_TRACE=0 >> $GITHUB_ENV
echo BOX64_STATICBUILD=1 >> $GITHUB_ENV
echo BOX64_BOX32=0 >> $GITHUB_ENV
elif [[ ${{ matrix.type }} == 'Box32' ]]; then
echo BOX64_BUILD_TYPE=Release >> $GITHUB_ENV
echo BOX64_HAVE_TRACE=0 >> $GITHUB_ENV
echo BOX64_STATICBUILD=0 >> $GITHUB_ENV
echo BOX64_BOX32=1 >> $GITHUB_ENV
else
echo BOX64_BUILD_TYPE=RelWithDebInfo >> $GITHUB_ENV
echo BOX64_HAVE_TRACE=1 >> $GITHUB_ENV
echo BOX64_STATICBUILD=0 >> $GITHUB_ENV
echo BOX64_BOX32=0 >> $GITHUB_ENV
fi
- name: "Get XuanTie QEMU Cache Key"
if: matrix.platform == 'RISCV'
id: get-xuantie-qemu-cache-key
run: |
echo "key=f2dfdd13014d51f957c7172acc2e791cb42dc400" >> $GITHUB_OUTPUT
- name: "Cache XuanTie QEMU"
if: matrix.platform == 'RISCV'
id: cache-xuantie-qemu
uses: actions/cache@v3
with:
path: ${{ github.workspace }}/xuantie_qemu_install
key: ${{ runner.os }}-${{ steps.get-xuantie-qemu-cache-key.outputs.key }}-xuantie-qemu
- name: "Checkout XuanTie QEMU"
if: matrix.platform == 'RISCV' && steps.cache-xuantie-qemu.outputs.cache-hit != 'true'
uses: actions/checkout@v3
with:
repository: revyos/qemu
path: xuantie_qemu
ref: f2dfdd13014d51f957c7172acc2e791cb42dc400
- name: "Build XuanTie QEMU for XTheadVector"
if: matrix.platform == 'RISCV' && steps.cache-xuantie-qemu.outputs.cache-hit != 'true'
run: |
cd xuantie_qemu
./configure --prefix=$GITHUB_WORKSPACE/xuantie_qemu_install --target-list=riscv64-linux-user --disable-system
make -j$(nproc)
make install
- name: "Display Build info"
run: |
echo "CMake Platform Macro: ${{ env.BOX64_PLATFORM_MARCRO }}"
echo "CMake C Compiler: ${{ env.BOX64_COMPILER }}"
echo "Build type: ${{ env.BOX64_BUILD_TYPE }}"
echo "Trace Enabled: ${{ env.BOX64_HAVE_TRACE }}"
echo "StaticBuild Enabled: ${{ env.BOX64_STATICBUILD }}"
echo "Box32 Enabled: ${{ env.BOX64_BOX32 }}"
- name: "Build Box64"
run: |
@@ -130,45 +184,108 @@ jobs:
${{ env.BOX64_PLATFORM_MARCRO }}\
-DCMAKE_BUILD_TYPE=${{ env.BOX64_BUILD_TYPE }}\
-DHAVE_TRACE=${{ env.BOX64_HAVE_TRACE }}\
-DSTATICBUILD=${{ env.BOX64_STATICBUILD }}\
-DBOX32=${{ env.BOX64_BOX32 }}\
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON\
-DCI=${{ matrix.platform != 'ANDROID' }}
make -j$(nproc) VERBOSE=1
- name: "Test Box64"
if: ${{ matrix.platform != 'TEGRAX1' }}
run: |
if [[ ${{ matrix.platform }} != 'X64' ]]; then
mkdir qemu9.0.0
wget -O- -q https://archive.archlinux.org/packages/q/qemu-user-static/qemu-user-static-9.0.0-1-x86_64.pkg.tar.zst | tar -I zstd -C qemu9.0.0 -xf -
sudo cp qemu9.0.0/usr/bin/* /usr/bin/
mkdir qemu9
wget -O- -q https://archive.archlinux.org/packages/q/qemu-user-static/qemu-user-static-9.0.2-1-x86_64.pkg.tar.zst | tar -I zstd -C qemu9 -xf -
sudo cp qemu9/usr/bin/* /usr/bin/
fi
cd build
export CTEST_OPTIONS="-j$(nproc) --timeout 120 --output-on-failure --repeat until-pass:20"
if [[ ${{ matrix.platform }} == 'RISCV' ]]; then
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ ctest -j$(nproc) --output-on-failure
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ BOX64_DYNAREC=0 ctest -j$(nproc) --output-on-failure
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ QEMU_CPU=rv64,zba=true,zbb=true,zbc=true,zbs=true ctest -j$(nproc) --output-on-failure
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ QEMU_CPU=rv64,xtheadba=true,xtheadba=true,xtheadbb=true,xtheadbs=true,xtheadcondmov=true,xtheadmemidx=true,xtheadmempair=true,xtheadfmemidx=true,xtheadmac=true,xtheadfmv=true ctest -j$(nproc) --output-on-failure
export INTERPRETER=qemu-riscv64-static
export QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/
ctest $CTEST_OPTIONS
QEMU_CPU=rv64,v=false BOX64_DYNAREC=0 ctest $CTEST_OPTIONS
QEMU_CPU=rv64,v=false,zba=true,zbb=true,zbc=true,zbs=true ctest $CTEST_OPTIONS
QEMU_CPU=rv64,v=true,vlen=128,vext_spec=v1.0 ctest $CTEST_OPTIONS
QEMU_CPU=rv64,v=true,vlen=256,vext_spec=v1.0 ctest $CTEST_OPTIONS
QEMU_CPU=thead-c906 ctest $CTEST_OPTIONS
BOX64_DYNAREC_TEST=1 ctest $CTEST_OPTIONS -E nocosim
BOX64_DYNAREC_TEST=1 QEMU_CPU=rv64,v=false,zba=true,zbb=true,zbc=true,zbs=true ctest $CTEST_OPTIONS -E nocosim
BOX64_DYNAREC_TEST=1 QEMU_CPU=rv64,v=true,vlen=128,vext_spec=v1.0 ctest $CTEST_OPTIONS -E nocosim
BOX64_DYNAREC_TEST=1 QEMU_CPU=rv64,v=true,vlen=256,vext_spec=v1.0 ctest $CTEST_OPTIONS -E nocosim
BOX64_DYNAREC_TEST=1 QEMU_CPU=thead-c906 ctest $CTEST_OPTIONS -E nocosim
export INTERPRETER=$GITHUB_WORKSPACE/xuantie_qemu_install/bin/qemu-riscv64
QEMU_CPU=c910v ctest $CTEST_OPTIONS
BOX64_DYNAREC_TEST=1 QEMU_CPU=c910v ctest $CTEST_OPTIONS -E nocosim
elif [[ ${{ matrix.platform }} == 'LARCH64' ]]; then
INTERPRETER=qemu-loongarch64-static QEMU_LD_PREFIX=/usr/loongarch64-linux-gnu/ BOX64_DYNAREC_LA64NOEXT=1 ctest -j$(nproc) --repeat until-pass:20 --output-on-failure
INTERPRETER=qemu-loongarch64-static QEMU_LD_PREFIX=/usr/loongarch64-linux-gnu/ BOX64_DYNAREC_TEST=2 BOX64_DYNAREC_LA64NOEXT=1 ctest -j$(nproc) --repeat until-pass:20 --output-on-failure
INTERPRETER=qemu-loongarch64-static QEMU_LD_PREFIX=/usr/loongarch64-linux-gnu/ BOX64_DYNAREC=0 ctest -j$(nproc) --repeat until-pass:20 --output-on-failure
export INTERPRETER=qemu-loongarch64-static
export QEMU_LD_PREFIX=/usr/loongarch64-linux-gnu/
BOX64_DYNAREC_LA64NOEXT=1 ctest $CTEST_OPTIONS -E nocosim
BOX64_DYNAREC=0 ctest $CTEST_OPTIONS -E nocosim
BOX64_DYNAREC_TEST=1 BOX64_DYNAREC_LA64NOEXT=1 ctest $CTEST_OPTIONS -E nocosim
elif [[ ${{ matrix.platform }} == 'ANDROID' ]]; then
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/system/lib64 BOX64_DYNAREC=0 ctest -j$(nproc) --repeat until-pass:20 --output-on-failure
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/system/lib64 ctest -j$(nproc) --repeat until-pass:20 --output-on-failure
export INTERPRETER=qemu-aarch64-static
export QEMU_LD_PREFIX=/system/lib64
BOX64_DYNAREC=0 ctest $CTEST_OPTIONS
ctest $CTEST_OPTIONS
elif [[ ${{ matrix.platform }} == 'TERMUX' ]]; then
INTERPRETER=qemu-aarch64-static QEMU_SET_ENV=LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib QEMU_LD_PREFIX=/system/lib64:/data/data/com.termux/files/usr/lib BOX64_DYNAREC=0 ctest -j$(nproc) --repeat until-pass:20 --output-on-failure
INTERPRETER=qemu-aarch64-static QEMU_SET_ENV=LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib QEMU_LD_PREFIX=/system/lib64:/data/data/com.termux/files/usr/lib ctest -j$(nproc) --repeat until-pass:20 --output-on-failure
export INTERPRETER=qemu-aarch64-static
export QEMU_SET_ENV=LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib
export QEMU_LD_PREFIX=/system/lib64:/data/data/com.termux/files/usr/lib
BOX64_DYNAREC=0 ctest $CTEST_OPTIONS
ctest $CTEST_OPTIONS
elif [[ ${{ matrix.platform }} != 'X64' ]]; then # AArch64
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ BOX64_DYNAREC=0 ctest -j$(nproc) --output-on-failure
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ ctest -j$(nproc) --output-on-failure
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ BOX64_DYNAREC_TEST=2 ctest -j$(nproc) --output-on-failure
export INTERPRETER=qemu-aarch64-static
export QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/
BOX64_DYNAREC=0 ctest $CTEST_OPTIONS
ctest $CTEST_OPTIONS
BOX64_DYNAREC_TEST=1 ctest $CTEST_OPTIONS -E nocosim
else
ctest -j$(nproc) --output-on-failure
ctest -j$(nproc)
fi
- name: "Get short Git commit"
id: git-info
run: echo "SHORT_COMMIT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: "Packaging WCP file for Winlator"
if: matrix.platform == 'ANDROID_GLIBC' && matrix.type != 'StaticBuild'
run: |
cd build
cat <<EOF > profile.json
{
"type": "Box64",
"versionName": "latest-${SHORT_COMMIT}",
"versionCode": 1,
"description": "Box64-latest-${SHORT_COMMIT}. Built from [https://github.com/ptitSeb/box64].",
"files": [
{
"source": "box64",
"target": "\${localbin}/box64"
}
]
}
EOF
patchelf --set-interpreter /data/data/com.winlator/files/imagefs/usr/lib/ld-linux-aarch64.so.1 ./box64
tar --zstd -cf box64-latest.wcp box64 profile.json
- name: "Upload Artifact"
uses: actions/upload-artifact@v4
with:
name: box64-${{ matrix.platform }}-${{ matrix.type }}
path: build/box64
- name: "Upload WCP file"
if: matrix.platform == 'ANDROID_GLIBC' && matrix.type != 'StaticBuild'
uses: actions/upload-artifact@v4
with:
name: box64-latest-${{ matrix.type }}-wcp
path: build/box64-latest.wcp
+10 -5
View File
@@ -60,11 +60,16 @@ build*/
src/git_head.h
backup/
# LLVMprivateGenerator
/LLVMprivateGenerator/*
!/LLVMprivateGenerator/Makefile
!/LLVMprivateGenerator/main.cpp
!/LLVMprivateGenerator/registered_structs.cpp
# Wrapper helper
/wrapperhelper/bin
/wrapperhelper/makedir
/wrapperhelper/obj
/wrapperhelper/sanaddress
/wrapperhelper/sanleak
/wrapperhelper/sanundefined
/wrapperhelper/src/machine.gen
/wrapperhelper/*.h
!/wrapperhelper/example-libc.h
# macOS
.DS_Store
+458 -49
View File
@@ -17,8 +17,10 @@ option(TEGRA_T194 "Set to ON if targeting an Tegra Xavier based device" ${TEGRA_
option(TEGRA_T234 "Set to ON if targeting an Tegra Orin based device" ${TEGRA_T234})
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
option(SD865 "Set to ON if targeting a Snapragon 865 based device" ${SD865})
option(SD888 "Set to ON if targeting a Snapragon 888 based device" ${SD888})
option(SD8G2 "Set to ON if targeting a Snapragon 8 Gen 2 based device" ${SD8G2})
option(SDORYON1 "Set to ON if targeting a Snapdragon Oryon 1 (X1E80100/X1E78100) based device" ${SDORYON1})
option(ADLINK "Set to ON if targeting an ADLink AmpereAltra based device" ${ADLINK})
option(M1 "Set to ON if targeting a AppleM1 running on Asahi computer" ${M1})
option(LARCH64 "Set to ON if targeting an Loongarch64 based device" ${LARCH64})
@@ -37,6 +39,8 @@ option(BAD_SIGNAL "Set to ON to activate the workaround for incoherent si_info o
option(SW64 "Set ON if targeting an SW64 based device" ${SW64})
option(CI "Set to ON if running in CI" ${CI})
option(WITH_MOLD "Set to ON to use with mold" ${WITH_MOLD})
option(BOX32 "Set to ON to add Linux 32bits support (experimental, do not use)" ${BOX32})
option(BOX32_BINFMT "Also setup binfmt integration for box32" ${BOX32_BINFMT})
if(TERMUX)
set(TERMUX_PATH "/data/data/com.termux/files")
@@ -63,7 +67,7 @@ if(PPC64LE)
set(RV64_DYNAREC OFF CACHE BOOL "")
set(LARCH64_DYNAREC OFF CACHE BOOL "")
endif()
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RPI5ARM64 OR RK3326 OR TEGRAX1 OR TEGRA_T194 OR TEGRA_T234 OR PHYTIUM OR SD845 OR SD888 OR SD8G2 OR LX2160A OR M1 OR ARM64 OR ADLINK)
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RPI5ARM64 OR RK3326 OR TEGRAX1 OR TEGRA_T194 OR TEGRA_T234 OR PHYTIUM OR SD845 OR SD865 OR SD888 OR SD8G2 OR SDORYON1 OR LX2160A OR M1 OR ARM64 OR ADLINK)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
@@ -81,6 +85,7 @@ if(SW64)
set(NOALIGN OFF CACHE BOOL "")
endif()
if(ANDROID)
set(TERMUX_PATH "/data/data/com.termux/files")
set(NOLOADADDR ON CACHE BOOL "")
set(BAD_SIGNAL ON CACHE BOOL "")
endif()
@@ -173,6 +178,11 @@ elseif(SD845)
add_definitions(-DSD845)
add_definitions(-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55")
elseif(SD865)
add_definitions(-DSD865)
#note that cortex-a77.cortex-a55 is not supported, so fall back to a76 instead
add_definitions(-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a76.cortex-a55)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a76.cortex-a55")
elseif(SD888)
add_definitions(-DSD888)
add_definitions(-pipe -march=armv8.4-a+simd+crypto)
@@ -181,6 +191,24 @@ elseif(SD8G2)
add_definitions(-DSD8G2)
add_definitions(-pipe -march=armv9-a+i8mm+sm4+sha3+rcpc+crypto+nosve+nosve2)
set(CMAKE_ASM_FLAGS "-pipe -march=armv9-a+i8mm+sm4+sha3+rcpc+crypto+nosve+nosve2")
elseif(SDORYON1)
add_definitions(-DSDORYON1)
# NOTE
#
# 1.
# GCC 14 and Clang 19 support oryon-1 as a -mcpu/-mtune argument,
# however it seems like fedora (the system I tested this on) does not work.
# see https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/AArch64-Options.html if you're interested
#
# 2.
# gcc/gcc/config/aarch64/aarch64-cores.def:157 defines oryon1 as
# AARCH64_CORE("oryon-1", oryon1, cortexa57, V8_6A, (CRYPTO, SM4, SHA3, F16), cortexa72, 0x51, 0x001, -1)
# where
# * the 3rd positional argument is represented as the "scheduler"
# * the 6th positional argument is represented as the "cost"
# I've chosen the a57 because I don't know if I should choose the a72
add_definitions(-pipe -march=armv8.6-a+crypto+sm4+sha3+fp16 -mtune=cortex-a57)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.6-a+crypto+sm4+sha3+fp16 -mtune=cortex-a57")
elseif(ADLINK)
add_definitions(-DADLINK)
add_definitions(-pipe -mcpu=neoverse-n1 -fuse-ld=gold -fuse-linker-plugin)
@@ -209,9 +237,7 @@ elseif(ARM64)
#add_definitions(-pipe -march=native)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+simd")
elseif(ARM_DYNAREC)
if(NOT ANDROID)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
endif()
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
endif()
if(ANDROID)
add_definitions(-DANDROID)
@@ -233,10 +259,17 @@ if(STATICBUILD)
set(CMAKE_EXE_LINKER_FLAGS "-static")
set(HAVE_TRACE OFF)
endif()
if(BOX32)
add_definitions(-DBOX32)
add_definitions(-Wno-address-of-packed-member) #32bits might generated unaligned pointers
endif()
if(NOGIT)
add_definitions(-DNOGIT)
endif()
if(CI)
add_definitions(-Wno-pointer-type-mismatch)
endif()
if(HAVE_TRACE)
set(BOX64 box64)
@@ -300,6 +333,11 @@ include_directories(
"${BOX64_ROOT}/src"
"${BOX64_ROOT}/src/wrapped/generated"
)
if(BOX32)
include_directories(
"${BOX64_ROOT}/src/wrapped32/generated"
)
endif()
# git_head.h is a generated file
set_source_files_properties(
@@ -313,6 +351,7 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/box64context.c"
"${BOX64_ROOT}/src/build_info.c"
"${BOX64_ROOT}/src/custommem.c"
"${BOX64_ROOT}/src/custommmap.c"
"${BOX64_ROOT}/src/dynarec/dynarec.c"
"${BOX64_ROOT}/src/elfs/elfloader.c"
"${BOX64_ROOT}/src/elfs/elfparser.c"
@@ -327,7 +366,6 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/emu/x64run_private.c"
"${BOX64_ROOT}/src/emu/x64shaext.c"
"${BOX64_ROOT}/src/emu/x64syscall.c"
"${BOX64_ROOT}/src/emu/x86syscall.c"
"${BOX64_ROOT}/src/emu/x64tls.c"
"${BOX64_ROOT}/src/emu/x64trace.c"
"${BOX64_ROOT}/src/librarian/librarian.c"
@@ -337,6 +375,7 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/libtools/auxval.c"
"${BOX64_ROOT}/src/libtools/myalign.c"
"${BOX64_ROOT}/src/libtools/signals.c"
"${BOX64_ROOT}/src/libtools/decopcode.c"
"${BOX64_ROOT}/src/libtools/threads.c"
"${BOX64_ROOT}/src/tools/bitutils.c"
"${BOX64_ROOT}/src/tools/box64stack.c"
@@ -360,6 +399,34 @@ if(NOT STATICBUILD)
"${BOX64_ROOT}/src/librarian/globalsymbols.c"
)
endif()
if(BOX32)
list(APPEND ELFLOADER_SRC
"${BOX64_ROOT}/src/box32.c"
"${BOX64_ROOT}/src/elfs/elfhash32.c"
"${BOX64_ROOT}/src/elfs/elfloader32.c"
"${BOX64_ROOT}/src/elfs/elfparser32.c"
"${BOX64_ROOT}/src/elfs/elfload_dump32.c"
"${BOX64_ROOT}/src/tools/box32stack.c"
"${BOX64_ROOT}/src/emu/x86int3.c"
"${BOX64_ROOT}/src/librarian/globalsymbols32.c"
"${BOX64_ROOT}/src/libtools/myalign32.c"
"${BOX64_ROOT}/src/libtools/myalign64_32.c"
"${BOX64_ROOT}/src/libtools/signal32.c"
"${BOX64_ROOT}/src/libtools/threads32.c"
"${BOX64_ROOT}/src/libtools/libc_net32.c"
"${BOX64_ROOT}/src/libtools/sdl1align32.c"
"${BOX64_ROOT}/src/libtools/sdl2align32.c"
"${BOX64_ROOT}/src/libtools/my_x11_conv.c"
"${BOX64_ROOT}/src/libtools/my_x11_xevent.c"
"${BOX64_ROOT}/src/emu/x86syscall_32.c"
"${BOX64_ROOT}/src/wrapped32/generated/wrapper32.c"
"${BOX64_ROOT}/src/wrapped32/generated/converter32.c"
)
else()
list(APPEND ELFLOADER_SRC
"${BOX64_ROOT}/src/emu/x86syscall.c"
)
endif()
if(NOT ANDROID)
list(APPEND ELFLOADER_SRC
"${BOX64_ROOT}/src/libtools/obstack.c"
@@ -379,6 +446,7 @@ set(INTERPRETER
"${BOX64_ROOT}/src/emu/x64run66dd.c"
"${BOX64_ROOT}/src/emu/x64run66f0.c"
"${BOX64_ROOT}/src/emu/x64run67.c"
"${BOX64_ROOT}/src/emu/x64run67avx.c"
"${BOX64_ROOT}/src/emu/x64run67_32.c"
"${BOX64_ROOT}/src/emu/x64run6764_32.c"
"${BOX64_ROOT}/src/emu/x64run670f.c"
@@ -395,12 +463,24 @@ set(INTERPRETER
"${BOX64_ROOT}/src/emu/x64runf0.c"
"${BOX64_ROOT}/src/emu/x64runf20f.c"
"${BOX64_ROOT}/src/emu/x64runf30f.c"
"${BOX64_ROOT}/src/emu/x64runavx.c"
"${BOX64_ROOT}/src/emu/x64runavx0f.c"
"${BOX64_ROOT}/src/emu/x64runavx0f38.c"
"${BOX64_ROOT}/src/emu/x64runavx660f.c"
"${BOX64_ROOT}/src/emu/x64runavxf20f.c"
"${BOX64_ROOT}/src/emu/x64runavxf30f.c"
"${BOX64_ROOT}/src/emu/x64runavx660f38.c"
"${BOX64_ROOT}/src/emu/x64runavx660f3a.c"
"${BOX64_ROOT}/src/emu/x64runavxf20f38.c"
"${BOX64_ROOT}/src/emu/x64runavxf30f38.c"
"${BOX64_ROOT}/src/emu/x64runavxf20f3a.c"
"${BOX64_ROOT}/src/emu/x64runavxf30f3a.c"
)
if(STATICBUILD)
set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibbsd.c"
#"${BOX64_ROOT}/src/wrapped/wrappedlibbsd.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibc.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibcmusl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibdl.c"
@@ -485,6 +565,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibcups.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibdl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibdrm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibdrmamdgpu.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibegl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibform.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibformw.c"
@@ -526,6 +607,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibx11.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibx11xcb.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxau.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxaw.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcb.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbcursor.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbdri2.c"
@@ -637,8 +719,21 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedicui18n73.c"
"${BOX64_ROOT}/src/wrapped/wrappedicuuc74.c"
"${BOX64_ROOT}/src/wrapped/wrappedicui18n74.c"
"${BOX64_ROOT}/src/wrapped/wrappedicuuc75.c"
"${BOX64_ROOT}/src/wrapped/wrappedicui18n75.c"
"${BOX64_ROOT}/src/wrapped/wrappedidn2.c"
"${BOX64_ROOT}/src/wrapped/wrappedanl.c"
"${BOX64_ROOT}/src/wrapped/wrappedpsl5.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibssh2.c"
"${BOX64_ROOT}/src/wrapped/wrappedp11kit.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibtasn1.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibnettle8.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibunistring2.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibhogweed6.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibsqlite3.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibtiff5.c"
"${BOX64_ROOT}/src/wrapped/wrappedbrotlidec.c"
"${BOX64_ROOT}/src/wrapped/wrappedzstd.c"
)
endif()
if(ANDROID)
@@ -691,6 +786,83 @@ endif ()
add_custom_target(WRAPPERS DEPENDS "${BOX64_ROOT}/src/wrapped/generated/functions_list.txt")
#add_custom_target(PRINTER DEPENDS "${BOX64_ROOT}/src/dynarec/last_run.txt")
if(BOX32)
if(STATICBUILD)
set(WRAPPEDS32
"${BOX64_ROOT}/src/wrapped32/wrappedldlinux.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibc.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibdl.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibm.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibpthread.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibrt.c"
)
else()
set(WRAPPEDS32
"${BOX64_ROOT}/src/wrapped32/wrappedldlinux.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibc.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibdl.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibm.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibpthread.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibrt.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibresolv.c"
"${BOX64_ROOT}/src/wrapped32/wrappedcrashhandler.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibgl.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibglu.c"
"${BOX64_ROOT}/src/wrapped32/wrappedsdl1.c"
"${BOX64_ROOT}/src/wrapped32/wrappedsdl2.c"
"${BOX64_ROOT}/src/wrapped32/wrappedsdl2image.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibasound.c"
"${BOX64_ROOT}/src/wrapped32/wrappedopenal.c"
"${BOX64_ROOT}/src/wrapped32/wrappedfreetype.c"
"${BOX64_ROOT}/src/wrapped32/wrappedfontconfig.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibx11.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxext.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxfixes.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxrender.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxi.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxcomposite.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxcursor.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxrandr.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxss.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxxf86vm.c"
"${BOX64_ROOT}/src/wrapped32/wrappedxinerama.c"
"${BOX64_ROOT}/src/wrapped32/wrappedexpat.c"
"${BOX64_ROOT}/src/wrapped32/wrappedudev0.c"
"${BOX64_ROOT}/src/wrapped32/wrappedudev1.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibuuid.c"
"${BOX64_ROOT}/src/wrapped32/wrappedtcmallocminimal.c"
)
endif()
string(REPLACE ".c" "_private.h" MODROOT ${BOX64_ROOT})
#set(WRAPPEDS32_HEAD "${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9_genvate.h")
foreach(A ${WRAPPEDS32})
string(REPLACE ".c" "_private.h" C ${A})
string(REPLACE "${MODROOT}" "${BOX64_ROOT}" B ${C})
set(WRAPPEDS32_HEAD ${WRAPPEDS32_HEAD} ${B})
set_source_files_properties(${A} PROPERTIES OBJECT_DEPENDS ${B})
endforeach()
set(WRAPPER32 "${BOX64_ROOT}/src/wrapped32/generated/wrapper32.c" "${BOX64_ROOT}/src/wrapped32/generated/wrapper32.h")
if(NOT CI)
add_custom_command(
OUTPUT "${BOX64_ROOT}/src/wrapped32/generated/functions_list.txt"
COMMAND "${PYTHON_EXECUTABLE}" "${BOX64_ROOT}/rebuild_wrappers_32.py"
"${BOX64_ROOT}"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "ANDROID" "TERMUX" "STATICBUILD" "--"
${WRAPPEDS32_HEAD}
MAIN_DEPENDENCY "${BOX64_ROOT}/rebuild_wrappers_32.py"
DEPENDS ${WRAPPEDS32} ${WRAPPEDS32_HEAD}
BYPRODUCTS ${WRAPPER32}
)
endif()
add_custom_target(WRAPPERS32 DEPENDS "${BOX64_ROOT}/src/wrapped32/generated/functions_list.txt")
else()
set(WRAPPEDS32)
endif()
if(DYNAREC)
set(DYNAREC_SRC
"${BOX64_ROOT}/src/dynarec/dynablock.c"
@@ -728,6 +900,7 @@ if(ARM_DYNAREC)
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_67.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_67_32.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_67_avx.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_6764_32.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_d8.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_d9.c"
@@ -745,6 +918,17 @@ if(ARM_DYNAREC)
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66f0.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_f20f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_f30f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_0f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_0f38.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_66_0f38.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_66_0f3a.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_f2_0f38.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_f2_0f3a.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_f3_0f38.c"
)
endif()
@@ -775,10 +959,12 @@ if(RV64_DYNAREC)
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_00_2.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_00_3.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_0f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_0f_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_64.c"
#"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_65.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_64_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_67.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_67_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_67_32.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_d8.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_d9.c"
@@ -790,12 +976,18 @@ if(RV64_DYNAREC)
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_df.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f0.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_660f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_660f38.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_660f_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f20f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f30f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_6664.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f0.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f20f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f20f_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f30f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f30f_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_avx.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c"
)
endif()
@@ -823,6 +1015,8 @@ if(LARCH64_DYNAREC)
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_0f.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_64.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_66.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_6664.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_67.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_f30f.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_660f.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_f0.c"
@@ -836,6 +1030,11 @@ if(DYNAREC)
${DYNAREC_PASS}
"${BOX64_ROOT}/src/dynarec/dynarec_native_pass.c"
)
if(BOX32)
list(APPEND DYNAREC_PASS
"${BOX64_ROOT}/src/wrapped32/generated/wrapper32.h"
)
endif()
add_library(dynarec_native OBJECT ${DYNAREC_SRC})
@@ -853,6 +1052,12 @@ if(DYNAREC)
add_dependencies(native_pass1 WRAPPERS)
add_dependencies(native_pass2 WRAPPERS)
add_dependencies(native_pass3 WRAPPERS)
if(BOX32)
add_dependencies(native_pass0 WRAPPERS32)
add_dependencies(native_pass1 WRAPPERS32)
add_dependencies(native_pass2 WRAPPERS32)
add_dependencies(native_pass3 WRAPPERS32)
endif()
add_library(dynarec STATIC
$<TARGET_OBJECTS:dynarec_native>
@@ -869,26 +1074,29 @@ if(DYNAREC)
add_custom_command(
OUTPUT "${BOX64_ROOT}/src/git_head.h"
COMMAND sh -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX64_ROOT}/src/git_head.h\""
DEPENDS dynarec ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS}
DEPENDS dynarec ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS} ${WRAPPEDS32}
VERBATIM)
else()
add_custom_command(
OUTPUT "${BOX64_ROOT}/src/git_head.h"
COMMAND sh -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX64_ROOT}/src/git_head.h\""
DEPENDS ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS}
DEPENDS ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS} ${WRAPPEDS32}
VERBATIM)
endif()
add_library(interpreter OBJECT ${INTERPRETER})
add_executable(${BOX64} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX64_ROOT}/src/git_head.h")
add_executable(${BOX64} ${ELFLOADER_SRC} ${WRAPPEDS} ${WRAPPEDS32} "${BOX64_ROOT}/src/git_head.h")
set_target_properties(${BOX64} PROPERTIES ENABLE_EXPORTS ON)
add_dependencies(${BOX64} WRAPPERS)
if(BOX32)
add_dependencies(${BOX64} WRAPPERS32)
endif()
#add_dependencies(${BOX64} PRINTER)
#target_link_libraries(${BOX64} c m dl rt pthread resolv)
if(STATICBUILD)
#set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-fuse-ld=gold -static -Wl,--no-relax -Wl,--allow-multiple-definition -ldl -lrt -lpthread -lresolv -lc -lutil -lm -Wl,-defsym,_DYNAMIC=0 -pthread")
target_link_libraries(${BOX64} c m dl pthread resolv util bsd c)
target_link_libraries(${BOX64} c m dl pthread resolv util c)
else()
if(ANDROID)
if(TERMUX)
@@ -908,7 +1116,7 @@ target_link_libraries(${BOX64} interpreter)
if(${CMAKE_VERSION} VERSION_LESS "3.13")
if(NOT NOLOADADDR)
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR WITH_MOLD)
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,--image-base=${BOX64_ELF_ADDRESS}")
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-no-pie -Wl,--image-base=${BOX64_ELF_ADDRESS}")
else()
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,-Ttext-segment,${BOX64_ELF_ADDRESS}")
endif()
@@ -917,6 +1125,9 @@ else()
# If symbols are missing, try this: target_link_options(${BOX64} PUBLIC -rdynamic)
if(NOT NOLOADADDR)
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR WITH_MOLD)
if(WITH_MOLD) # --image-base requires -no-pie in mold!
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-no-pie -lm")
endif()
target_link_options(${BOX64} PUBLIC LINKER:--image-base=${BOX64_ELF_ADDRESS})
else()
target_link_options(${BOX64} PUBLIC LINKER:-Ttext-segment,${BOX64_ELF_ADDRESS})
@@ -935,49 +1146,62 @@ endif()
if(NOT _x86 AND NOT _x86_64)
if(NOT TERMUX)
install(TARGETS ${BOX64}
RUNTIME DESTINATION bin)
install(TARGETS ${BOX64} RUNTIME DESTINATION bin)
if(NOT NO_LIB_INSTALL)
install(PROGRAMS ${CMAKE_SOURCE_DIR}/tests/box64-bash DESTINATION bin)
endif()
else()
install(TARGETS ${BOX64}
RUNTIME DESTINATION ${TERMUX_PATH}/usr/bin)
install(TARGETS ${BOX64} RUNTIME DESTINATION ${TERMUX_PATH}/usr/bin)
if(NOT NO_LIB_INSTALL)
install(PROGRAMS ${CMAKE_SOURCE_DIR}/tests/box64-bash DESTINATION ${TERMUX_PATH}/usr/bin)
endif()
endif()
if(NOT NO_CONF_INSTALL)
configure_file(system/box64.conf.cmake system/box64.conf)
if(NOT TERMUX)
install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION /etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION /etc/)
else()
install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION ${TERMUX_PATH}/usr/etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION ${TERMUX_PATH}/usr/etc/)
install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION /etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION /etc/)
if(BOX32_BINFMT)
configure_file(system/box32.conf.cmake system/box32.conf)
install(FILES ${CMAKE_BINARY_DIR}/system/box32.conf DESTINATION /etc/binfmt.d/)
endif()
else()
install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION ${TERMUX_PATH}/usr/etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION ${TERMUX_PATH}/usr/etc/)
if(BOX32_BINFMT)
configure_file(system/box32.conf.cmake system/box32.conf)
install(FILES ${CMAKE_BINARY_DIR}/system/box32.conf DESTINATION ${TERMUX_PATH}/usr/etc/binfmt.d/)
endif()
endif()
endif()
set(INSTALL_PATH "/usr/lib/x86_64-linux-gnu/")
set(INSTALL_PATH "/usr/lib/box64-x86_64-linux-gnu/")
if(NOT NO_LIB_INSTALL)
if(NOT TERMUX)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.5 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libunwind.so.8 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedx509.so.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedx509.so.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedtls.so.14 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedtls.so.12 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedcrypto.so.7 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedcrypto.so.3 DESTINATION ${INSTALL_PATH})
# Create symlinks
install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${INSTALL_PATH}libssl.so.1.1 ${INSTALL_PATH}libssl.so.1.0.0)")
install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${INSTALL_PATH}libcrypto.so.1.1 ${INSTALL_PATH}libcrypto.so.1.0.0)")
else()
if(NOT TERMUX AND NOT ANDROID)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.5 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.0.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.0.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libunwind.so.8 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedx509.so.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedx509.so.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedtls.so.14 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedtls.so.12 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedcrypto.so.7 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedcrypto.so.3 DESTINATION ${INSTALL_PATH})
elseif(TERMUX)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.5 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.1 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.0.0 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.1 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.0.0 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libunwind.so.8 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedx509.so.1 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedx509.so.0 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
@@ -985,8 +1209,36 @@ if(NOT _x86 AND NOT _x86_64)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedtls.so.12 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedcrypto.so.7 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedcrypto.so.3 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
elseif(ANDROID)
install(FILES ${CMAKE_SOURCE_DIR}/x64android/libc++_shared.so DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
endif()
endif()
if(BOX32)
set(INSTALL_PATH "/usr/lib/box64-i386-linux-gnu/")
if(NOT NO_LIB_INSTALL)
if(NOT TERMUX AND NOT ANDROID)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libunwind.so.8 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libcrypto.so.1.0.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libssl.so.1.0.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libz.so.1 DESTINATION ${INSTALL_PATH})
elseif(TERMUX)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libunwind.so.8 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libcrypto.so.1.0.0 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libssl.so.1.0.0 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libz.so.1 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
elseif(ANDROID)
install(FILES ${CMAKE_SOURCE_DIR}/x86android/libc++_shared.so DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
endif()
endif()
endif()
endif()
if(NOT TARGET uninstall)
@@ -1094,11 +1346,13 @@ add_test(fork ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref09.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(cppThreads ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(cppThreads_nocosim ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test10 -D TEST_OUTPUT=tmpfile10.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref10.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(cppThreads_nocosim PROPERTIES ENVIRONMENT "BOX64_LD_LIBRARY_PATH=${CMAKE_SOURCE_DIR}/x64lib")
add_test(tlsData ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test11 -D TEST_OUTPUT=tmpfile11.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref11.txt
@@ -1200,6 +1454,14 @@ add_test(lock ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test29 -D TEST_OUTPUT=tmpfile29.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref29.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(avx_intrinsics ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test30 -D TEST_OUTPUT=tmpfile30.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref30.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(avx_intrinsics PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTNAN=0;BOX64_DYNAREC_FASTROUND=0;BOX64_AVX=2")
else()
add_test(bootSyscall ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
@@ -1232,10 +1494,10 @@ add_test(threadsStart ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref06.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
#add_test(trig ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test07_android -D TEST_OUTPUT=tmpfile07.txt
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref07.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(trig ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test07_android -D TEST_OUTPUT=tmpfile07.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref07.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(pi ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test08_android -D TEST_OUTPUT=tmpfile08.txt
@@ -1287,10 +1549,10 @@ add_test(irelative_reloc ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref20.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(longjumpInSignals ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test21_android -D TEST_OUTPUT=tmpfile21.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref21.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
# add_test(longjumpInSignals ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test21_android -D TEST_OUTPUT=tmpfile21.txt
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref21.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(x87 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test22_android -D TEST_OUTPUT=tmpfile22.txt
@@ -1336,6 +1598,15 @@ add_test(lock ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test29_android -D TEST_OUTPUT=tmpfile29.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref29.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
#add_test(avx_intrinsics ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test30_android -D TEST_OUTPUT=tmpfile30.txt
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref30.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
#
#set_tests_properties(avx_intrinsics PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTNAN=0;BOX64_DYNAREC_FASTROUND=0 BOX64_AVX=2")
endif()
if(NOT ANDROID)
@@ -1358,3 +1629,141 @@ foreach(file ${extension_tests})
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
endforeach()
endif()
if(BOX32)
add_test(NAME bootSyscall_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test01 -D TEST_OUTPUT=tmpfile32_01.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref01.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME bootSyscallC_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test02 -D TEST_OUTPUT=tmpfile32_02.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref02.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME printf_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test03 -D TEST_OUTPUT=tmpfile32_03.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref03.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME args_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test04 -D TEST_ARGS2=yeah -D TEST_OUTPUT=tmpfile32_04.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref04.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME maths1_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test05 -D TEST_ARGS2=7 -D TEST_OUTPUT=tmpfile32_05.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref05.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME threadsStart_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test06 -D TEST_OUTPUT=tmpfile32_06.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref06.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME trig_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test07 -D TEST_OUTPUT=tmpfile32_07.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref07.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME pi_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test08 -D TEST_OUTPUT=tmpfile32_08.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref08.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME fork_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test09 -D TEST_OUTPUT=tmpfile32_09.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref09.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
if(NOT CI)
add_test(NAME cppThreads_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test10 -D TEST_OUTPUT=tmpfile32_10.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref10.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(cppThreads_32bits PROPERTIES ENVIRONMENT "BOX64_LD_LIBRARY_PATH=${CMAKE_SOURCE_DIR}/x86lib")
endif()
add_test(NAME tlsData_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test11 -D TEST_OUTPUT=tmpfile32_11.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref11.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME fpu_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test12 -D TEST_OUTPUT=tmpfile32_12.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref12.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME contexts_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test13 -D TEST_OUTPUT=tmpfile32_13.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref13.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
if(NOT LD80BITS)
add_test(NAME conditionalThreads_32bits_nocosim COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test14 -D TEST_OUTPUT=tmpfile32_14.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref14.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
endif()
add_test(NAME linkingIndirectNoversion_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test15 -D TEST_OUTPUT=tmpfile32_15.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref15.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME linkingIndirectVersion_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test16 -D TEST_OUTPUT=tmpfile32_16.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref16.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME sse_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test17 -D TEST_OUTPUT=tmpfile32_17.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref17.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(sse_32bits PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTNAN=0;BOX64_DYNAREC_FASTROUND=0")
add_test(NAME longjumpInSignals_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test18 -D TEST_OUTPUT=tmpfile32_18.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref18.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME x87_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test19 -D TEST_OUTPUT=tmpfile32_19.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref19.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(x87_32bits PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTROUND=0")
add_test(NAME idiv_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test20 -D TEST_OUTPUT=tmpfile32_20.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref20.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME multiple_dlopen_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test21 -D TEST_OUTPUT=tmpfile32_21.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref21.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests32/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
add_test(NAME "${testname}_32bits" COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/extensions/${testname} -D TEST_OUTPUT=tmpfile32_-${testname}.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/extensions/${testname}.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
endforeach()
#add_test(NAME sse_optimized_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test17_o2 -D TEST_OUTPUT=tmpfile32_17_o2.txt
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref17_o2.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
#set_tests_properties(sse_optimized_32bits PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTNAN=0;BOX64_DYNAREC_FASTROUND=0")
add_test(bswap_32bits ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test23 -D TEST_OUTPUT=tmpfile32_23.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref23.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
endif()
-12
View File
@@ -1,12 +0,0 @@
all: dumpSigs
dumpSigs: main.o registered_structs.o
g++ -g3 -std=gnu++17 -fno-rtti main.o registered_structs.o -o dumpSigs "-L$(LLVM_install_dir)/lib" -lclang-cpp -lclangTooling -Wl,-rpath "-Wl,$(LLVM_install_dir)/lib"
main.o: main.cpp
g++ -g3 -std=gnu++17 -fno-rtti -c main.cpp -Wfatal-errors "-I$(LLVM_install_dir)/include" -o main.o
registered_structs.o: registered_structs.cpp
g++ -g3 -std=gnu++17 -fno-rtti -c registered_structs.cpp -Wfatal-errors -o registered_structs.o
clean:
$(RM) dumpSigs main.o registered_structs.o
-458
View File
@@ -1,458 +0,0 @@
#include <algorithm>
#include <fstream>
#include <iostream>
#include <numeric>
#include <unordered_map>
#include <utility>
#include <vector>
#include <llvm/Support/raw_ostream.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/AST/Decl.h>
#include <clang/AST/Mangle.h>
#include <clang/AST/PrettyPrinter.h>
#include <clang/AST/RecursiveASTVisitor.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/Tooling/CommonOptionsParser.h>
#include <clang/Tooling/Tooling.h>
clang::MangleContext *mangler = nullptr;
std::unordered_map<std::string, std::pair<std::string, bool>> funMap;
std::vector<std::string> funList;
bool isTypeTrivial(const clang::QualType &q, const clang::QualType *qorig);
clang::QualType getPointedType(const clang::QualType q) {
if (const clang::PointerType *p = q->getAs<clang::PointerType>())
return getPointedType(p->getPointeeType());
else if (const clang::ReferenceType *r = q->getAs<clang::ReferenceType>())
return getPointedType(r->getPointeeType());
else
return q;
}
std::string record2name(const clang::RecordDecl &q, const clang::QualType *qorig) {
std::string s = q.getNameAsString();
if (s == "") {
if (!qorig) return "????.!";
if (const clang::TypedefType *tt = (*qorig)->getAs<clang::TypedefType>()) {
// Typedef
if (clang::TypedefNameDecl *td = tt->getDecl()) {
return td->getNameAsString();
} else {
return "<typedef with no declaration>";
}
} else {
return std::string("<unknown type ") + (*qorig)->getTypeClassName() + ">";
}
} else {
return s;
}
}
char ptr2char(const std::string &str) __attribute__((const));
const char *ptr2str(const std::string &str) __attribute__((const));
char type2char(const clang::QualType &qual /* Canonical */, const clang::QualType *qorig) {
if (qual->isBuiltinType()) {
switch (static_cast<const clang::BuiltinType&>(*qual).getKind()) {
case clang::BuiltinType::Kind::Void:
return 'v';
case clang::BuiltinType::Kind::Bool:
return 'i';
case clang::BuiltinType::Kind::Char_U:
return 'C';
case clang::BuiltinType::Kind::Char_S:
return 'c';
case clang::BuiltinType::Kind::Char8:
return 'c';
case clang::BuiltinType::Kind::UChar:
return 'C';
case clang::BuiltinType::Kind::SChar:
return 'c';
case clang::BuiltinType::Kind::WChar_U:
return 'W';
case clang::BuiltinType::Kind::UShort:
return 'W';
case clang::BuiltinType::Kind::WChar_S:
return 'w';
case clang::BuiltinType::Kind::Char16:
return 'w';
case clang::BuiltinType::Kind::Short:
return 'w';
case clang::BuiltinType::Kind::UInt:
return 'u';
case clang::BuiltinType::Kind::Char32:
return 'i';
case clang::BuiltinType::Kind::Int:
return 'i';
case clang::BuiltinType::Kind::ULong:
return 'L';
case clang::BuiltinType::Kind::Long:
return 'l';
case clang::BuiltinType::Kind::ULongLong:
return 'U';
case clang::BuiltinType::Kind::LongLong:
return 'I';
case clang::BuiltinType::Kind::UInt128:
return 'H';
case clang::BuiltinType::Kind::Int128:
return 'H';
case clang::BuiltinType::Kind::Float:
return 'f';
case clang::BuiltinType::Kind::Double:
return 'd';
case clang::BuiltinType::Kind::LongDouble:
return 'D';
case clang::BuiltinType::Kind::NullPtr:
return 'p'; // nullptr_t
case clang::BuiltinType::Kind::Half:
case clang::BuiltinType::Kind::BFloat16:
case clang::BuiltinType::Kind::ShortAccum:
case clang::BuiltinType::Kind::Accum:
case clang::BuiltinType::Kind::LongAccum:
case clang::BuiltinType::Kind::UShortAccum:
case clang::BuiltinType::Kind::UAccum:
case clang::BuiltinType::Kind::ULongAccum:
case clang::BuiltinType::Kind::ShortFract:
case clang::BuiltinType::Kind::Fract:
case clang::BuiltinType::Kind::LongFract:
case clang::BuiltinType::Kind::UShortFract:
case clang::BuiltinType::Kind::UFract:
case clang::BuiltinType::Kind::ULongFract:
case clang::BuiltinType::Kind::SatShortAccum:
case clang::BuiltinType::Kind::SatAccum:
case clang::BuiltinType::Kind::SatLongAccum:
case clang::BuiltinType::Kind::SatUShortAccum:
case clang::BuiltinType::Kind::SatUAccum:
case clang::BuiltinType::Kind::SatULongAccum:
case clang::BuiltinType::Kind::SatShortFract:
case clang::BuiltinType::Kind::SatFract:
case clang::BuiltinType::Kind::SatLongFract:
case clang::BuiltinType::Kind::SatUShortFract:
case clang::BuiltinType::Kind::SatUFract:
case clang::BuiltinType::Kind::SatULongFract:
case clang::BuiltinType::Kind::Float16:
case clang::BuiltinType::Kind::Float128:
case clang::BuiltinType::Kind::Overload:
case clang::BuiltinType::Kind::BoundMember:
case clang::BuiltinType::Kind::PseudoObject:
case clang::BuiltinType::Kind::Dependent:
case clang::BuiltinType::Kind::UnknownAny:
case clang::BuiltinType::Kind::ARCUnbridgedCast:
case clang::BuiltinType::Kind::BuiltinFn:
case clang::BuiltinType::Kind::ObjCId:
case clang::BuiltinType::Kind::ObjCClass:
case clang::BuiltinType::Kind::ObjCSel:
#define IMAGE_TYPE(it, id, si, a, s) case clang::BuiltinType::Kind::id:
#include <clang/Basic/OpenCLImageTypes.def>
#undef IMAGE_TYPE
case clang::BuiltinType::Kind::OCLSampler:
case clang::BuiltinType::Kind::OCLEvent:
case clang::BuiltinType::Kind::OCLClkEvent:
case clang::BuiltinType::Kind::OCLQueue:
case clang::BuiltinType::Kind::OCLReserveID:
case clang::BuiltinType::Kind::IncompleteMatrixIdx:
case clang::BuiltinType::Kind::OMPArraySection:
case clang::BuiltinType::Kind::OMPArrayShaping:
case clang::BuiltinType::Kind::OMPIterator:
#define EXT_OPAQUE_TYPE(et, id, e) case clang::BuiltinType::Kind::id:
#include <clang/Basic/OpenCLExtensionTypes.def>
#define SVE_TYPE(n, id, si) case clang::BuiltinType::Kind::id:
#include <clang/Basic/AArch64SVEACLETypes.def>
#define PPC_VECTOR_TYPE(n, id, s) case clang::BuiltinType::Kind::id:
#include <clang/Basic/PPCTypes.def>
#undef EXT_OPAQUE_TYPE
#undef SVE_TYPE
#undef PPC_VECTOR_TYPE
return '!';
default:
return ':';
}
} else if (qual->isEnumeralType()) {
const clang::EnumDecl *ed = qual->getAs<clang::EnumType>()->getDecl();
if (!ed) {
return 'i';
} else {
return type2char(ed->getIntegerType().getCanonicalType(), qorig);
}
} else if (qual->isFunctionPointerType()) {
return '@';
} else if (qual->isAnyPointerType() || qual->isReferenceType()) {
const clang::QualType &pointed = getPointedType(qual);
if (isTypeTrivial(pointed, qorig)) {
return 'p';
} else if (const clang::RecordType *rct = pointed->getAs<clang::RecordType>()) {
clang::RecordDecl *rc = rct->getDecl();
if (!rc) {
return '!';
} else if (!rc->isCompleteDefinition()) {
return 'p';
} else {
std::string str;
if (qorig) {
const clang::QualType qpted = getPointedType(*qorig);
str = record2name(*rc, &qpted);
} else {
str = record2name(*rc, nullptr);
}
char ret = ptr2char(str);
if (ret) return ret;
else {
return '!';
}
}
} else {
return '!';
}
} else if (const clang::RecordType *rct = qual->getAs<clang::RecordType>()) {
clang::RecordDecl *rc = rct->getDecl();
if (!rc) {
return '?';
} else if (rc->getNameAsString() == "__builtin_va_list") {
// va_list
return 'A';
} else {
return '?';
}
} else {
return '?';
}
}
bool isTypeTrivial(const clang::QualType &q, const clang::QualType *qorig) {
const char c = type2char(q, qorig);
#define GO(chr) || (c == chr)
return (c == 'v')
GO('i') GO('u')
GO('I') GO('U')
GO('l') GO('L')
GO('f') GO('d')
GO('D') GO('K')
GO('0') GO('1')
GO('C') GO('c')
GO('W') GO('w')
GO('H')
GO('p');
#undef GO
}
bool isTypeValid(const clang::QualType &q, const clang::QualType *qorig) {
const char c = type2char(q, qorig);
if (c == 'A') return false;
if (c == 'V') return false;
return ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'));
}
const std::string type2string(const clang::QualType &qual, const clang::QualType *qorig) {
if (qual->isBuiltinType()) {
return std::string("(builtin) ") + static_cast<const clang::BuiltinType&>(*qual).getName(clang::PrintingPolicy{{}}).data();
} else if (qual->isFunctionPointerType()) {
return "Callback (function pointer)";
} else if (qual->isAnyPointerType() || qual->isReferenceType()) {
std::string prefix = qual->isAnyPointerType() ? "Pointer to " : "Reference to ";
const clang::QualType &pointed = getPointedType(qual);
if (isTypeTrivial(pointed, qorig)) {
return prefix + "trivial object " + type2string(pointed, qorig) + " (" + type2char(pointed, qorig) + ")";
} else if (const clang::RecordType *rct = pointed->getAs<clang::RecordType>()) {
clang::RecordDecl *rc = rct->getDecl();
if (!rc) {
return prefix + "unknown record";
} else if (!rc->isCompleteDefinition()) {
return prefix + "incomplete record " + rc->getNameAsString();
} else {
std::string str;
if (qorig) {
const clang::QualType qpted = getPointedType(*qorig);
str = record2name(*rc, &qpted);
} else {
str = record2name(*rc, nullptr);
}
const char *ret = ptr2str(str);
if (ret[0] != '\0') {
return prefix + ret;
} else {
if (mangler && mangler->shouldMangleDeclName(rc)) {
std::string mangled;
{
llvm::raw_string_ostream strstr{mangled};
mangler->mangleName(rc, strstr);
}
return prefix + "unknown record " + str + " (=== " + mangled + ")";
} else {
return prefix + "unknown record " + str;
}
}
}
} else {
return prefix + "non-trivial or typedef'ed object " + type2string(pointed, qorig) + " (" + type2char(pointed, qorig) + ")";
//return "Pointer (maybe to callback)";
}
} else if (qual->isEnumeralType()) {
const clang::EnumDecl *ed = qual->getAs<clang::EnumType>()->getDecl();
if (!ed) {
return "Enumeration with unknown underlying integer type (assuming int)";
} else {
return "Enumeration with underlying type " + type2string(ed->getIntegerType().getCanonicalType(), nullptr);
}
} else if (const clang::RecordType *rct = qual->getAs<clang::RecordType>()) {
clang::RecordDecl *rc = rct->getDecl();
if (!rc) {
return "Unknown record";
} else if (rc->getNameAsString() == "__builtin_va_list") {
return "va_list";
} else {
return "Unknown record " + std::string(rc->getName().data());
}
} else {
return std::string("??? ") + qual->getTypeClassName();
}
}
class Visitor : public clang::RecursiveASTVisitor<Visitor> {
public:
clang::ASTContext &context;
bool shouldVisitTemplateInstantiations() const /* override */ { return true; }
Visitor(clang::CompilerInstance &ci) : context(ci.getASTContext()) {
if (!mangler) {
mangler = clang::ItaniumMangleContext::create(context, ci.getDiagnostics());
}
}
~Visitor() {
if (mangler) {
delete mangler;
mangler = nullptr;
}
}
bool VisitDecl(clang::Decl *decl) /* override */ {
std::cerr << std::flush;
if (!decl) return true;
if ((decl->getKind() >= clang::Decl::Kind::firstFunction) && (decl->getKind() <= clang::Decl::Kind::lastFunction)) {
clang::DeclaratorDecl *ddecl = static_cast<clang::DeclaratorDecl*>(decl);
std::cout << "Function detected!\n";
std::string funName{ddecl->getName()};
auto niceprint = [](const std::string &infotype, const auto &dat){ std::cout << " " << infotype << ": " << dat << "\n"; };
niceprint("Function name", funName);
if (mangler && mangler->shouldMangleDeclName(ddecl)) {
std::string mangled;
{
llvm::raw_string_ostream strstr{mangled};
mangler->mangleName(ddecl, strstr);
}
niceprint("Function mangled name", mangled);
funName = std::move(mangled);
}
bool valid;
std::string funTypeStr{""};
if (ddecl->getFunctionType()->isFunctionNoProtoType()) {
const clang::FunctionNoProtoType *funType = static_cast<const clang::FunctionNoProtoType*>(ddecl->getFunctionType());
const auto &retType = funType->getReturnType();
niceprint("Function return type", type2string(retType, &retType));
niceprint("Canonical function return type",
type2string(retType.getCanonicalType(), &retType) +
" (" + type2char(retType.getCanonicalType(), &retType) + ")");
niceprint("Is sugared", funType->isSugared());
if (funType->isSugared()) {
clang::QualType qft{funType, 0};
niceprint("Desugared", type2string(funType->desugar(), &qft));
}
funTypeStr = type2char(retType.getCanonicalType(), &retType) + std::string("Fv");
valid = isTypeValid(retType.getCanonicalType(), &retType);
} else {
const clang::FunctionProtoType *funType = static_cast<const clang::FunctionProtoType*>(ddecl->getFunctionType());
const auto &retType = funType->getReturnType();
niceprint("Function return type", type2string(retType, &retType));
niceprint("Canonical function return type",
type2string(retType.getCanonicalType(), &retType)
+ " (" + type2char(retType.getCanonicalType(), &retType) + ")");
niceprint("Parameter count", funType->getNumParams());
for (const clang::QualType &type : funType->getParamTypes()) {
niceprint(" " + type2string(type, &type),
type2string(type.getCanonicalType(), &type) + " (" + type2char(type.getCanonicalType(), &type) + ")");
}
niceprint("Variadic function", funType->isVariadic() ? "yes" : "no");
funTypeStr =
type2char(retType.getCanonicalType(), &retType) +
((funType->getNumParams() == 0)
? std::string("Fv") : std::accumulate(funType->getParamTypes().begin(), funType->getParamTypes().end(), std::string("F"),
[](const std::string &acc, const clang::QualType &qual){ return acc + type2char(qual.getCanonicalType(), &qual); }));
if (funType->isVariadic()) funTypeStr += "V";
valid = !funType->isVariadic() &&
std::accumulate(funType->getParamTypes().begin(), funType->getParamTypes().end(), isTypeValid(retType.getCanonicalType(), &retType),
[](bool acc, const clang::QualType &qual){ return acc && isTypeValid(qual.getCanonicalType(), &qual); });
}
niceprint("Conclusion", "");
niceprint("Function final name", funName);
niceprint("Function type", funTypeStr);
niceprint("Valid function type", valid ? "yes" : "no");
std::cout << "\n";
funMap[funName] = std::make_pair(funTypeStr, valid);
funList.push_back(funName);
}
return true;
}
};
class Consumer : public clang::ASTConsumer {
public:
Visitor visitor;
Consumer(clang::CompilerInstance &ci) : visitor(ci) {
}
void HandleTranslationUnit(clang::ASTContext &context) override {
visitor.TraverseDecl(context.getTranslationUnitDecl());
}
};
class Action : public clang::ASTFrontendAction {
public:
virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef inFile) override {
return std::make_unique<Consumer>(ci);
}
};
int main(int argc, const char **argv) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " (filenames) -- [-I...]" << std::endl;
return 2;
}
/*int fakeargc = argc + 1;
const char **fakeargv = new const char*[fakeargc];
memcpy(fakeargv, argv, argc * sizeof(char*));
fakeargv[fakeargc - 1] = "--";*/
llvm::cl::OptionCategory opcat{""};
clang::tooling::CommonOptionsParser op{argc, argv, opcat};
std::vector<std::string> paths; for (int i = 1; i < argc; ++i) paths.push_back(argv[i]);
clang::tooling::ClangTool tool{op.getCompilations(), paths};
tool.run(clang::tooling::newFrontendActionFactory<Action>().get());
std::cout << "Done, outputing output.h" << std::endl;
std::sort(funList.begin(), funList.end());
std::fstream file{"output.h", std::ios_base::out};
for (const std::string &funName : funList) {
if (!funMap[funName].second) {
file << "//";
}
file << "GO(" << funName << ", " << funMap[funName].first << ")\n";
}
return 0;
}
-267
View File
@@ -1,267 +0,0 @@
#include <string>
#define ALL START() \
/* libc */ \
STRUCT("_IO_FILE", "a FILE") \
STRUCT("_G_fpos_t", "a file position") \
STRUCT("sockaddr", "a socket address") \
STRUCT("itimerspec", "an itimerspec") \
STRUCT("timespec", "a timespec") \
STRUCT("itimerval", "an itimerval") \
STRUCT("timeval", "a timeval") \
STRUCT("timex", "a timex") \
STRUCT("timezone", "a timezone") \
STRUCT("dirent", "a dirent") \
STRUCT("dirent64", "a dirent64") \
STRUCT("__dirstream", "a dir stream") \
STRUCT("tm", "a time structure (tm)") \
STRUCT("cmsghdr", "a cmsghdr") \
STRUCT("msghdr", "a msghdr") \
STRUCT("rpcent", "an rpcent") \
STRUCT("random_data", "a random_data structure") \
STRUCT("drand48_data", "a drand48_data structure") \
STRUCT("termios", "a termios") \
STRUCT("iovec", "an iovec") \
STRUCT("file_handle", "a file handle") \
STRUCT("lconv", "an lconv") \
STRUCT("__locale_struct", "a locale structure") \
STRUCT("aliasent", "an alias") \
STRUCT("fstab", "an fstab") \
STRUCT("group", "a group") \
STRUCT("hostent", "a hostent") \
STRUCT("protoent", "a protoent") \
STRUCT("passwd", "a password") \
STRUCT("spwd", "an spwd") \
STRUCT("ttyent", "a ttyent") \
STRUCT("utmp", "an utmp structure") \
STRUCT("utmpx", "an utmpx structure") \
STRUCT("ifaddrs", "an ifaddrs structure") \
STRUCT("statfs", "a statfs structure") \
STRUCT("statfs64", "a statfs64 structure") \
STRUCT("statvfs", "a statvfs structure") \
STRUCT("statvfs64", "a statvfs64 structure") \
STRUCT("timeb", "a timeb structure") \
STRUCT("_ftsent", "an _ftsent structure") \
STRUCT("sysinfo", "a sysinfo structure") \
STRUCT("rlimit", "an rlimit structure") \
STRUCT("rlimit64", "an rlimit64 structure") \
STRUCT("rusage", "an rusage structure") \
STRUCT("entry", "an entry structure") \
STRUCT("pollfd", "a pollfd structure") \
STRUCT("re_pattern_buffer", "a re_pattern_buffer structure") \
STRUCT("sembuf", "a sembuf structure") \
STRUCT("tms", "a tms structure") \
STRUCT("utsname", "an utsname structure") \
STRUCT("utimbuf", "an utimbuf structure") \
STRUCT2("__va_list_tag", "__va_list_tag (aka, a va_list)", 'A') \
/* ncurses */ \
STRUCT("_win_st", "a _win_st structure") \
STRUCT("MEVENT", "an MEVENT structure") \
TYPEDEF("cchar_t", "a cchar_t") \
/* zlib */ \
STRUCT("gz_header_s", "a gz_header_s structure") \
STRUCT("gzFile_s", "a gzFile_s structure") \
STRUCT("z_stream_s", "a z_stream_s structure") \
\
END()
#define START()
#define STRUCT(s, ret) if (str == s) { return 'p'; } else
#define STRUCT2(s, ret, c) if (str == s) { return c; } else
#define TYPEDEF(s, ret) if (str == s) { return 'p'; } else
#define END() { return 0; }
char ptr2char(const std::string &str) {
/*if ((str == "_IO_FILE")
|| (str == "_G_fpos_t")
|| (str == "sockaddr")
|| (str == "itimerspec")
|| (str == "timespec")
|| (str == "itimerval")
|| (str == "timeval")
|| (str == "timex")
|| (str == "timezone")
|| (str == "dirent")
|| (str == "dirent64")
|| (str == "__dirstream")
|| (str == "tm")
|| (str == "cmsghdr")
|| (str == "msghdr")
|| (str == "rpcent")
|| (str == "random_data")
|| (str == "drand48_data")
|| (str == "termios")
|| (str == "iovec")
|| (str == "file_handle")
|| (str == "lconv")
|| (str == "__locale_struct")
|| (str == "aliasent")
|| (str == "fstab")
|| (str == "group")
|| (str == "hostent")
|| (str == "protoent")
|| (str == "passwd")
|| (str == "spwd")
|| (str == "ttyent")
|| (str == "utmp")
|| (str == "utmpx")
|| (str == "ifaddrs")
|| (str == "statfs")
|| (str == "statfs64")
|| (str == "statvfs")
|| (str == "timeb")
|| (str == "_ftsent")
|| (str == "sysinfo")
|| (str == "rlimit")
|| (str == "rlimit64")
|| (str == "rusage")
|| (str == "entry")
|| (str == "pollfd")
|| (str == "re_pattern_buffer")
|| (str == "sembuf")
|| (str == "tms")
|| (str == "utsname")
|| (str == "utimbuf")
// ncurses
|| (str == "_win_st")
|| (str == "cchar_t")
) {
// FILE*, fpos_t*, ...
return 'p';
} else if (str == "__va_list_tag") {
return 'A';
} else {
return 0;
}*/
ALL
}
#undef END
#undef TYPEDEF
#undef STRUCT2
#undef STRUCT
#undef START
#define START()
#define STRUCT(s, ret) if (str == s) { return ret; } else
#define STRUCT2(s, ret, c) if (str == s) { return ret; } else
#define TYPEDEF(s, ret) if (str == s) { return ret; } else
#define END() return "";
const char *ptr2str(const std::string &str) {
/*if (str == "_IO_FILE") {
return "a FILE";
} else if (str == "_G_fpos_t") {
return "a file position";
} else if (str == "sockaddr") {
return "a socket address";
} else if (str == "itimerspec") {
return "an itimerspec";
} else if (str == "timespec") {
return "a timespec";
} else if (str == "itimerval") {
return "an itimerval";
} else if (str == "timeval") {
return "a timeval";
} else if (str == "timex") {
return "a timex";
} else if (str == "timezone") {
return "a timezone";
} else if (str == "dirent") {
return "a dirent";
} else if (str == "dirent64") {
return "a dirent64";
} else if (str == "__dirstream") {
return "a dir stream";
} else if (str == "tm") {
return "a time structure (tm)";
} else if (str == "cmsghdr") {
return "a cmsghdr";
} else if (str == "msghdr") {
return "a msghdr";
} else if (str == "rpcent") {
return "an rpcent";
} else if (str == "random_data") {
return "a random_data structure";
} else if (str == "drand48_data") {
return "a drand48_data structure";
} else if (str == "termios") {
return "a termios";
} else if (str == "iovec") {
return "an iovec";
} else if (str == "file_handle") {
return "a file handle";
} else if (str == "lconv") {
return "an lconv";
} else if (str == "__locale_struct") {
return "a locale structure";
} else if (str == "aliasent") {
return "an alias";
} else if (str == "fstab") {
return "an fstab";
} else if (str == "group") {
return "a group";
} else if (str == "hostent") {
return "a hostent";
} else if (str == "protoent") {
return "a protoent";
} else if (str == "passwd") {
return "a password";
} else if (str == "spwd") {
return "an spwd";
} else if (str == "ttyent") {
return "a ttyent";
} else if (str == "utmp") {
return "an utmp structure";
} else if (str == "utmpx") {
return "an utmpx structure";
} else if (str == "ifaddrs") {
return "an ifaddrs structure";
} else if (str == "statfs") {
return "a statfs structure";
} else if (str == "statfs64") {
return "a statfs64 structure";
} else if (str == "statvfs") {
return "a statvfs structure";
} else if (str == "statvfs64") {
return "a statvfs64 structure";
} else if (str == "timeb") {
return "a timeb structure";
} else if (str == "_ftsent") {
return "an _ftsent structure";
} else if (str == "sysinfo") {
return "a sysinfo structure";
} else if (str == "rlimit") {
return "an rlimit structure";
} else if (str == "rlimit64") {
return "an rlimit64 structure";
} else if (str == "rusage") {
return "an rusage structure";
} else if (str == "entry") {
return "an entry structure";
} else if (str == "pollfd") {
return "a pollfd structure";
} else if (str == "re_pattern_buffer") {
return "a re_pattern_buffer structure";
} else if (str == "sembuf") {
return "a sembuf structure";
} else if (str == "tms") {
return "a tms structure";
} else if (str == "utsname") {
return "an utsname structure";
} else if (str == "utimbuf") {
return "an utimbuf structure";
} else if (str == "__va_list_tag") {
return "__va_list_tag (aka, a va_list)";
// ncurses
} else if (str == "_win_st") {
return "a _win_st structure";
} else if (str == "cchar_t") {
return "a cchar_t";
} else return "";*/
ALL
}
#undef END
#undef TYPEDEF
#undef STRUCT2
#undef STRUCT
#undef START
+88 -104
View File
@@ -1,112 +1,95 @@
![Official logo](docs/img/Box64Logo.png "Official Logo")
Linux Userspace x86_64 Emulator with a twist
# Box64: Linux Userspace x86-64 Emulator with a Twist
[View changelog](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md) | [Report an error](https://github.com/ptitSeb/box64/issues/new)
[Changelog](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md) | [Report an Error](https://github.com/ptitSeb/box64/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main) ![stars](https://img.shields.io/github/stars/ptitSeb/box64) ![forks](https://img.shields.io/github/forks/ptitSeb/box64) ![contributors](https://img.shields.io/github/contributors/ptitSeb/box64) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box64) ![issues](https://img.shields.io/github/issues/ptitSeb/box64)
![Build Status](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main) ![Stars](https://img.shields.io/github/stars/ptitSeb/box64) ![Forks](https://img.shields.io/github/forks/ptitSeb/box64) ![Contributors](https://img.shields.io/github/contributors/ptitSeb/box64) ![Pull Requests](https://img.shields.io/github/issues-pr/ptitSeb/box64) ![Issues](https://img.shields.io/github/issues/ptitSeb/box64)
---
Box64 enables running x86_64 Linux programs, including games, on non-x86_64 Linux systems such as Arm (64-bit little-endian host system required).
Check out Box64 in action on YouTube:
- [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)
- [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)
- [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA)
Box64 leverages native system libraries (libc, libm, SDL, OpenGL), offering ease of integration and surprising performance in many applications. For performance benchmarks, check [this analysis](https://box86.org/index.php/2021/06/game-performances/).
With DynaRec for ARM64, RV64 and LA64 platforms, Box64 achieves a speed boost 5-10x faster than the interpreter alone. For a deeper look at DynaRec, see [Inner workings](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
<img src="docs/img/Box64Icon.png" width="96" height="96" alt="Box64 Icon">
_Logo and icon by @grayduck - Thank you!_
---
## 📖 Usage
Box64 offers environment variables to control its behavior. For details, see [Usage Documentation](docs/USAGE.md).
---
## 🚀 Compiling and Installation
- [Compilation Instructions](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md)
- [Wine Installation for Box64](https://github.com/ptitSeb/box64/blob/main/docs/X64WINE.md)
---
## 🔄 Version History
See the [Changelog](docs/CHANGELOG.md) for version updates.
---
## 🖥️ Platform Compatibility Notes
Box64 requires 64-bit libraries on the host system, as it directly translates x86_64 function calls. For 32-bit binaries, use Box86.
**Notes**
1. Box32 mode is in the making, which aims to support 32-bit binaries on Box64, you can enable it at build time, but do not expect everything to work. There is actually a few things that works, amny that don't. It's a known issue, no need to create tickets about it for now.
2. Some installers may default to x86 on 64-bit host OSes, causing compatibility issues. Workaround: Use a fake `uname` that returns "x86_64" for `-m`.
---
## ⚙️ Configuration
Box64 has configuration files located in `/etc/box64.box64rc` and `~/.box64rc`, both formatted as `.ini` files. If you don’t want to use the default `/etc/box64.box64rc` file, copy it to `~/.box64rc` to ensure compatibility.
Settings priority: `~/.box64rc` > `/etc/box64.box64rc` > Command line.
---
## 📄 Additional Platform-Specific Notes
### Unity Game Emulation
- Many Unity games require OpenGL 3+, which may be challenging on ARM/RISC-V SBCs.
- **Tip for Pi4 and Pi5 Users**: Set `MESA_GL_VERSION_OVERRIDE=3.2` with `BOX64_DYNAREC_STRONGMEM=1` to prevent freezes and enable strong memory mode.
- **Using Panfrost**: For better compatibility on ARM, enable `PAN_MESA_DEBUG=gl3` to force higher OpenGL profiles. This can help if a game starts but quits unexpectedly before showing any content.
### GTK Programs
Box64 wraps GTK libraries, supporting both gtk2 and gtk3.
### Steam
Steam requires Box86 due to its 32-bit client app, but uses 64-bit local server binaries. Systems with less than 6GB RAM may need a swap file for optimal performance.
### Wine
Box64 supports Wine64 and Proton. For 32-bit components, Box86 is required. Systems with both Box64 and Box86 can run 32- and 64-bit Windows programs.
**Note**: You can use Wine WOW64 build to run x86 Windows programs in Box64-only environments, this is still experimental, but it works in most cases.
### Vulkan
Box64 wraps Vulkan libraries.
----
Box64 lets you run x86_64 Linux programs (such as games) on non-x86_64 Linux systems, like ARM (host system needs to be 64-bit little-endian).
You can find many Box64 videos on the [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) or [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) YouTube channels.
Since Box64 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at thoses bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
Box64 integrates with DynaRec (dynamic recompiler) for the ARM64 and RV64 platform, providing a speed boost between 5 to 10 times faster than using only the interpreter. Some high level information on how DynaRec works can be found [here](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
Some x64 internal opcodes use parts of "Realmode X86 Emulator Library", see [x64primop.c](src/emu/x64primop.c) for copyright details
<img src="docs/img/Box64Icon.png" width="96" height="96">
Logo and Icon made by @grayduck, thanks!
----
Usage
----
There are a few environment variables to control the behaviour of Box64.
See [here](docs/USAGE.md) for all the environment variables and what they do.
Note: Box64's Dynarec uses a mechanism with Memory Protection and a SegFault signal handler to handle JIT code. In simpler terms, if you want to use GDB to debug a running program that use JIT'd code (like mono/Unity3D), you will still have many "normal" segfaults triggering. It is suggested to use something like `handle SIGSEGV nostop` in GDB to not stop at each segfault, and maybe put a breakpoint inside `my_memprotectionhandler` in `signals.c` if you want to trap SegFaults.
----
Compiling/Installation
----
> Compilation instructions can be found [here](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md) \
> Instructions for installing Wine for Box64 can be found [here](https://github.com/ptitSeb/box64/blob/main/docs/X64WINE.md)
----
Version history/Change log
----
The change log is available [here](docs/CHANGELOG.md).
----
Notes about 32-bit platforms
----
Because Box64 works by directly translating function calls from x86_64 to host system, the host system (the one Box64 is running on) needs to have 64-bit libraries. Box64 doesn't include any 64-bit <-> 32-bit translation.
So understand that box64 will only run 64-bit linux binaries. For 32-bit binaries, you need box86 (with all the multiarch or proot trickery it implies on a 64-bit OS).
Note that many installer (mojo setup based) will fall back to "x86" when detecting ARM64 OS, and so will try to use box86 for the setup, even if an x86_64 version exist. You can hack your way around with a fake "uname" that return "x86_64" when the argument is "-m"
An alternative solution is to use Wine with new WoW64, but you will be limited to 32bits windows apps and games.
----
Notes about Box64 configuration
----
Box64 now have configurations files. There are 2 files loaded. `/etc/box64.box64rc` and `~/.box64rc`. Both files have the same syntax, and is basicaly an ini files. Section in square brakets define the process name, and the rest is the env. var. to set. Looke at [Usage](USAGE.md) for detail on what parameters can be put. Box64 comes with a default file that should be installed for better stability. The file in in `system/box64.box64rc` and should be installed to `/etc/box64.box64rc` If, for some reason, you don't want to install that file here, at least copy it to `~/.box64rc` or some game may not function correctly.
Note that the priority is: `~/.box64rc` > `/etc/box64.box64rc` > command line
So, your settings in `~/.box64rc` may override the setting from your command line...
----
Notes about Unity game emulation
----
Running Unity games should just work, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers). Also many newer Unity3D (like KSP) games use the BC7 compressed textures, which is not supported on many ARM integrated GPU.
Hint: on Pi4, use `MESA_GL_VERSION_OVERRIDE=3.2` and with Panfrost use `PAN_MESA_DEBUG=gl3` to use higher profile if the game starts then quits before showing anything.
----
Notes about GTK programs
----
GTK libraries are now wrapped on box64, both gtk2 and gtk3.
----
Notes about Steam
----
Note that Steam is a hybrid 32-bit / 64-bit. You NEED box86 to run Steam, as the client app is a 32-bit binary. It also uses a 64-bit local server binaries, and that steamwebhelper process is now mandatory, even on the "small mode". And that process will eat lots of memory. So machine with less the 6Gb of RAM will need a swapfile to use Steam.
----
Notes about Wine
----
Wine64 is supported on box64. Proton too. Be aware that 64-bit Wine also includes 32-bit components, to be able to run 32-bit Windows programs. The 32-bit apps will need box86 and will not run without it. On a system where both box64 and box86 are present and working, a wine 64-bit setup can run both 32-bit and 64-bit Windows programs (just use `wine` and `wine64` respectively).
Note that the new 32-bit PE in 64-bit processes that the Wine team is currently implementing in Wine 7.+ is now supported. It's called "new WoW64" and it's working fine on box64, allowing the use of 32bits windows program on 64bits only system.
----
Notes about Vulkan
----
Box64 wraps Vulkan libraries, but note that it as mostly been tested with an AMD RX550 card and on the Freedreno driver, so some extensions may be missing depending on your graphics card.
----
Final word
----
@@ -114,7 +97,7 @@ I want to thank everyone who has contributed to box64 development.
There are many ways to contribute: code contribution, financial, hardware and advertisement!
So, in no particular order, I want to thank:
* For their major code contribution: rajdakin, mogery, ksco, xctan
* For their major financial contribution: [Playtron](https://playtron.one), FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/), [CubeCoders Limited](http://cubecoders.com/)
* For their major financial contribution: [Playtron](https://playtron.one), tohodakilla, FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/), [CubeCoders Limited](http://cubecoders.com/)
* For hardware contribution and LoongArch migration: [xiaoji](https://www.linuxgame.cn/), Deepin Beijing Develop Team
* For their hardware contribution: [ADLINK](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en) with [Ampere](https://amperecomputing.com/home/edge), [SOPHGO](https://www.sophon.ai/), [Radxa](https://rockpi.org/), [StarFive](https://rvspace.org/), [Pine64](https://www.pine64.org/), [AYN](https://www.ayntec.com/), [AYANEO](https://ayaneo.com/), [jiangcuo](https://github.com/jiangcuo)
* For their continuous advertisements for the box64 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
@@ -122,3 +105,4 @@ So, in no particular order, I want to thank:
And I also thank the many other people who participated even once in this project.
(If you use Box64 in your project, please don't forget to mention it!)
+50 -55
View File
@@ -1,97 +1,92 @@
# box64
![图标](docs/img/Box64Logo.png "图标")
![Official logo](docs/img/Box64Logo.png "Official Logo")
Linux 上用户空间的 x86_64 应用模拟器(支持运行原生库)
# Box64:Linux 用户空间 x86-64 模拟器(支持原生库)
----
![box64 build status](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main)
[更新日志](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [English](https://github.com/ptitSeb/box64/blob/main/README.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md) | [Report an Error](https://github.com/ptitSeb/box64/issues/new)
[English](docs/README.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md)
![Build Status](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main) ![Stars](https://img.shields.io/github/stars/ptitSeb/box64) ![Forks](https://img.shields.io/github/forks/ptitSeb/box64) ![Contributors](https://img.shields.io/github/contributors/ptitSeb/box64) ![Pull Requests](https://img.shields.io/github/issues-pr/ptitSeb/box64) ![Issues](https://img.shields.io/github/issues/ptitSeb/box64)
Box64 可以在非 x86_64 Linux 系统(比如 ARM64)上运行 x86_64 Linux 程序(比如游戏),注意主机系统需要是 64 位小端。
---
您可以在 [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)、[Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) 和 [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) YouTube 频道上找到许多 Box64 视频。
Box64 可以在非 x86_64 Linux 主机系统(比如 Arm)上运行 x86_64 Linux 程序(比如游戏),目前仅支持 64 位小端主机系统。
由于 Box64 使用一些“系统”库的原生版本,如 libc、libm、SDL 和 OpenGL 等,因此很容易与大多数应用程序集成和使用,并且在许多情况下性能会相当不错。可以在[这里](https://box86.org/index.php/2021/06/game-performances/)查看一些性能测试的样例。
在 YouTube 上查看 Box64 的运行效果:
- [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)
- [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)
- [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA)
Box64 集成了适用于 ARM64 和 RV64 平台的 DynaRec(动态重编译器),速度可以比纯解释模式快 5 到 10 倍。可以在[这里](https://box86.org/2021/07/inner-workings-a-high%E2%80%91level-view-of-box86-and-a-low%E2%80%91level-view-of-the-dynarec/)找到有关 DynaRec 工作原理的一些信息。
Box64 可以使用本机原生的系统库(libc、libm、SDL、OpenGL),有着易于集成的特性和令人惊讶的性能。如需性能基准测试,请查看[此分析](https://box86.org/index.php/2021/06/game-performances/)。
一些 x64 内部操作码使用 “Realmode X86 Emulator Library” 的部分内容,有关版权详细信息,请参见 [x64primop.c](../src/emu/x64primop.c)。
借助适用于 ARM64,RV64 以及 LA64 平台的 DynaRec,Box64 的速度比单独使用解释器快 5-10 倍。如需深入了解 DynaRec,请参考[此文章](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/)。
<img src="docs/img/Box64Icon.png" width="96" height="96">
<img src="docs/img/Box64Icon.png" width="96" height="96" alt="Box64 Icon">
LOGO 由 @grayduck 制作,感谢!
_Logo 由 @grayduck 制作,感谢!_
----
---
使用方法
----
## 📖 使用方法
有若干环境变量可以控制 Box64 的行为。
Box64 提供了环境变量来控制其行为。有关详细信息请参阅[使用文档](docs/USAGE.md)。
可在[这里](docs/USAGE.md)查看所有环境变量及其作用。
---
注意:Box64 的 Dynarec 使用具有内存保护和段错误信号处理的机制来执行 JIT 代码。所以,如果想使用 GDB 调试使用 JIT 代码的程序(如 Mono/Unity3D),这会触发许多“正常”的段错误。建议在 GDB 中使用类似 `handle SIGSEGV nostop` 来防止它每个段错误处停止。如果你想捕获段错误,可以在 `signals.c` 的 `my_memprotectionhandler` 中设置断点。
## 🚀 编译和安装
----
- [编译说明](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md)
- [安装 Wine](https://github.com/ptitSeb/box64/blob/main/docs/X64WINE.md)
编译/安装
----
---
编译说明可以在[这里](docs/COMPILE.md)查看。
## 🔄 版本历史
----
请参阅[变更日志](docs/CHANGELOG.md)了解版本更新说明。
版本历史
----
---
版本日志在[这里](docs/CHANGELOG.md)。
## 🖥️ 平台兼容性说明
----
Box64 直接转换 x86_64 函数调用到本机原生库,因此需要主机系统上的 64 位库。对于 32 位二进制文​​件,请使用 Box86。
32位平台的注意事项
----
**注意事项**
因为 Box64 的工作原理是直接将函数调用从 x86_64 转换为主机系统,所以主机系统(运行 Box64 的系统)需要有 64 位库。Box64 不包含任何 64 位 <-> 32 位的转换。
1. Box32 模式正在制作中,旨在支持 Box64 上运行 32 位二进制文​​件,敬请期待!
2. 某些安装程序可能会将 64 位的主机操作系统判定为 x86 导致兼容性问题。解决方法:使用假的 `uname` ,并使它在运行参数为 `-m` 时返回 `x86_64`。
所以 box64 只能运行 64 位的 Linux 二进制。对于 32 位二进制则需要使用 box86 来运行(它在 64 位操作系统上使用了 multiarch 和 proot 等技巧来实现运行)。请注意,许多(基于 mojo 的)安装程序在检测到 ARM64 操作系统时将回退到 “x86”,因此即使存在 x86_64 版本,也会尝试使用 box86。这时你可以使用一个假的 `uname` ,并使它在运行参数为 `-m` 时返回 `x86_64`。
---
----
## ⚙️ 配置
关于 Unity 游戏模拟的注意事项
----
Box64 的配置文件位于 `/etc/box64.box64rc` 和 `~/.box64rc`,均为 `.ini` 格式的文件。如果您不想使用默认的 `/etc/box64.box64rc` 文件,请将其复制到 `~/.box64rc` 以确保兼容性。
运行 Unity 游戏应该没什么问题,但还应该注意,许多 Unity3D 游戏需要 OpenGL 3+,这在 ARM SBC 上可能会比较棘手。同时许多较新的 Unity3D游戏(如 KSP)也使用 BC7 压缩纹理,很多 ARM 的集成显卡并不支持。
配置项的优先级:`~/.box64rc` > `/etc/box64.box64rc` > 命令行。
> 提示:如果游戏开始后没有显示任何东西就退出了,在 Pi4 上可以使用 `MESA_GL_VERSION_OVERRIDE=3.2`,在 Panfrost 上则可以使用 `PAN_MESA_DEBUG=gl3` 来使用更高的配置。
---
----
## 📄 特定平台的其他说明
关于GTK程序的注意事项
----
### Unity 游戏
- 许多 Unity 游戏需要 OpenGL 3+,这对 ARM/RISC-V SBC 来说可能具有挑战性。
- **对 Pi4 和 Pi5 用户的提示**:设置 `MESA_GL_VERSION_OVERRIDE=3.2` 和 `BOX64_DYNAREC_STRONGMEM=1` 以防止卡死并启用强内存模式。
- **Panfrost**:为了在 ARM 上实现更好的兼容性,启用 `PAN_MESA_DEBUG=gl3` 以强制更高的 OpenGL Profile。如果游戏可以启动但在显示任何内容之前意外退出,这个设置可能会有所帮助。
box64 封装了 GTK,包括 gtk2 和 gtk3。
### GTK 程序
----
Box64 包装了 GTK 库,支持 gtk2 和 gtk3。
关于 Steam 的注意事项
----
### Steam
请注意,Steam 是 32/64 位混合的应用,所以你需要 box86 才能运行,因为客户端应用程序是 32 位的。它还使用 64 位本地服务器,它的 steamwebhelper 无法被关闭(即使是在最小模式)而且会吃掉大量的内存。对于内存小于 6 GB 的机型,你将会需要创建 swapfile 来运行 Steam。
由于 Steam 客户端应用是 32 位的,需要使用 Box86,但其本地服务器是 64 位的二进制文件。对于内存少于 6GB 的系统,可能需要使用交换文件以获得最佳性能。
----
### Wine
关于 Wine 的注意事项
----
Box64 支持 Wine64 和 Proton。对于 32 位组件,需要 Box86。配备 Box64 和 Box86 的系统可以运行 32 位和 64 位的 Windows 程序。
box64 支持 Wine64,Proton 应该也能运行。请注意,64 位 Wine 包含有 32 位组件,以便能够运行 32 位 Windows 程序。32 位应用程序需要 box86,否则无法运行。在 box64 和 box86 都存在并工作的系统上,64 位的 Wine 可以同时运行 32 位和 64 位 Windows 程序(分别使用 `wine` 和 `wine64`)。请注意,目前在 Wine 7.+ 中实现的 Wine 时间在 64 位进程中的新 32bit PE 尚不支持。我测试了 Wine 7.5 64 位可以正常工作,但是更新的版本可能还不行。
**提示**:您可以使用 Wine WOW64 版本在仅限 Box64 的环境中运行 x86 Windows 程序,这项支持仍处于实验阶段,但在大多数情况下都可以工作。
----
### Vulkan
关于 Vulkan 注意事项
----
Box64 封装了 Vulkan 库,但请注意,它仅在 RX550 显卡上进行过测试,因此根据您的显卡,某些扩展可能会丢失。
Box64 包装了 Vulkan 库。
----
@@ -103,7 +98,7 @@ Box64 封装了 Vulkan 库,但请注意,它仅在 RX550 显卡上进行过
以下感谢不分先后:
* 代码贡献:rajdakin, mogery, ksco, xctan
* 财务帮助:[Playtron](https://playtron.one), FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* 财务支持:[Playtron](https://playtron.one), tohodakilla, FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/), [CubeCoders Limited](http://cubecoders.com/)
* 硬件捐赠和 LoongArch 迁移:[xiaoji](https://www.linuxgame.cn/), Deepin Beijing Develop Team
* 硬件捐赠:[ADLINK](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en) with [Ampere](https://amperecomputing.com/home/edge), [SOPHGO](https://www.sophon.ai/), [Radxa](https://rockpi.org/), [StarFive](https://rvspace.org/), [Pine64](https://www.pine64.org/), [AYN](https://www.ayntec.com/), [AYANEO](https://ayaneo.com/), [jiangcuo](https://github.com/jiangcuo)
* 为本项目持续的宣传:salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
+3 -4
View File
@@ -2,7 +2,7 @@
Емулятор простіра користувача x86_64 із родзинкою
[Дивитись журнал змін](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md) | [Повідомити про помилку](https://github.com/ptitSeb/box64/issues/new)
[Дивитись журнал змін](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [English](https://github.com/ptitSeb/box64/blob/main/README.md) | [Повідомити про помилку](https://github.com/ptitSeb/box64/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main) ![stars](https://img.shields.io/github/stars/ptitSeb/box64) ![forks](https://img.shields.io/github/forks/ptitSeb/box64) ![contributors](https://img.shields.io/github/contributors/ptitSeb/box64) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box64) ![issues](https://img.shields.io/github/issues/ptitSeb/box64)
@@ -40,7 +40,6 @@ Box64 інтегрується з DynaRec (динамічний рекомпіл
> Інструкцію з встановлення Wine для Box64 можна знайти [тут](docs/X64WINE.md).
----
Історія версій/Журнал змін
----
@@ -68,7 +67,7 @@ Box64 інтегрується з DynaRec (динамічний рекомпіл
----
Запуск ігор Unity має працювати, але ви також повинні зауважити, що для багатьох ігор Unity3D потрібен OpenGL 3+, який може бути складно забезпечити на ARM SBC (одноплатних комп’ютерах). Крім того, багато нових ігор Unity3D (наприклад, KSP) використовують стиснуті текстури BC7, які не підтримуються багатьма інтегрованими GPU ARM.
Підказка: в Pi4 використовуйте `MESA_GL_VERSION_OVERRIDE=3.2`, а в Panfrost — `PAN_MESA_DEBUG=gl3`, щоб використовувати вищий профіль, якщо гра запускається, а потім завершується, перш ніж щось показує.
Підказка: на Pi4 і Pi5 використовуйте `MESA_GL_VERSION_OVERRIDE=3.2` з `BOX64_DYNAREC_STRONGMEM=1`, щоб запобігти зависанням і ввімкнути режим сильної пам’яті, і використовуйте Panfrost `PAN_MESA_DEBUG=gl3`, щоб використовувати вищий профіль, якщо гра починається, а потім завершується, перш ніж щось показати.
----
@@ -108,7 +107,7 @@ Box64 використовує бібліотеки Vulkan, але зауваж
Є багато способів зробити внесок: внесок коду, фінансовий внесок, апаратне забезпечення та реклама!
Отже, без особливого порядку, я хочу подякувати:
* За основний внесок у код: rajdakin, mogery, ksco, xctan
* За великий фінансовий внесок: [Playtron](https://playtron.one), FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* За великий фінансовий внесок: [Playtron](https://playtron.one), tohodakilla, FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* За апаратне забезпечення та міграцію LoongArch: [xiaoji](https://www.linuxgame.cn/), команда розробників Deepin Beijing
* За внесок у апаратне забезпечення: [ADLINK](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en) with [Ampere](https://amperecomputing.com/home/edge), [SOPHGO](https://www.sophon.ai/), [Radxa](https://rockpi.org/), [StarFive](https://rvspace.org/), [Pine64](https://www.pine64.org/), [AYN](https://www.ayntec.com/), [AYANEO](https://ayaneo.com/), [jiangcuo](https://github.com/jiangcuo)
* За безперервну рекламу Box64: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/Команда [TwisterOS](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
+59
View File
@@ -1,3 +1,62 @@
box64 (0.3.2) unstable; urgency=low
* Introduced Box32 to run 32bits apps on 64bits OS
* => Box32 is a build option for Box64, and is disabled by default
* => Optionnal binfmt integration available for Box32
* => Wrapped some basics libs, including graphics and sounds so a few games already works
* => Work In Progress, many issues remain to be fixed, but some Linux games are playable
* Introduced Native Flags. Can be controled with BOX64_DYNAREC_NATIVEFLAGS, but enabled by default
* => Available on the 3 Dynarec backend, with different implementations
* => ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default
* +> Can lead to large speedup on certain cases
* Improved Strong Memory Model emulation, with better default options and a more efficiant emulation
* Dynarec: RV64: using RVV (and XThreadVector) to implement SSEx opcodes, with some massive speedup when used!
* Some bugfix and improvment in the Signal handler and internal memory tracking
* Improvment to TRAP signal generation and Handling
* Improved CPUID opcodes again, and the various virtual file in /proc that represent those data
* Improved some x87 operations, like long double handling and infinity comparisons...
* Dynarec: ARM64 fixes to a few opcodes
* Dynarec: RV64 fixes to many opcodes
* Dynarec: LA64 fixes to a few opcodes
* Dynarec: RV64 fixes and improvments on LOCK prefixes opcodes
* Dynarec: Many optimisation on some individual opcodes, an all 3 backends
* WRAPPING: More libs and functions wrapped. Some wrapping fixes too
* WREPPING: New wrapperhelper to help coding new wrapping & fixing/enhancing existing one
* ElfLoader: Improved object fetching
* New build profile for SD865 and ORYON
* Changed the installation folder of x86 libs to avoid conflict with linux distro
* Added a few syscalls
* Some more Vulkan extensions wrapped
* More work on build system, and github CI (generating WCP archive), with some fixes on the Android version (still not 100% operational)
-- Sebastien Chevalier <[email protected]> Thu, 6 Dec 2024 10:30:33 -0100
box64 (0.3.0) unstable; urgency=low
* AVX and AVX2 implemented, along with BMI1, BMI2, ADX, FMA, F16C and RDANDR extension!
* Introduced BOX64_AVX env. var. to enable/disable AVX extension:
* => BOX64_AVX=1 enable AVX, BMI1, F16C and VAES extension
* => BOX64_AVX=2 also enable AVX2, BMI2, FMA, ADX,VPCLMULQDQ and RDRAND
* Dynarec: Implemented most AVX/AVX2 and friends in ARM64 Dynarec (using only NEON, so available on all ARM64 CPU)
* => ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default
* Improved CPUID opcodes, adding a few leaf, fixing same. Returnning an Haswell type of CPU now (was Pentium IV before)
* Dynarec: Small optim in the emit_pf helper, on all 3 backends
* Dynarec: ARM64 some fixes to a few opcodes
* Dynarec: LA64 many new opcodes added, and fixes.
* Dynarec: RV64 some new opcodes added, many fixes.
* Dynarec: RV64 Adding some infrastructure to use RVV (if available) for SIMD emulation.
* Dynarec: Many small changes and fixes around handling of x87, registers and internal jump.
* WRAPPING: Added a workaround on SDL_GetThreadID to fix a race condition that was happening mostly on LA64 and broke many SDL games
* WRAPPING: More libs and functions wrapped. Some wrapping fixes too (including a nasty error on some rare libGL functions)
* WRAPPING: Wayland is now supported. Wine-wayland at least works now
* Dynarec: LA64 improved LOCK CMPXCHG handling, and better 16Byte LOCK handling too (fixes many Unity3D games)
* Dynarec: RV64 improved LOCK CMPXCHG handling
* COSIM: Many fixes and improvment, to make BOX64_DYNAREC_TEST more usable
* Detect when a Wine program use UnityPlayer.dll to atumaticaly use BOX64_DYNAREC_STRONGMEM=1 (unless it's already set), so more games just work
* ElfLoader: Added a new type of relocation
-- Sebastien Chevalier <[email protected]> Thu, 9 Jul 2024 10:30:33 -0100
box64 (0.2.8) unstable; urgency=low
* Wrapping: More libs and function wrapping (gtk3, vulkan...)
+12 -1
View File
@@ -10,4 +10,15 @@ override_dh_auto_configure:
-DNOGIT=1
override_dh_shlibdeps:
dh_shlibdeps --exclude=libgcc_s.so.1 --exclude=libpng12.so.0 --exclude=libstdc++.so.5 --exclude=libstdc++.so.6
dh_shlibdeps --exclude=libgcc_s.so.1 \
--exclude=libpng12.so.0 \
--exclude=libstdc++.so.5 \
--exclude=libstdc++.so.6 \
--exclude=libmbedcrypto.so.7 \
--exclude=libssl.so.1.1 \
--exclude=libunwind.so.8 \
--exclude=libmbedtls.so.14 \
--exclude=libcrypto.so.1.1 \
--exclude=libmbedx509.so.1 \
--exclude=libcrypto.so.1.0.0 \
--exclude=libssl.1.0.0
+55
View File
@@ -1,3 +1,58 @@
v0.3.2
======
* Introduced Box32 to run 32bits apps on 64bits OS
=> Box32 is a build option for Box64, and is disabled by default
=> Optionnal binfmt integration available for Box32
=> Wrapped some basics libs, including graphics and sounds so a few games already works
=> Work In Progress, many issues remain to be fixed, but some Linux games are playable
* Introduced Native Flags. Can be controled with BOX64_DYNAREC_NATIVEFLAGS, but enabled by default
=> Available on the 3 Dynarec backend, with different implementations
=> ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default
+> Can lead to large speedup on certain cases
* Improved Strong Memory Model emulation, with better default options and a more efficiant emulation
* Dynarec: RV64: using RVV (and XThreadVector) to implement SSEx opcodes, with some massive speedup when used!
* Some bugfix and improvment in the Signal handler and internal memory tracking
* Improvment to TRAP signal generation and Handling
* Improved CPUID opcodes again, and the various virtual file in /proc that represent those data
* Improved some x87 operations, like long double handling and infinity comparisons...
* Dynarec: ARM64 fixes to a few opcodes
* Dynarec: RV64 fixes to many opcodes
* Dynarec: LA64 fixes to a few opcodes
* Dynarec: RV64 fixes and improvments on LOCK prefixes opcodes
* Dynarec: Many optimisation on some individual opcodes, an all 3 backends
* WRAPPING: More libs and functions wrapped. Some wrapping fixes too
* WREPPING: New wrapperhelper to help coding new wrapping & fixing/enhancing existing one
* ElfLoader: Improved object fetching
* New build profile for SD865 and ORYON
* Changed the installation folder of x86 libs to avoid conflict with linux distro
* Added a few syscalls
* Some more Vulkan extensions wrapped
* More work on build system, and github CI (generating WCP archive), with some fixes on the Android version (still not 100% operational)
v0.3.0
======
* AVX and AVX2 implemented, along with BMI1, BMI2, ADX, FMA, F16C and RDANDR extension!
* Introduced BOX64_AVX env. var. to enable/disable AVX extension:
=> BOX64_AVX=1 enable AVX, BMI1, F16C and VAES extension
=> BOX64_AVX=2 also enable AVX2, BMI2, FMA, ADX,VPCLMULQDQ and RDRAND
* Dynarec: Implemented most AVX/AVX2 and friends in ARM64 Dynarec (using only NEON, so available on all ARM64 CPU)
=> ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default
* Improved CPUID opcodes, adding a few leaf, fixing same. Returnning an Haswell type of CPU now (was Pentium IV before)
* Dynarec: Small optim in the emit_pf helper, on all 3 backends
* Dynarec: ARM64 some fixes to a few opcodes
* Dynarec: LA64 many new opcodes added, and fixes.
* Dynarec: RV64 some new opcodes added, many fixes.
* Dynarec: RV64 Adding some infrastructure to use RVV (if available) for SIMD emulation.
* Dynarec: Many small changes and fixes around handling of x87, registers and internal jump.
* WRAPPING: Added a workaround on SDL_GetThreadID to fix a race condition that was happening mostly on LA64 and broke many SDL games
* WRAPPING: More libs and functions wrapped. Some wrapping fixes too (including a nasty error on some rare libGL functions)
* WRAPPING: Wayland is now supported. Wine-wayland at least works now
* Dynarec: LA64 improved LOCK CMPXCHG handling, and better 16Byte LOCK handling too (fixes many Unity3D games)
* Dynarec: RV64 improved LOCK CMPXCHG handling
* COSIM: Many fixes and improvment, to make BOX64_DYNAREC_TEST more usable
* Detect when a Wine program use UnityPlayer.dll to atumaticaly use BOX64_DYNAREC_STRONGMEM=1 (unless it's already set), so more games just work
* ElfLoader: Added a new type of relocation
v0.2.8
======
* Wrapping: More libs and function wrapping (gtk3, vulkan...)
+41 -14
View File
@@ -1,17 +1,11 @@
Compiling/Installing
----
### Debian-based Linux
You can use [@ryanfortner](https://github.com/ryanfortner)'s apt repository to install precompiled box64 debs, updated every 24 hours.
If you don't want to compile box64 yourself and prefer to use third-party pre-build version, go to the [end of the document](#pre-build-packages) for alternatives.
```
sudo wget https://ryanfortner.github.io/box64-debs/box64.list -O /etc/apt/sources.list.d/box64.list
wget -qO- https://ryanfortner.github.io/box64-debs/KEY.gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/box64-debs-archive-keyring.gpg
sudo apt update && sudo apt install box64-arm64 -y
```
Alternatively, you can generate your own package using the [instructions below](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md#debian-packaging).
You can also generate your own package using the [instructions below](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md#debian-packaging).
## Per-platform compiling instructions
----
### The general approach is:
@@ -104,7 +98,7 @@ Using a 64bit OS:
Using a 64bit OS:
Caution: please use gcc-11 or higher, older gcc dosen't know cortex-a78ae
Caution: please use gcc-11 or higher, older gcc doesn't know cortex-a78ae
```
-D TEGRA_T234=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
@@ -217,7 +211,7 @@ If you encounter some linking errors, try using `NOLOADADDR=ON` (`cmake -D NOLOA
### Use ccmake
Alternatively, you can **use the curses-bases ccmake (or any other gui frontend for cmake)** to select wich platform to use interactively.
Alternatively, you can **use the curses-based ccmake (or any other gui frontend for cmake)** to select which platform to use interactively.
### Customize your build
@@ -251,12 +245,12 @@ You need to add `-DWITH_MOLD=1` if GNU ld is extremely slow. Then run `mold -run
#### Build a statically linked box64
You can now build box64 staticaly linked, with `-DSTATICBUILD`. This is to use inside an x86_64 chroot. Note that this version of box64 will have just the minimum of wrapped libs. So only libc, libm and libpthread basically are wrapped. Other libs (like libGL or libvulkan, SDL2, etc...) will not be wrapped and x86_64 version will be used. It's designed to be used in docker image, or in headless server.
You can now build box64 statically linked, with `-DSTATICBUILD`. This is to use inside an x86_64 chroot. Note that this version of box64 will have just the minimum of wrapped libs. So only libc, libm and libpthread basically are wrapped. Other libs (like libGL or libvulkan, SDL2, etc...) will not be wrapped and x86_64 version will be used. It's designed to be used in docker image, or in headless server.
Also, the Static Build is highly experimental, but feedback are always welcomed.
----
Testing
## Testing
----
A few tests are included with box64.
@@ -266,6 +260,39 @@ The tests are very basic and only tests some functionality for now.
----
Debian Packaging
## Debian Packaging
----
Box64 can also be packaged into a .deb file ***using the source code zip from the releases page*** with `DEB_BUILD_OPTIONS=nostrip dpkg-buildpackage -us -uc -nc`. Configure any additional cmake options you might want in `debian/rules`.
## Pre-build packages
----
### Debian-based Linux
You can use the [Pi-Apps-Coders apt repository](https://github.com/Pi-Apps-Coders/box64-debs) to install precompiled box64 debs, updated every 24 hours.
```
# check if .list file already exists
if [ -f /etc/apt/sources.list.d/box64.list ]; then
sudo rm -f /etc/apt/sources.list.d/box64.list || exit 1
fi
# check if .sources file already exists
if [ -f /etc/apt/sources.list.d/box64.sources ]; then
sudo rm -f /etc/apt/sources.list.d/box64.sources || exit 1
fi
# download gpg key from specified url
if [ -f /usr/share/keyrings/box64-archive-keyring.gpg ]; then
sudo rm -f /usr/share/keyrings/box64-archive-keyring.gpg
fi
sudo mkdir -p /usr/share/keyrings
wget -qO- "https://pi-apps-coders.github.io/box64-debs/KEY.gpg" | sudo gpg --dearmor -o /usr/share/keyrings/box64-archive-keyring.gpg
# create .sources file
echo "Types: deb
URIs: https://Pi-Apps-Coders.github.io/box64-debs/debian
Suites: ./
Signed-By: /usr/share/keyrings/box64-archive-keyring.gpg" | sudo tee /etc/apt/sources.list.d/box64.sources >/dev/null
sudo apt update
sudo apt install box64-generic-arm -y
```
+65 -22
View File
@@ -7,6 +7,8 @@ Env. var with * can also be put inside box64rc files.
Box64 look for 2 places for rcfile: `/etc/box64.box64rc` and `~/.box64rc`
The second takes precedence to the first, on an APP level
(that means if an [MYAPP] my appears in both file, only the settings in `~/.box64rc` will be applied)
There is also some égeneric" name, like [*SETUP*] that will be applied to every program containing "setup" in the name
(Note that this is not a full regex rules, it's just a name between '[*' and '*]', nothing else)
#### BOX64_LOG *
Controls the Verbosity level of the logs
@@ -28,7 +30,7 @@ Disables Box64 printing its version and build
#### BOX64_LD_LIBRARY_PATH *
Path to look for x86_64 libraries. Default is current folder and `lib` in current folder.
Also, `/usr/lib/x86_64-linux-gnu` and `/lib/x86_64-linux-gnu` are added if they exist.
Also, `/usr/lib/x86_64-linux-gnu`, `/lib/x86_64-linux-gnu` and `/usr/lib/box64-x86_64-linux-gnu` are added if they exist.
#### BOX64_PATH *
Path to look for x86_64 executable. Default is current folder and `bin` in current folder.
@@ -41,7 +43,7 @@ Enables/Disables the logging of `dlsym` errors.
#### BOX64_TRACE_FILE *
Send all log and trace to a file instead of `stdout`
Also, if name contains `%pid` then this is replaced by the actual PID of box64 instance
End the filename with `+` to have thetrace appended instead of overwritten
End the filename with `+` to have the trace appended instead of overwritten
Use `stderr` to use this instead of default `stdout`
#### BOX64_TRACE *
@@ -95,7 +97,7 @@ Show Segfault signal even if a signal handler is present
* 1 : Show SIGSEGV detail, even if a signal handler is present
#### BOX64_SHOWBT *
Show some Backtrace (Nativ e and Emulated) whgen a signal (SEGV, ILL or BUS) is caught
Show some Backtrace (Native and Emulated) when a signal (SEGV, ILL or BUS) is caught
* 0 : Don"t show backtraces (Default.)
* 1 : Show Backtrace detail (for native, box64 is rename as the x86_64 binary run)
@@ -143,14 +145,14 @@ Enables/Disables trace for generated code.
* 1 : Enable trace for generated code (like regular Trace, this will slow down the program a lot and generate huge logs).
#### BOX64_NODYNAREC *
Forbid dynablock creation in the interval specified (helpfull for debugging behaviour difference between Dynarec and Interpreter)
Forbid dynablock creation in the interval specified (helpful for debugging behaviour difference between Dynarec and Interpreter)
* 0xXXXXXXXX-0xYYYYYYYY : define the interval where dynablock cannot start (inclusive-exclusive)
#### BOX64_DYNAREC_TEST *
Dynarec will compare it's execution with the interpreter (super slow, only for testing)
* 0 : No comparison. (Default.)
* 1 : Each opcode runs on interepter and on Dynarec, and regs and memory are compared and print if different.
* 2 : Thread-safe tests, extremely slow.
* 1 : Each opcode runs on interpreter and on Dynarec, and regs and memory are compared and print if different.
* 0xXXXXXXXX-0xYYYYYYYY : define the interval where dynarec is tested (inclusive-exclusive)
#### BOX64_DYNAREC_BIGBLOCK *
Enables/Disables Box64's Dynarec building BigBlock.
@@ -167,9 +169,22 @@ Define Box64's Dynarec max allowed forward value when building Block.
#### BOX64_DYNAREC_STRONGMEM *
Enable/Disable simulation of Strong Memory model
* 0 : Don't try anything special (Default.)
* 1 : Enable some Memory Barrier when writting to memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
* 2 : All 1. plus a memory barrier on every write to memory using MOV
* 3 : All 2. plus Memory Barrier when reading from memory and on some SSE/SSE2 opcodes too
* 1 : Enable some memory barriers when writing to memory to simulate the Strong Memory Model in a limited way (Default when libmonobdwgc-2.0.so is loaded)
* 2 : All 1. plus memory barriers on SIMD instructions
* 3 : All 2. plus more memory barriers on a regular basis
#### BOX64_DYNAREC_WEAKBARRIER *
Tweaking the memory barriers to reduce the performance impact by STRONGMEM
* 0 : Use regular safe barrier (Default.)
* 1 : Use weak barriers to have more performance boost
* 2 : All 1. Plus disabled the last write barriers
#### BOX64_DYNAREC_PAUSE *
Enable/Disable x86 PAUSE emulation, which may help the performance of spinlocks
* 0 : Ignore x86 PAUSE instruction (Default.)
* 1 : Use YIELD to emulate x86 PAUSE instruction
* 2 : Use WFI to emulate x86 PAUSE instruction
* 3 : Use SEVL+WFE to emulate x86 PAUSE instruction
#### BOX64_DYNAREC_X87DOUBLE *
Force the use of Double for x87 emulation
@@ -185,6 +200,7 @@ Enable/Disable generation of -NAN
Enable/Disable generation of precise x86 rounding
* 0 : Generate float/double -> int rounding like on x86
* 1 : Don't do anything special with edge case Rounding, to go as fast as possible (no INF/NAN/Overflow -> MIN_INT conversion) (default, faster)
* 2 : Everything from 1 plus also fast round of double->float (not taking into account current rounding mode)
#### BOX64_DYNAREC_SAFEFLAGS *
Handling of flags on CALL/RET opcodes
@@ -200,7 +216,12 @@ Optimisation of CALL/RET opcodes (not compatible with jit/dynarec/smc)
#### BOX64_DYNAREC_ALIGNED_ATOMICS *
Generated code for aligned atomics only
* 0 : The code generated can handle unaligned atomics (Default)
* 1 : Generated code only for aligned atomics (faster and less code generated, but will SEGBUS if LOCK prefix is unsed on unaligned data)
* 1 : Generated code only for aligned atomics (faster and less code generated, but will SEGBUS if LOCK prefix is unused on unaligned data)
#### BOX64_DYNAREC_NATIVEFLAGS *
Generate code will use native flags if possible
* 0 : The code generated whill not use native flags even when possible
* 1 : Generated code will use native flags when possible (Arm64 only for now) (Default)
#### BOX64_DYNAREC_BLEEDING_EDGE *
Detect MonoBleedingEdge and apply conservative settings
@@ -213,7 +234,7 @@ Detect libjvm and apply conservative settings. Obsolete, use BOX64_JVM instead.
* 1 : Detect libjvm, and apply BIGBLOCK=0 STRONGMEM=1 SSE42=0 if detected (Default)
#### BOX64_DYNAREC_WAIT *
Behavior with FillBlock is not availble (FillBlock build Dynarec blocks and is not multithreaded)
Behavior with FillBlock is not available (FillBlock build Dynarec blocks and is not multithreaded)
* 0 : Dynarec will not wait for FillBlock to ready and use Interpreter instead (might speedup a bit massive multithread or JIT programs)
* 1 : Dynarec will wait for FillBlock to be ready (Default)
@@ -221,6 +242,7 @@ Behavior with FillBlock is not availble (FillBlock build Dynarec blocks and is n
Dynarec print the missing opcodes
* 0 : not print the missing opcode (Default, unless DYNAREC_LOG>=1 or DYNAREC_DUMP>=1 is used)
* 1 : Will print the missing opcodes
* 2 : Will print the fallback to scalar opcodes (only valid on RISC-V)
#### BOX64_SSE_FLUSHTO0 *
Handling of SSE Flush to 0 flags
@@ -252,6 +274,11 @@ Detect libjvm and apply conservative settings
* 0 : Don't detect libjvm
* 1 : Detect libjvm, and apply BIGBLOCK=0 STRONGMEM=1 SSE42=0 if detected (Default)
#### BOX64_UNITYPLAYER *
Detect UnityPlayer.dll and apply strongmem settings
* 0 : Don't detect UnityPlayer.dll
* 1 : Detect UnityPlayer.dll, and apply BOX64_DYNAREC_STRONGMEM=1 if detected (Default)
#### BOX64_SDL2_JGUID *
Need a workaround for SDL_GetJoystickGUIDInfo function for wrapped SDL2
* 0 : Don't use any workaround
@@ -264,12 +291,12 @@ Need a workaround for SDL_GetJoystickGUIDInfo function for wrapped SDL2
#### BOX64_LD_PRELOAD
* XXXX[:YYYYY] force loading XXXX (and YYYY...) libraries with the binary
PreLoaded libs can be emulated or native, and are treated the same way as if they were comming from the binary
PreLoaded libs can be emulated or native, and are treated the same way as if they were coming from the binary
#### BOX64_EMULATED_LIBS *
* XXXX[:YYYYY] force lib XXXX (and YYYY...) to be emulated (and not wrapped)
Some games uses an old version of some libraries, with an ABI incompatible with native version.
Note that LittleInferno for example is auto detected, and libvorbis.so.0 is automatical added to emulated libs, and same for Don't Starve (and Together / Server variant) that use an old SDL2 too
Note that LittleInferno for example is auto detected, and libvorbis.so.0 is automatically added to emulated libs, and same for Don't Starve (and Together / Server variant) that use an old SDL2 too
#### BOX64_ALLOWMISSINGLIBS *
Allow Box64 to continue even if a library is missing.
@@ -282,14 +309,19 @@ Box64 will use wrapped libs even if the lib is specified with absolute path
* 1 : Use Wrapped native libs even if path is absolute
#### BOX64_PREFER_EMULATED *
Box64 will prefer emulated libs first (execpt for glibc, alsa, pulse, GL, vulkan and X11
* 0 : Native libs are prefered (Default.)
* 1 : Emulated libs are prefered (Default for program running inside pressure-vessel)
Box64 will prefer emulated libs first (except for glibc, alsa, pulse, GL, vulkan and X11
* 0 : Native libs are preferred (Default.)
* 1 : Emulated libs are preferred (Default for program running inside pressure-vessel)
#### BOX64_WRAP_EGL *
Box64 will prefer wrapped libs for EGL and GLESv2
* 0 : Emulated libs are preferred (Default)
* 1 : Native libs are preferred
#### BOX64_CRASHHANDLER *
Box64 will use a dummy crashhandler.so library
* 0 : Use Emulated crashhandler.so library if needed
* 1 : Use an internal dummy (completly empty) crashhandler.so library (defaut)
* 1 : Use an internal dummy (completely empty) crashhandler.so library (default)
#### BOX64_MALLOC_HACK *
How Box64 will handle hooking of malloc operators
@@ -312,10 +344,15 @@ Disables the load of vulkan libraries.
* 0 : Load vulkan libraries if found.
* 1 : Disables the load of vulkan libraries, both the native and the i386 version (can be useful on Pi4, where the vulkan driver is not quite there yet.)
#### BOX64_SHAEXT *
Expose or not SHAEXT (a.k.a. SHA_NI) capabilities
* 0 : Do not expose SHAEXT capabilities
* 1 : Expose SHAEXT capabilities (Default.)
#### BOX64_SSE42 *
Expose or not SSE 4.2 capabilites
* 0 : Do not expose SSE 4.2 capabilites (default when libjvm is detected)
* 1 : Expose SSE 4.2 capabilites (Default.)
Expose or not SSE 4.2 capabilities
* 0 : Do not expose SSE 4.2 capabilities (default when libjvm is detected)
* 1 : Expose SSE 4.2 capabilities (Default.)
#### BOX64_FUTEX_WAITV *
Use of the new fuext_waitc syscall
@@ -335,7 +372,7 @@ Define x86_64 bash to launch script
* XXX=yyyy
will add XXX=yyyy env. var. and continue with BOX86_ENV2 ... until var doesn't exist
#### BOX64_RESERVE_HIGH
#### BOX64_RESERVE_HIGH *
* 0 : Don't try to pe-reserve high memory (beyond 47bits) (Default)
* 1 : Try to reserve (without allocating it) memory beyond 47bits (seems unstable)
@@ -348,7 +385,7 @@ Define x86_64 bash to launch script
`set waiting=0` to exit the infinite loop.
* 2 : Launch `gdbserver` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process, and go in an endless loop, waiting.
Use `gdb /PATH/TO/box64` and then `target remote 127.0.0.1:1234` to connect to the gdbserver (or use actual IP if not on the machine). After that, the procedure is the same as with ` BOX64_JITGDB=1`.
This mode can be usefullwhen programs redirect all console output to a file (like Unity3D Games)
This mode can be usefull when programs redirect all console output to a file (like Unity3D Games)
* 3 : Launch `lldb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process and go in an endless loop, waiting.
#### BOX64_NORCFILES
@@ -378,6 +415,12 @@ Those variables are only valid inside a rcfile:
* 0 : Nothing special
* 1 : Added "-cef-disable-gpu-compositor" to command line arguments (usefull for steamwebhelper/cef based programs)
#### BOX64_ARGS
If that var exist, it will be added as argument(s) to the command line if there is no current argument (it's ignored else). Note that "" are supported, but not ''
#### BOX64_INSERT_ARGS
If that var exist, it will be inserted as firsts argument(s) to the command line. Note that "" are supported, but not ''
#### BOX64_EXIT
* 0 : Nothing special
* 1 : Just exit, don't try to run the program
+40 -19
View File
@@ -33,7 +33,7 @@ Print box64 version and quit.
=head1 CONFIGURATION FILE
B<Box64> now have configurations files. There are 2 files loaded.
F</etc/box4.box64rc> and F<~/.box64rc>. Both files have the same syntax, and is
F</etc/box64.box64rc> and F<~/.box64rc>. Both files have the same syntax, and is
basically an ini files. Section in square brackets define the process name, and
the rest is the environment variable. B<Box64> comes with a default file that
should be installed for better stability. Note that the priority is:
@@ -77,7 +77,7 @@ When set to 1, don't prints the banner including version and build.
=item B<BOX64_LD_PRELOAD>=I<lib1>[:I<lib2>:...]
Force loading libraries with the binary. PreLoaded libs can be emulated or
native, and are treated the same way as if they were comming from the binary.
native, and are treated the same way as if they were coming from the binary.
=item B<BOX64_ENV>=I<env=val>
@@ -118,8 +118,8 @@ B<BOX64_LOG> > 1 (may need B<BOX64_SHOWSEGV=1> also)
=item B<BOX64_LD_LIBRARY_PATH>=I</path/to/libs>
Path to look for x86_64 libraries. Default is current folder and C<lib> in
current folder. Also, F</usr/lib/x86_64-linux-gnu> and
F</lib/x86_64-linux-gnu> are added if they exist.
current folder. Also, F</usr/lib/x86_64-linux-gnu>,
F</lib/x86_64-linux-gnu> and F</usr/lib/box64-x86_64-linux-gnu> are added if they exist.
=item B<BOX64_PATH>=I</path/to/bins>
@@ -205,14 +205,14 @@ Disable handling of SigILL (to ease debugging mainly).
Show Segfault signal even if a signal handler is present
* 0 : Don"t force show the SIGSEGV analysis (Default.)
* 0 : Don't force show the SIGSEGV analysis (Default.)
* 1 : Show SIGSEGV detail, even if a signal handler is present
=item B<BOX64_SHOWBT>=I<0|1>
Show some Backtrace (Nativ e and Emulated) whgen a signal (SEGV, ILL or BUS) is caught
Show some Backtrace (Nativ e and Emulated) when a signal (SEGV, ILL or BUS) is caught
* 0 : Don"t show backtraces (Default.)
* 0 : Don't show backtraces (Default.)
* 1 : Show Backtrace detail (for native, box64 is rename as the x86_64 binary run)
=item B<BOX64_X11THREADS>=I<0|1>
@@ -263,7 +263,7 @@ down the program a lot and generate huge logs.
=item B<BOX64_NODYNAREC>=I<0xXXXXXXXX-0xYYYYYYYY>
Forbid dynablock creation in the interval specified (helpfull for debugging
Forbid dynablock creation in the interval specified (helpful for debugging
behaviour difference between Dynarec and Interpreter)
=item B<BOX64_DYNAREC_TEST>=I<0|1>
@@ -272,7 +272,8 @@ Dynarec will compare it's execution with the interpreter (super slow, only for t
* 0 : No comparison. (Default.)
* 1 : Each opcode runs on interepter and on Dynarec, and regs and memory are compared and print if different.
* 2 : Thread-safe tests, extremely slow.
* 0xXXXXXXXX-0xYYYYYYYY : Define the interval where dynarec is tested (inclusive-exclusive)
=item B<BOX64_DYNAREC_BIGBLOCK>=I<0|1|2|3>
@@ -290,13 +291,31 @@ Define Box64's Dynarec max allowed forward value when building Block.
* 0 : No forward value. When current block end, don't try to go further even if there are previous forward jumps
* XXX : Allow up to XXXX bytes of gap when building a Block after the block end to next forward jump (Default: 128)
=item B<BOX64_DYNAREC_STRONGMEM>=I<0|1|2>
=item B<BOX64_DYNAREC_STRONGMEM>=I<0|1|2|3>
Enable/Disable simulation of Strong Memory model
* 0 : Don't try anything special (Default.)
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
* 1 : Enable some memory barriers when writing to memory to simulate the Strong Memory Model in a limited way (Default when libmonobdwgc-2.0.so is loaded)
* 2 : All 1. plus memory barriers on SIMD instructions
* 3 : All 2. plus more memory barriers on a regular basis
=item B<BOX64_DYNAREC_WEAKBARRIER>=I<0|1|2>
Tweaking the memory barriers to reduce the performance impact by STRONGMEM
* 0 : Use regular safe barrier (Default.)
* 1 : Use weak barriers to have more performance boost
* 2 : All 1. Plus disabled the last write barriers
=item B<BOX64_DYNAREC_PAUSE>=I<0|1|2|3>
Enable/Disable x86 PAUSE emulation, which may help the performance of spinlocks
* 0 : Ignore x86 PAUSE instruction (Default.)
* 1 : Use YIELD to emulate x86 PAUSE instruction
* 2 : Use WFI to emulate x86 PAUSE instruction
* 3 : Use SEVL+WFE to emulate x86 PAUSE instruction
=item B<BOX64_DYNAREC_X87DOUBLE>=I<0|1>
@@ -343,7 +362,7 @@ Detect MonoBleedingEdge and apply conservative settings
=item B<BOX64_DYNAREC_WAIT>=I<0|1>
Behavior with FillBlock is not availble (FillBlock build Dynarec blocks and is not multithreaded)
Behavior with FillBlock is not available (FillBlock build Dynarec blocks and is not multithreaded)
* 0 : Dynarec will not wait for FillBlock to ready and use Interpreter instead (might speedup a bit massive multithread or JIT programs)
* 1 : Dynarec will wait for FillBlock to be ready (Default)
@@ -388,7 +407,7 @@ You can also use B<SDL_VIDEO_GL_DRIVER>
Force lib XXXX (and YYYY...) to be emulated (and not wrapped) Some games uses
an old version of some libraries, with an ABI incompatible with native version.
Note that LittleInferno for example is auto detected, and libvorbis.so.0 is
automatical added to emulated libs, and same for Don't Starve (and Together /
automatically added to emulated libs, and same for Don't Starve (and Together /
Server variant) that use an old SDL2 too
=item B<BOX64_ALLOWMISSINGLIBS>=I<0|1>
@@ -407,18 +426,18 @@ Box64 will use wrapped libs even if the lib is specified with absolute path
=item B<BOX64_PREFER_EMULATED>=I<0|1>
Box64 will prefer emulated libs first (execpt for glibc, alsa, pulse, GL,
Box64 will prefer emulated libs first (except for glibc, alsa, pulse, GL,
vulkan and X11
* 0 : Native libs are prefered (Default.)
* 1 : Emulated libs are prefered (Default for program running inside pressure-vessel)
* 0 : Native libs are preferred (Default.)
* 1 : Emulated libs are preferred (Default for program running inside pressure-vessel)
=item B<BOX64_CRASHHANDLER>=I<0|1>
Box64 will use a dummy crashhandler.so library
* 0 : Use Emulated crashhandler.so library if needed
* 1 : Use an internal dummy (completly empty) crashhandler.so library (defaut)
* 1 : Use an internal dummy (completely empty) crashhandler.so library (default)
=item B<BOX64_MALLOC_HACK>=I<0|1|2>
@@ -465,7 +484,9 @@ script. yyyy needs to be a full path to a valid x86_64 version of bash
* 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_box64signalhandler` in is stack) then probably need to `finish` 1 or 2 functions (inside `usleep(..)`) and then you'll be in `my_box64signalhandler`, just before the printf of the Segfault message. Then simply `set waiting=0` to exit the infinite loop.
* 2 : Launch `gdbserver` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process, and go in an endless loop, waiting. Use `gdb /PATH/TO/box64` and then `target remote 127.0.0.1:1234` to connect to the gdbserver (or use actual IP if not on the machine). After that, the procedure is the same as with ` BOX64_JITGDB=1`. This mode can be usefullwhen programs redirect all console output to a file (like Unity3D Games)
* 2 : Launch `gdbserver` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process, and go in an endless loop, waiting. Use `gdb /PATH/TO/box64` and then `target remote 127.0.0.1:1234` to connect to the gdbserver (or use actual IP if not on the machine). After that, the procedure is the same as with ` BOX64_JITGDB=1`. This mode can be usefull when programs redirect all console output to a file (like Unity3D Games)
=back
=head1 VARIABLES FOR ENVIRONMENT ONLY
+1 -1
View File
@@ -1,6 +1,6 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rk3xxx-git
pkgname=box64-rk3xxx-git
pkgver=r2431.60c6858
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
+276 -66
View File
@@ -150,14 +150,18 @@ class FunctionConvention(object):
self.ident = ident
self.name = convname
self.values = valid_chars
# Free letters: B FG J QR T YZa e gh jk mno qrst z
# Free letters: B FG JK QR T YZa e gh jk mno qrst yz
conventions = {
'F': FunctionConvention('F', "System V", ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H', 'P', 'A', 'x', 'X', 'Y', 'y', 'b']),
'W': FunctionConvention('W', "Windows", ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'P', 'A'])
'F': FunctionConvention('F', "System V", ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'H', 'P', 'A', 'x', 'X', 'Y', 'b']),
'W': FunctionConvention('W', "Windows", ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'P', 'A'])
}
sortedvalues = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H', 'P', 'A', 'x', 'X', 'Y', 'y', 'b', '0', '1']
sortedvalues = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'H', 'P', 'A', 'x', 'X', 'Y', 'b', '0', '1']
assert(all(all(c not in conv.values[:i] and c in sortedvalues for i, c in enumerate(conv.values)) for conv in conventions.values()))
# Some type depend on HAVE_LD80BITS; define this here so we can use it in readFiles and main
depends_on_ld: str = "DY"
assert(all(c in sortedvalues for c in depends_on_ld))
class FunctionType(str):
@staticmethod
def validate(s: str, post: str) -> bool:
@@ -369,7 +373,7 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
# typedefs is a list of all "*FE*" types for the current file
# mystructs is a map of all char -> (structure C name, replacement) for structures
typedefs : JumbledTypedefs = {}
typedefs : JumbledTypedefs = {}
mystructs : JumbledStructures = {}
mystructuses: JumbledStructUses = {}
filespec[filename[:-10]] = (typedefs, mystructs, mystructuses)
@@ -402,9 +406,11 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
or match("libgl", "libegl") \
or match("libgl", "glesv2") \
or match("libegl", "glesv2") \
or match("softokn3", "p11kit") \
or match("libc", "tcmallocminimal") \
or match("libc", "tbbmallocproxy") \
or match("libc", "androidshmem") \
or match("crypto", "libssl3") \
or match("tcmallocminimal", "tbbmallocproxy"):
continue
@@ -530,9 +536,22 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
if ln not in gbl[str(dependants)]:
gbl[str(dependants)].append(FunctionType(ln))
if any(c in origLine for c in depends_on_ld):
if (gotype != "GOM") and (gotype != "GOWM") and (gotype != "GOD") and (gotype != "GOWD"):
print("\033[91mError:\033[m type depends on HAVE_LD80BITS but the GO type doesn't support that ({0}:{1})"
.format(filename, line[:-1]))
halt_required = True
if (gotype == "GO2") or (gotype == "GOW2") or (gotype == "GOD") or (gotype == "GODW"):
altfun = line.split(',')[2].split(')')[0].strip()
if altfun == "":
print("\033[91mError:\033[m empty alt function ({0}:{1})".format(filename, line[:-1]))
halt_required = True
elif altfun == funname:
print("\033[91mError:\033[m alt function is the original function ({0}:{1})".format(filename, line[:-1]))
halt_required = True
if origLine[2] == "E":
if (gotype != "GOM") and (gotype != "GOWM"):
if (gotype != "GO2") or not (line.split(',')[2].split(')')[0].strip().startswith('my_')):
if ((gotype != "GO2") and (gotype != "GOW2")) or not (line.split(',')[2].split(')')[0].strip().startswith('my_')):
print("\033[91mThis is probably not what you meant!\033[m ({0}:{1})".format(filename, line[:-1]))
halt_required = True
if len(origLine) > 3:
@@ -828,10 +847,10 @@ def main(root: str, files: Iterable[Filename], ver: str):
# Detect functions which return in an x87 register
retx87_wraps: Dict[ClausesStr, List[FunctionType]] = {}
return_x87: str = "DK"
return_x87: str = "D"
# Sanity checks
forbidden_simple: Dict[str, str] = {"ARM64": "EDKVOSNMHPAxXYyb", "RV64": "EcwiDKVOSNMHPAxXYyb"}
forbidden_simple: Dict[str, str] = {"ARM64": "EDVOSNHPAxXYb", "RV64": "EcwiDVOSNHPAxXYb"}
assert(all(k in allowed_simply for k in forbidden_simple))
assert(all(k in allowed_regs for k in forbidden_simple))
assert(all(k in allowed_fpr for k in forbidden_simple))
@@ -842,17 +861,18 @@ def main(root: str, files: Iterable[Filename], ver: str):
assert(all(c not in allowed_simply[k1] + allowed_regs[k1] + allowed_fpr[k1] for c in forbidden_simple[k1]))
assert(all(c in allowed_simply[k1] + allowed_regs[k1] + allowed_fpr[k1] + forbidden_simple[k1] for c in allowed_conv.values))
assert(all(c in allowed_conv.values for c in return_x87))
assert(all(c in forbidden_simple[k] for c in depends_on_ld for k in forbidden_simple))
simple_wraps: Dict[str, Dict[ClausesStr, List[Tuple[FunctionType, int]]]] = {
k1: {} for k1 in forbidden_simple
}
def check_simple(v: FunctionType) -> Dict[str, int]:
regs_count: int = 0
fpr_count : int = 0
ret = {}
ret: Dict[str, int] = {}
for k in forbidden_simple:
regs_count: int = 0
fpr_count : int = 0
if v.get_convention() is not allowed_conv:
continue
if v[0] in forbidden_simple[k]:
@@ -930,6 +950,19 @@ def main(root: str, files: Iterable[Filename], ver: str):
return v;
{rbr}
static void* io_convert_back(void* v)
{lbr}
if(!v)
return v;
if(v == stdin)
return my__IO_2_1_stdin_;
if(v == stdout)
return my__IO_2_1_stdout_;
if(v == stderr)
return my__IO_2_1_stderr_;
return v;
{rbr}
#define ST0val ST0.d
int of_convert(int);
@@ -966,7 +999,6 @@ def main(root: str, files: Iterable[Filename], ver: str):
// o = stdout
// S = _IO_2_1_stdXXX_ pointer (or FILE*)
// N = ... automatically sending 1 arg
// M = ... automatically sending 2 args
// A = va_list
// 0 = constant 0, 1 = constant 1
// x = float complex
@@ -1033,20 +1065,59 @@ def main(root: str, files: Iterable[Filename], ver: str):
# Rewrite the wrapper.c file:
# i and u should only be 32 bits
td_types = {
# E v c w i I C W u U f d D K l L p V O S N M H P A x X Y y b
'F': ["x64emu_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*", "...", "...", "unsigned __int128", "void*", "void*", "complexf_t", "complex_t", "complexl_t", "complex_t", "void*"],
# E v c w i I C W u U f d K l L p V O S N M P A
'W': ["x64emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "...", "void*", "void*"]
# E v c w i I C W u U f d D l L p V O S N H P A x X Y b
'F': ["x64emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "unsigned __int128", "void*", "void*", "complexf_t", "complex_t", "complexl_t", "void*"],
# E v c w i I C W u U f d l L p V O S N P A
'W': ["x64emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "void*", "void*"]
}
td_types_nold = {
'F': {'D': "double", 'Y': "complex_t"},
'W': {}
}
td_types_ld = {
k: {t: td_types[k][conventions[k].values.index(t)] for t in td_types_nold[k]} for k in td_types_nold
}
assert(all(k in conventions for k in td_types))
assert(all(k in conventions for k in td_types_nold))
assert(all(t in depends_on_ld for k in td_types_nold for t in td_types_nold[k]))
for k in conventions:
if len(conventions[k].values) != len(td_types[k]):
raise NotImplementedError("len(values) = {lenval} != len(td_types) = {lentypes}".format(lenval=len(conventions[k].values), lentypes=len(td_types[k])))
def generate_typedefs(arr: Iterable[FunctionType], file) -> None:
any_depends_on_ld = False
for v in arr:
file.write("typedef " + td_types[v.get_convention().ident][v.get_convention().values.index(v[0])] + " (*" + v + "_t)"
if any(c in v for c in depends_on_ld):
any_depends_on_ld = True
continue
name = v + "_t"
v = v[:-1] if v.endswith('NN') else v # FIXME
file.write("typedef " + td_types[v.get_convention().ident][v.get_convention().values.index(v[0])] + " (*" + name + ")"
+ "(" + ', '.join(td_types[v.get_convention().ident][v.get_convention().values.index(t)] for t in v[2:]) + ");\n")
if any_depends_on_ld:
file.write("\n#if defined(HAVE_LD80BITS) || defined(ANDROID)\n")
for v in arr:
if all(c not in v for c in depends_on_ld):
continue
name = v + "_t"
v = v[:-1] if v.endswith('NN') else v # FIXME
file.write("typedef " + td_types[v.get_convention().ident][v.get_convention().values.index(v[0])] + " (*" + name + ")"
+ "(" + ', '.join(td_types[v.get_convention().ident][v.get_convention().values.index(t)] for t in v[2:]) + ");\n")
file.write("#else // !HAVE_LD80BITS && !ANDROID\n")
for k in td_types_nold:
for t in td_types_nold[k]:
td_types[k][conventions[k].values.index(t)] = td_types_nold[k][t]
for v in arr:
if all(c not in v for c in depends_on_ld):
continue
name = v + "_t"
v = v[:-1] if v.endswith('NN') else v # FIXME
file.write("typedef " + td_types[v.get_convention().ident][v.get_convention().values.index(v[0])] + " (*" + name + ")"
+ "(" + ', '.join(td_types[v.get_convention().ident][v.get_convention().values.index(t)] for t in v[2:]) + ");\n")
for k in td_types_nold:
for t in td_types_ld[k]:
td_types[k][conventions[k].values.index(t)] = td_types_ld[k][t]
file.write("#endif\n")
with open(os.path.join(root, "src", "wrapped", "generated", "wrapper.c"), 'w') as file:
file.write(files_header["wrapper.c"].format(lbr="{", rbr="}", version=ver))
@@ -1069,10 +1140,10 @@ def main(root: str, files: Iterable[Filename], ver: str):
conventions['F']: [
"\n#error Invalid return type: emulator\n", # E
"fn({0});", # v
"R_RAX=fn({0});", # c
"R_RAX=fn({0});", # w
"R_RAX=(int32_t)fn({0});", # i
"R_RAX=(int64_t)fn({0});", # I
"R_RAX=(uint8_t)fn({0});", # c
"R_RAX=(uint16_t)fn({0});", # w
"R_RAX=(uint32_t)fn({0});", # i
"S_RAX=(int64_t)fn({0});", # I
"R_RAX=(unsigned char)fn({0});", # C
"R_RAX=(unsigned short)fn({0});", # W
"R_RAX=(uint32_t)fn({0});", # u
@@ -1080,22 +1151,19 @@ def main(root: str, files: Iterable[Filename], ver: str):
"emu->xmm[0].f[0]=fn({0});", # f
"emu->xmm[0].d[0]=fn({0});", # 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_RAX=(intptr_t)fn({0});", # l
"R_RAX=(uintptr_t)fn({0});", # L
"R_RAX=(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
"R_RAX=(uintptr_t)io_convert_back(fn({0}));", # S
"\n#error Invalid return type: ... with 1 arg\n", # N
"\n#error Invalid return type: ... with 2 args\n", # M
"unsigned __int128 u128 = fn({0}); R_RAX=(u128&0xFFFFFFFFFFFFFFFFL); R_RDX=(u128>>64)&0xFFFFFFFFFFFFFFFFL;", # H
"\n#error Invalid return type: pointer in the stack\n", # P
"\n#error Invalid return type: va_list\n", # A
'from_complexf(emu, fn({0}));', # x
'from_complex(emu, fn({0}));', # X
'from_complexl(emu, fn({0}));', # Y
'from_complexk(emu, fn({0}));', # y
"from_complexf(emu, fn({0}));", # x
"from_complex(emu, fn({0}));", # X
"from_complexl(emu, fn({0}));", # Y
"\n#error Invalid return type: xcb_connection_t*\n", # b
],
conventions['W']: [
@@ -1111,32 +1179,47 @@ def main(root: str, files: Iterable[Filename], ver: str):
"R_RAX=fn({0});", # U
"emu->xmm[0].f[0]=fn({0});", # f
"emu->xmm[0].d[0]=fn({0});", # d
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # K
"R_RAX=(intptr_t)fn({0});", # l
"R_RAX=(uintptr_t)fn({0});", # L
"R_RAX=(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
"R_RAX=io_convert_back(fn({0}));", # S
"\n#error Invalid return type: ... with 1 arg\n", # N
"\n#error Invalid return type: ... with 2 args\n", # M
"\n#error Invalid return type: pointer in the stack\n", # P
"\n#error Invalid return type: va_list\n", # A
]
}
vals_nold = {
conventions['F']: {
'D': "double db=fn({0}); fpu_do_push(emu); ST0val = db;",
'Y': "from_complexk(emu, fn({0}));",
},
conventions['W']: {}
}
vals_android = {
conventions['F']: {
"D": "long double ld=fn({0}); emu->xmm[0].u128=*(__uint128_t*)&ld;",
"Y": "from_complexl(emu, fn({0}));",
},
conventions['W']: {}
}
vals_ld = {
k: {t: vals[k][k.values.index(t)] for t in vals_nold[k]} for k in vals_nold
}
# vreg: value is in a general register
# E v c w i I C W u U f d D K l L p V O S N M H P A x X Y y b
vreg = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2, 0, 1, 0, 0, 0, 0, 1]
# E v c w i I C W u U f d D l L p V O S N H P A x X Y b
vreg = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 2, 0, 1, 0, 0, 0, 1]
# vxmm: value is in a XMM register
# E v c w i I C W u U f d D K l L p V O S N M H P A x X Y y b
vxmm = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0]
# E v c w i I C W u U f d D l L p V O S N H P A x X Y b
vxmm = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0]
# vother: value is elsewere
# E v c w i I C W u U f d D K l L p V O S N M H P A x X Y y b
vother = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# E v c w i I C W u U f d D l L p V O S N H P A x X Y b
vother = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# vstack: value is on the stack (or out of register)
# E v c w i I C W u U f d D K l L p V O S N M H P A x X Y y b
vstack = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 1, 1, 1, 2, 2, 1, 1, 1, 2, 4, 4, 1]
# E v c w i I C W u U f d D l L p V O S N H P A x X Y b
vstack = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 1, 1, 1, 2, 1, 1, 1, 2, 4, 1]
arg_r = [
"", # E
"", # v
@@ -1151,7 +1234,6 @@ def main(root: str, files: Iterable[Filename], ver: str):
"", # f
"", # d
"", # D
"", # K
"(intptr_t){p}, ", # l
"(uintptr_t){p}, ", # L
"(void*){p}, ", # p
@@ -1159,14 +1241,12 @@ def main(root: str, files: Iterable[Filename], ver: str):
"of_convert((int32_t){p}), ", # O
"io_convert((void*){p}), ", # S
"(void*){p}, ", # N
"(void*){p}, ", # M
"\n#error Use pp instead\n", # H
"(unsigned __int128){p} + ((unsigned __int128){p2} << 64), ", # H
"", # P
"(void*){p}, ", # A
"", # x
"", # x
"", # X
"", # Y
"", # y
"", # Y
"aligned_xcb, ", # b
]
arg_x = [
@@ -1183,7 +1263,6 @@ def main(root: str, files: Iterable[Filename], ver: str):
"emu->xmm[{p}].f[0], ", # f
"emu->xmm[{p}].d[0], ", # d
"", # D
"", # K
"", # l
"", # L
"", # p
@@ -1191,14 +1270,12 @@ def main(root: str, files: Iterable[Filename], ver: str):
"", # O
"", # S
"", # N
"", # M
"", # H
"", # P
"", # A
"to_complexf(emu, {p}), ", # x
"to_complex(emu, {p}), ", # X
"", # Y
"", # y
"", # Y
"", # b
]
arg_o = [
@@ -1215,7 +1292,6 @@ def main(root: str, files: Iterable[Filename], ver: str):
"", # f
"", # d
"", # D
"", # K
"", # l
"", # L
"", # p
@@ -1223,14 +1299,12 @@ def main(root: str, files: Iterable[Filename], ver: str):
"", # O
"", # S
"", # N
"", # M
"", # H
"", # P
"", # A
"", # x
"", # X
"", # Y
"", # y
"", # Y
"", # b
]
arg_s = [
@@ -1247,7 +1321,6 @@ def main(root: str, files: Iterable[Filename], ver: str):
"*(float*)(R_RSP + {p}), ", # f
"*(double*)(R_RSP + {p}), ", # d
"LD2localLD((void*)(R_RSP + {p})), ", # D
"FromLD((void*)(R_RSP + {p})), ", # K
"*(intptr_t*)(R_RSP + {p}), ", # l
"*(uintptr_t*)(R_RSP + {p}), ", # L
"*(void**)(R_RSP + {p}), ", # p
@@ -1255,16 +1328,36 @@ def main(root: str, files: Iterable[Filename], ver: str):
"of_convert(*(int32_t*)(R_RSP + {p})), ", # O
"io_convert(*(void**)(R_RSP + {p})), ", # S
"*(void**)(R_RSP + {p}), ", # N
"*(void**)(R_RSP + {p}),*(void**)(R_RSP + {p} + 8), ", # M
"*(unsigned __int128*)(R_RSP + {p}), ", # H
"*(void**)(R_RSP + {p}), ", # P
"*(void**)(R_RSP + {p}), ", # A
"*(complexf_t*)(R_RSP + {p}), ", # x
"*(complex_t*)(R_RSP + {p}), ", # X
"to_complexl(emu, R_RSP + {p}), ", # Y
"to_complexk(emu, R_RSP + {p}), ", # y
"to_complexl(emu, R_RSP + {p}), ", # Y
"aligned_xcb, ", # b
]
arg_s_nold = {
'D': "FromLD((void*)(R_RSP + {p})), ", # K
'Y': "to_complexk(emu, R_RSP + {p}), ", # y
}
arg_s_android = {
'D': "*(long double*)(R_RSP + {p})], ",
'Y': "to_complexl(emu, R_RSP + {p}), ",
}
arg_s_ld = {
t: arg_s[conventions['F'].values.index(t)] for t in arg_s_nold
}
vxmm_noandroid = vxmm[:]
vxmm_android = vxmm[:]
vxmm_android[conventions['F'].values.index('D')] = 1
vxmm_android[conventions['F'].values.index('Y')] = 1
arg_x_android = {
'D': "*(long double*)&emu->xmm[{p}], ",
'Y': "to_complexl(emu, (uintptr_t)&emu->xmm[{p}]), ",
}
arg_x_ld = {
t: arg_x[conventions['F'].values.index(t)] for t in arg_x_android
}
# Asserts
for k in conventions:
@@ -1378,16 +1471,26 @@ def main(root: str, files: Iterable[Filename], ver: str):
reg_arg = ["R_RDI", "R_RSI", "R_RDX", "R_RCX", "R_R8", "R_R9"]
if (r < len(reg_arg)) and (vreg[idx] > 0):
ret = ""
for _ in range(vreg[idx]):
# There may be values in multiple registers
if (vreg[idx] == 2) and ("{p2}" in arg_r[idx]):
if r < len(reg_arg):
# Value is in a general register
ret = ret + arg_r[idx].format(p=reg_arg[r])
r = r + 1
ret = ret + arg_r[idx].format(p=reg_arg[r], p2=reg_arg[r+1])
r = r + 2
else:
# Remaining is in the stack
ret = ret + arg_s[idx].format(p=d)
d = d + 8
else:
for _ in range(vreg[idx]):
# There may be values in multiple registers
if r < len(reg_arg):
# Value is in a general register
ret = ret + arg_r[idx].format(p=reg_arg[r])
r = r + 1
else:
# Remaining is in the stack
ret = ret + arg_s[idx].format(p=d)
d = d + 8
return ret + function_args_systemV(args[1:], d, r, x)
elif (x < 8) and (vxmm[idx] > 0):
# Value is in an XMM register
@@ -1445,22 +1548,128 @@ def main(root: str, files: Iterable[Filename], ver: str):
f.write(" }\n")
for k in gbls:
any_depends_on_ld = False
if k != str(Clauses()):
file.write("\n#if " + k + "\n")
for v in gbls[k]:
if any(c in v for c in depends_on_ld):
any_depends_on_ld = True
continue
if v == FunctionType("vFv"):
# Suppress all warnings...
file.write("void vFv(x64emu_t *emu, uintptr_t fcn) { vFv_t fn = (vFv_t)fcn; fn(); (void)emu; }\n")
else:
function_writer(file, v, v + "_t")
if any_depends_on_ld:
file.write("\n#if defined(ANDROID)\n")
for c in vals_android:
for t in vals_android[c]:
vals[c][c.values.index(t)] = vals_android[c][t]
for t in arg_s_android:
arg_s[conventions['F'].values.index(t)] = arg_s_android[t]
for t in arg_x_android:
arg_x[conventions['F'].values.index(t)] = arg_x_android[t]
vxmm = vxmm_android
for v in gbls[k]:
if all(c not in v for c in depends_on_ld):
continue
if v == FunctionType("vFv"):
# Suppress all warnings...
file.write("void vFv(x64emu_t *emu, uintptr_t fcn) { vFv_t fn = (vFv_t)fcn; fn(); (void)emu; }\n")
else:
function_writer(file, v, v + "_t")
file.write("#elif !defined(HAVE_LD80BITS)\n")
for c in vals_android:
for t in vals_ld[c]:
vals[c][c.values.index(t)] = vals_ld[c][t]
for c in vals_nold:
for t in vals_nold[c]:
vals[c][c.values.index(t)] = vals_nold[c][t]
for t in arg_s_android:
arg_s[conventions['F'].values.index(t)] = arg_s_ld[t]
for t in arg_s_nold:
arg_s[conventions['F'].values.index(t)] = arg_s_nold[t]
for t in arg_x_android:
arg_x[conventions['F'].values.index(t)] = arg_x_ld[t]
vxmm = vxmm_noandroid
for v in gbls[k]:
if all(c not in v for c in depends_on_ld):
continue
if v == FunctionType("vFv"):
# Suppress all warnings...
file.write("void vFv(x64emu_t *emu, uintptr_t fcn) { vFv_t fn = (vFv_t)fcn; fn(); (void)emu; }\n")
else:
function_writer(file, v, v + "_t")
for c in vals_nold:
for t in vals_nold[c]:
vals[c][c.values.index(t)] = vals_ld[c][t]
for t in arg_s_nold:
arg_s[conventions['F'].values.index(t)] = arg_s_ld[t]
file.write("#else // defined(HAVE_LD80BITS) && !defined(ANDROID)\n")
for v in gbls[k]:
if all(c not in v for c in depends_on_ld):
continue
if v == FunctionType("vFv"):
# Suppress all warnings...
file.write("void vFv(x64emu_t *emu, uintptr_t fcn) { vFv_t fn = (vFv_t)fcn; fn(); (void)emu; }\n")
else:
function_writer(file, v, v + "_t")
file.write("#endif\n")
if k != str(Clauses()):
file.write("#endif\n")
file.write("\n")
for k in redirects:
any_depends_on_ld = False
if k != str(Clauses()):
file.write("\n#if " + k + "\n")
for vr, vf in redirects[k]:
if any(c in vr for c in depends_on_ld):
any_depends_on_ld = True
continue
function_writer(file, vr, vf + "_t")
if any_depends_on_ld:
file.write("\n#if defined(ANDROID)\n")
for c in vals_android:
for t in vals_android[c]:
vals[c][c.values.index(t)] = vals_android[c][t]
for t in arg_s_android:
arg_s[conventions['F'].values.index(t)] = arg_s_android[t]
for t in arg_x_android:
arg_x[conventions['F'].values.index(t)] = arg_x_android[t]
vxmm = vxmm_android
for vr, vf in redirects[k]:
if all(c not in vr for c in depends_on_ld):
continue
function_writer(file, vr, vf + "_t")
file.write("#elif !defined(HAVE_LD80BITS)\n")
for c in vals_android:
for t in vals_ld[c]:
vals[c][c.values.index(t)] = vals_ld[c][t]
for c in vals_nold:
for t in vals_nold[c]:
vals[c][c.values.index(t)] = vals_nold[c][t]
for t in arg_s_android:
arg_s[conventions['F'].values.index(t)] = arg_s_ld[t]
for t in arg_s_nold:
arg_s[conventions['F'].values.index(t)] = arg_s_nold[t]
for t in arg_x_android:
arg_x[conventions['F'].values.index(t)] = arg_x_ld[t]
vxmm = vxmm_noandroid
for vr, vf in redirects[k]:
if all(c not in vr for c in depends_on_ld):
continue
function_writer(file, vr, vf + "_t")
for c in vals_nold:
for t in vals_nold[c]:
vals[c][c.values.index(t)] = vals_ld[c][t]
for t in arg_s_nold:
arg_s[conventions['F'].values.index(t)] = arg_s_ld[t]
file.write("#else // defined(HAVE_LD80BITS) && !defined(ANDROID)\n")
for vr, vf in redirects[k]:
if all(c not in vr for c in depends_on_ld):
continue
function_writer(file, vr, vf + "_t")
file.write("#endif\n")
if k != str(Clauses()):
file.write("#endif\n")
@@ -1468,7 +1677,7 @@ def main(root: str, files: Iterable[Filename], ver: str):
inttext = ""
file.write("\n")
for k1 in simple_idxs:
file.write("#{inttext}if defined({k1})\nint isSimpleWrapper(wrapper_t fun) {{\n".format(inttext=inttext, k1=k1))
file.write("#{inttext}if defined({k1})\nint isSimpleWrapper(wrapper_t fun) {{\n\tif (box64_is32bits) return 0;\n".format(inttext=inttext, k1=k1))
inttext = "el"
for k in simple_idxs[k1]:
if k != str(Clauses()):
@@ -1478,9 +1687,10 @@ def main(root: str, files: Iterable[Filename], ver: str):
if k != str(Clauses()):
file.write("#endif\n")
file.write("\treturn 0;\n}\n")
file.write("\n#else\nint isSimpleWrapper(wrapper_t fun) {\n\treturn 0;\n}\n#endif\n")
file.write("#else\nint isSimpleWrapper(wrapper_t fun) {\n\treturn 0;\n}\n#endif\n")
# Write the isRetX87Wrapper function
file.write("\nint isRetX87Wrapper32(wrapper_t fun)\n#ifndef BOX32\n{ return 0; }\n#else\n ;\n#endif\n")
file.write("\nint isRetX87Wrapper(wrapper_t fun) {\n")
for k in retx87_idxs:
if k != str(Clauses()):
@@ -1559,11 +1769,11 @@ def main(root: str, files: Iterable[Filename], ver: str):
return 0
if __name__ == '__main__':
limit = []
limit: List[int] = []
for i, v in enumerate(sys.argv):
if v == "--":
limit.append(i)
Define.defines = list(map(DefineType, sys.argv[2:limit[0]]))
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.4.0.21") != 0:
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.5.0.24") != 0:
exit(2)
exit(0)
+1647
View File
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -19,10 +19,10 @@ set(ENV{BOX64_LOG} 0)
set(ENV{BOX64_NOBANNER} 1)
if( EXISTS ${CMAKE_SOURCE_DIR}/x64lib )
# we are inside box64 folder
set(ENV{LD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/x64lib)
set(ENV{BOX64_LD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/x64lib)
else()
# we are inside build folder
set(ENV{LD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/../x64lib)
set(ENV{BOX64_LD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/../x64lib)
endif( EXISTS ${CMAKE_SOURCE_DIR}/x64lib )
# run the test program, capture the stdout/stderr and the result var
+342
View File
@@ -0,0 +1,342 @@
#include <stdint.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include "debug.h"
#include "box32.h"
#include "custommem.h"
#include "converter32.h"
#include "khash.h"
KHASH_MAP_INIT_INT64(to, ulong_t);
KHASH_MAP_INIT_INT(from, uintptr_t);
KHASH_MAP_INIT_STR(strings, ptr_t);
static kh_from_t* hash_from = NULL;
static kh_to_t* hash_to = NULL;
#define HASH_MSK 0xf000000f
#define HASH_VAL 0x00ffffff
#define HASH_SHIFT 4
static uint32_t hash_cnt = 1;
static pthread_rwlock_t hash_lock = {0};
static int hash_running = 0;
// locale
static kh_from_t* locale_from = NULL;
static kh_to_t* locale_to = NULL;
static kh_strings_t* const_strings = NULL;
void init_hash_helper() {
hash_from = kh_init(from);
hash_to = kh_init(to);
locale_from = kh_init(from);
locale_to = kh_init(to);
const_strings = kh_init(strings);
pthread_rwlock_init(&hash_lock, NULL);
hash_running = 1;
}
void fini_hash_helper() {
if(!hash_running)
return;
hash_running = 0;
kh_destroy(from, hash_from);
hash_from = NULL;
kh_destroy(to, hash_to);
hash_to = NULL;
hash_cnt = 1;
kh_destroy(from, locale_from);
locale_from = NULL;
kh_destroy(to, locale_to);
locale_to = NULL;
kh_destroy(strings, const_strings); //TODO: does not free memory correctly
const_strings = NULL;
pthread_rwlock_destroy(&hash_lock);
}
// Convert from hash key to original 64bits value
uintptr_t from_hash(ulong_t l) {
// easy case first
if((l&HASH_MSK)!=HASH_MSK) {
return (uintptr_t)l;
}
if(l==0xffffffff) {
return 0xffffffffffffffffll;
}
// get value from hash table second
uintptr_t ret = 0;
if(!hash_running) {
//printf_log(LOG_INFO, "Warning, from_hash used but hash not running\n");
return ret;
}
pthread_rwlock_rdlock(&hash_lock);
khint_t k = kh_get(from, hash_from, l);
if (k==kh_end(hash_from)) {
ret = (uintptr_t)l;
} else {
ret = kh_value(hash_from, k);
}
pthread_rwlock_unlock(&hash_lock);
return ret;
}
// same as from_hash
uintptr_t from_hash_d(ulong_t l) {
return from_hash(l);
}
// Convert from 64bits to hash key, creating it if needed
ulong_t to_hash(uintptr_t p) {
if((p<0x100000000LL) && ((p&HASH_MSK)!=HASH_MSK))
return (ulong_t)p;
if(p==0xffffffffffffffffll) {
return 0xffffffff;
}
ulong_t ret = 0;
if(!hash_running) {
//printf_log(LOG_INFO, "Warning, to_hash used but hash not running\n");
return ret;
}
khint_t k;
pthread_rwlock_rdlock(&hash_lock);
k = kh_get(to, hash_to, p);
if(k==kh_end(hash_to)) {
// create a new key, but need write lock!
pthread_rwlock_unlock(&hash_lock);
pthread_rwlock_wrlock(&hash_lock);
ret = HASH_MSK | (((hash_cnt++)&HASH_VAL)<<HASH_SHIFT);
int r;
k = kh_put(to, hash_to, p, &r);
kh_value(hash_to, k) = ret;
k = kh_put(from, hash_from, ret, &r);
kh_value(hash_from, k) = p;
} else {
ret = kh_value(hash_to, k);
}
pthread_rwlock_unlock(&hash_lock);
return ret;
}
// Convert from 64bits to hash key and delete the entry from both hash table
ulong_t to_hash_d(uintptr_t p) {
if((p<0x100000000LL) && ((p&HASH_MSK)!=HASH_MSK))
return (ulong_t)p;
if(p==0xffffffffffffffffll)
return 0xffffffff;
ulong_t ret = 0;
if(!hash_running) {
//printf_log(LOG_INFO, "Warning, to_hash_d used but hash not running\n");
return ret;
}
khint_t k;
pthread_rwlock_wrlock(&hash_lock);
k = kh_get(to, hash_to, p);
if(k==kh_end(hash_to)) {
/// should this be an assert?
} else {
ret = kh_value(hash_to, k);
// delete both entries
//k = kh_get(to, hash_to, p);
kh_del(to, hash_to, k);
k = kh_get(from, hash_from, ret);
kh_del(from, hash_from, k);
}
pthread_rwlock_unlock(&hash_lock);
return ret;
}
typedef struct struct_locale_s {
void* p0[13];
void* p1; //const unsigned short int *__ctype_b;
void* p2; //const int *__ctype_tolower;
void* p3; //const int *__ctype_toupper;
void* p4[13];
} struct_locale_t;
// not a real structure
#define LOCALE_SIGN 0x54abcd845412LL
typedef struct struct_locale_32_s {
ptr_t p0[13];
ptr_t p1;
ptr_t p2;
ptr_t p3;
ptr_t p4[13];
uint64_t sign;
struct_locale_t* org; // save the orginal locale
// copy of the array, in case some apps use them
unsigned short int type_b[384];
int tolower[384];
int tohigher[384];
} struct_locale_32_t;
void to_struct_locale(ptr_t d, const struct_locale_t *src) {
if (!src) return;
struct_locale_32_t* dest = from_ptrv(d);
// save the original locale
dest->sign = LOCALE_SIGN;
dest->org = (void*)src;
//copy the 2 arrays
for(int i=0; i<13; ++i) {
dest->p0[i] = to_hashv(src->p0[i]);
}
for(int i=0; i<13; ++i) {
dest->p4[i] = to_hashv(src->p4[i]);
}
// copy the 3 ctype int (1st is short int, but int will do)
memcpy(dest->type_b, src->p1-128*sizeof(short), 384*sizeof(short));
memcpy(dest->tolower, src->p2-128*sizeof(int), 384*sizeof(int));
memcpy(dest->tohigher, src->p3-128*sizeof(int), 384*sizeof(int));
dest->p1 = to_ptrv(dest->type_b)+128*sizeof(short);
dest->p2 = to_ptrv(dest->tolower)+128*sizeof(int);
dest->p3 = to_ptrv(dest->tohigher)+128*sizeof(int);
}
void free_struct_locale(const struct_locale_t *src) {
for(int i=0; i<13; ++i) {
to_hash_d((uintptr_t)src->p0[i]);
}
for(int i=0; i<13; ++i) {
to_hash_d((uintptr_t)src->p4[i]);
}
}
// Convert from locale key to original 64bits value
void* from_locale(ptr_t l) {
// easy case first
if(l < 0x100) {
return from_ptrv(l);
}
if(l == 0xffffffff) {
return (void*)-1;
}
// get value from hash table second
void* ret = 0;
if(!hash_running) {
//printf_log(LOG_INFO, "Warning, from_locale used but hash not running\n");
return ret;
}
struct_locale_32_t* loc = from_ptrv(l);
if(loc->sign==LOCALE_SIGN)
return loc->org;
pthread_rwlock_rdlock(&hash_lock);
khint_t k = kh_get(from, locale_from, l);
if (k==kh_end(locale_from)) {
ret = from_ptrv(l);
} else {
ret = (void*)kh_value(locale_from, k);
}
pthread_rwlock_unlock(&hash_lock);
//from_struct_locale((struct_locale_t*)ret, l);
return ret;
}
// same as from_locale
void* from_locale_d(ptr_t l) {
return from_locale(l);
}
// Convert from 64bits to locale key, creating it if needed
ptr_t to_locale(void* p) {
if((uintptr_t)p < 0x100) {
return to_ptrv(p);
}
if(p == (void*)-1) {
return 0xffffffff;
}
ptr_t ret = 0;
if(!hash_running) {
//printf_log(LOG_INFO, "Warning, to_locale used but hash not running\n");
return ret;
}
khint_t k;
pthread_rwlock_rdlock(&hash_lock);
k = kh_get(to, locale_to, (uintptr_t)p);
int conv = 0;
if(k==kh_end(locale_to)) {
// create a new key, but need write lock!
pthread_rwlock_unlock(&hash_lock);
pthread_rwlock_wrlock(&hash_lock);
// a locale_t is 5 pointer!
void* m = calloc(1, sizeof(struct_locale_32_t)); // the 3 ctype value are also inside the locale struct
ret = to_ptrv(m);
// add to hash maps
int r;
k = kh_put(to, locale_to, (uintptr_t)p, &r);
kh_value(locale_to, k) = ret;
k = kh_put(from, locale_from, ret, &r);
kh_value(locale_from, k) = (uintptr_t)p;
conv = 1;
} else {
ret = kh_value(locale_to, k);
}
pthread_rwlock_unlock(&hash_lock);
if(conv)
to_struct_locale(ret, (struct_locale_t*)p);
return ret;
}
// Convert from 64bits to hash key and delete the entry from both hash table
ptr_t to_locale_d(void* p) {
if((uintptr_t)p < 0x100)
return to_ptrv(p);
ptr_t ret = 0;
if(!hash_running)
return ret;
khint_t k;
pthread_rwlock_wrlock(&hash_lock);
k = kh_get(to, locale_to, (uintptr_t)p);
if(k==kh_end(locale_to)) {
/// should this be an assert?
} else {
ret = kh_value(locale_to, k);
// free the memory
free_struct_locale(p);
free(from_ptrv(ret));
// delete both entries
k = kh_get(to, locale_to, (uintptr_t)p);
kh_del(to, locale_to, k);
k = kh_get(from, locale_from, ret);
kh_del(from, locale_from, k);
}
pthread_rwlock_unlock(&hash_lock);
return ret;
}
char* from_cstring(ptr_t p) {
return (char*)from_ptrv(p);
}
ptr_t to_cstring(char* p) {
if((uintptr_t)p<0x100000000LL)
return to_ptrv(p);
ptr_t ret = 0;
pthread_rwlock_rdlock(&hash_lock);
khint_t k = kh_get(strings, const_strings, p);
if(k==kh_end(const_strings)) {
// create a new key, but need write lock!
pthread_rwlock_unlock(&hash_lock);
pthread_rwlock_wrlock(&hash_lock);
ret = to_ptrv(box_strdup(p));
int r;
k = kh_put(strings, const_strings, (char*)from_ptrv(ret), &r);
kh_value(const_strings, k) = ret;
} else
ret = kh_value(const_strings, k);
pthread_rwlock_unlock(&hash_lock);
return ret;
}
ptr_t to_cstring_d(char* p) {
if((uintptr_t)p<0x100000000LL)
return to_ptrv(p);
ptr_t ret = 0;
pthread_rwlock_wrlock(&hash_lock);
khint_t k = kh_get(strings, const_strings, p);
if(k==kh_end(const_strings)) {
// assert?
} else {
ret = kh_value(const_strings, k);
kh_del(strings, const_strings, k);
free(from_ptrv(ret));
}
pthread_rwlock_unlock(&hash_lock);
return ret;
}
+29 -15
View File
@@ -23,6 +23,9 @@
#include "gltools.h"
#include "rbtree.h"
#include "dynarec.h"
#ifdef BOX32
#include "box32.h"
#endif
EXPORTDYN
void initAllHelpers(box64context_t* context)
@@ -31,6 +34,9 @@ void initAllHelpers(box64context_t* context)
if(inited)
return;
my_context = context;
#ifdef BOX32
init_hash_helper();
#endif
init_pthread_helper();
init_bridge_helper();
init_signal_helper(context);
@@ -47,6 +53,9 @@ void finiAllHelpers(box64context_t* context)
fini_pthread_helper(context);
fini_signal_helper();
fini_bridge_helper();
#ifdef BOX32
fini_hash_helper();
#endif
fini_custommem_helper(context);
finied = 1;
}
@@ -75,6 +84,7 @@ void free_tlsdatasize(void* p)
}
void x64Syscall(x64emu_t *emu);
void x86Syscall(x64emu_t *emu);
int unlockMutex()
{
@@ -128,7 +138,7 @@ void relockMutex(int locks)
#undef GO
}
static void init_mutexes(box64context_t* context)
void init_mutexes(box64context_t* context)
{
#ifndef DYNAREC
pthread_mutexattr_t attr;
@@ -213,25 +223,27 @@ box64context_t *NewBox64Context(int argc)
init_custommem_helper(context);
#ifdef DYNAREC
x64test_init();
#endif
context->maplib = NewLibrarian(context);
context->local_maplib = NewLibrarian(context);
context->versym = NewDictionnary();
context->system = NewBridge();
// Cannot use Bridge name as the map is not initialized yet
// create vsyscall
context->vsyscall = AddBridge(context->system, vFEv, x64Syscall, 0, NULL);
context->vsyscall = AddBridge(context->system, vFEv, box64_is32bits?x86Syscall:x64Syscall, 0, NULL);
// create the vsyscalls
context->vsyscalls[0] = AddVSyscall(context->system, 96);
context->vsyscalls[1] = AddVSyscall(context->system, 201);
context->vsyscalls[2] = AddVSyscall(context->system, 309);
// create the alternate to map at address
addAlternate((void*)0xffffffffff600000, (void*)context->vsyscalls[0]);
addAlternate((void*)0xffffffffff600400, (void*)context->vsyscalls[1]);
addAlternate((void*)0xffffffffff600800, (void*)context->vsyscalls[2]);
if(box64_is32bits) {
#ifdef BOX32
addAlternate((void*)0xffffe400, from_ptrv(context->vsyscall));
#endif
} else {
context->vsyscalls[0] = AddVSyscall(context->system, 96);
context->vsyscalls[1] = AddVSyscall(context->system, 201);
context->vsyscalls[2] = AddVSyscall(context->system, 309);
// create the alternate to map at address
addAlternate((void*)0xffffffffff600000, (void*)context->vsyscalls[0]);
addAlternate((void*)0xffffffffff600400, (void*)context->vsyscalls[1]);
addAlternate((void*)0xffffffffff600800, (void*)context->vsyscalls[2]);
}
// create exit bridge
context->exit_bridge = AddBridge(context->system, NULL, NULL, 0, NULL);
// get handle to box64 itself
@@ -275,7 +287,7 @@ box64context_t *NewBox64Context(int argc)
initAllHelpers(context);
#ifdef DYNAREC
context->db_sizes = init_rbtree();
context->db_sizes = rbtree_init("db_sizes");
#endif
return context;
@@ -351,6 +363,8 @@ void FreeBox64Context(box64context_t** context)
#ifndef STATICBUILD
freeGLProcWrapper(ctx);
freeALProcWrapper(ctx);
#ifdef BOX32
#endif
#endif
if(ctx->stack_clone)
@@ -377,7 +391,7 @@ void FreeBox64Context(box64context_t** context)
#ifdef DYNAREC
//dynarec_log(LOG_INFO, "BOX64 Dynarec at exit: Max DB=%d, righter=%d\n", ctx->max_db_size, rb_get_righter(ctx->db_sizes));
delete_rbtree(ctx->db_sizes);
rbtree_delete(ctx->db_sizes);
#endif
finiAllHelpers(ctx);
+2 -2
View File
@@ -2,7 +2,7 @@
#define __BOX64_VERSION_H_
#define BOX64_MAJOR 0
#define BOX64_MINOR 2
#define BOX64_REVISION 8
#define BOX64_MINOR 3
#define BOX64_REVISION 2
#endif //__BOX64_VERSION_H_
+534 -181
View File
File diff suppressed because it is too large. Load diff
+619 -211
View File
File diff suppressed because it is too large. Load diff
+53
View File
@@ -0,0 +1,53 @@
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <unistd.h>
#include <stdint.h>
#ifndef MAP_FAILED
#define MAP_FAILED ((void *) -1)
#endif
#define EXPORT __attribute__((visibility("default")))
#ifdef BUILD_DYNAMIC
#define EXPORTDYN __attribute__((visibility("default")))
#else
#define EXPORTDYN
#endif
#ifndef MAP_32BIT
#define MAP_32BIT 0x40
#endif
typedef void x64emu_t;
extern void* mapallmem;
extern int box64_is32bits;
void setProtection(uintptr_t addr, size_t size, uint32_t prot);
void freeProtection(uintptr_t addr, size_t size);
void* internal_mmap(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset);
int internal_munmap(void* addr, unsigned long length);
void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset);
extern int running32bits;
extern int box64_mmap32;
EXPORT void* mmap64(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset)
{
void* ret;
if(!addr && ((running32bits && box64_mmap32) || (flags&MAP_32BIT) || box64_is32bits))
ret = my_mmap64(NULL, addr, length, prot, flags | MAP_32BIT, fd, offset);
else
ret = internal_mmap(addr, length, prot, flags, fd, offset);
if(ret!=MAP_FAILED && mapallmem)
setProtection((uintptr_t)ret, length, prot);
return ret;
}
EXPORT void* mmap(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset) __attribute__((alias("mmap64")));
EXPORT int munmap(void* addr, unsigned long length)
{
int ret = internal_munmap(addr, length);
if(!ret && mapallmem) {
freeProtection((uintptr_t)addr, length);
}
return ret;
}
+228 -53
View File
@@ -5,6 +5,41 @@
*/
/*
ARM64 Linux Call Convention
SP The Stack Pointer.
r30 LR The Link Register.
r29 FP The Frame Pointer
r19…r28 Callee-saved registers
r18 The Platform Register, if needed; otherwise a temporary register. See notes.
r17 IP1 The second intra-procedure-call temporary register (can be used by call veneers and PLT code); at other times may be used as a temporary register.
r16 IP0 The first intra-procedure-call scratch register (can be used by call veneers and PLT code); at other times may be used as a temporary register.
r9…r15 Temporary registers
r8 Indirect result location register
r0…r7 Parameter/result registers
For SIMD:
The first eight registers, v0-v7, are used to pass argument values into a subroutine and to return result values from a function.
They may also be used to hold intermediate values within a routine (but, in general, only between subroutine calls).
Registers v8-v15 must be preserved by a callee across subroutine calls;
the remaining registers (v0-v7, v16-v31) do not need to be preserved (or should be preserved by the caller).
Additionally, only the bottom 64 bits of each value stored in v8-v15 need to be preserved [8];
it is the responsibility of the caller to preserve larger values.
For SVE:
z0-z7 are used to pass scalable vector arguments to a subroutine, and to return scalable vector results from a function.
If a subroutine takes at least one argument in scalable vector registers or scalable predicate registers,
or returns results in such regisers, the subroutine must ensure that the entire contents of z8-z23 are preserved across the call.
In other cases it need only preserve the low 64 bits of z8-z15, as described in SIMD and Floating-Point registers.
p0-p3 are used to pass scalable predicate arguments to a subroutine and to return scalable predicate results from a function.
If a subroutine takes at least one argument in scalable vector registers or scalable predicate registers,
or returns results in such registers, the subroutine must ensure that p4-p15 are preserved across the call.
In other cases it need not preserve any scalable predicate register contents.
*/
// x86 Register mapping
#define xRAX 10
#define xRCX 11
@@ -25,6 +60,10 @@
#define xFlags 26
#define xRIP 27
#define xSavedSP 28
// convert a x86 register to native according to the register mapping
#define TO_NAT(A) (xRAX + (A))
// 32bits version
#define wEAX xRAX
#define wECX xRCX
@@ -143,35 +182,37 @@ int convert_bitmask(uint64_t bitmask);
// ADD / SUB
#define ADDSUB_REG_gen(sf, op, S, shift, Rm, imm6, Rn, Rd) ((sf)<<31 | (op)<<30 | (S)<<29 | 0b01011<<24 | (shift)<<22 | (Rm)<<16 | (imm6)<<10 | (Rn)<<5 | (Rd))
#define ADDx_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(1, 0, 0, 0b00, Rm, 0, Rn, Rd))
#define ADDSx_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(1, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDSx_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(1, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(1, 0, 0, 0b00, Rm, lsl, Rn, Rd))
#define ADDz_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(rex.is32bits?0:1, 0, 0, 0b00, Rm, lsl, Rn, Rd))
#define ADDw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 0, 0, 0b00, Rm, 0, Rn, Rd))
#define ADDSw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDSw_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(0, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(0, 0, 0, 0b00, Rm, lsl, Rn, Rd))
#define ADDSw_REG_LSL(Rd, Rn, Rm, lsl) FEMIT(ADDSUB_REG_gen(0, 0, 1, 0b00, Rm, lsl, Rn, Rd))
#define ADDxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 0, 0, 0b00, Rm, 0, Rn, Rd))
#define ADDz_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.is32bits?0:1, 0, 0, 0b00, Rm, 0, Rn, Rd))
#define ADDSxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDSxw_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(rex.w, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDxw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(ADDSUB_REG_gen(rex.w, 0, 0, 0b01, Rm, lsr, Rn, Rd))
#define ADDSUB_IMM_gen(sf, op, S, shift, imm12, Rn, Rd) ((sf)<<31 | (op)<<30 | (S)<<29 | 0b10001<<24 | (shift)<<22 | (imm12)<<10 | (Rn)<<5 | (Rd))
#define ADDx_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(1, 0, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDSx_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(1, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDSx_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(1, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(0, 0, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDSw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(0, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDSw_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(0, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDxw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.w, 0, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDSxw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.w, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDSxw_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(rex.w, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDz_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.is32bits?0:1, 0, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBx_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(1, 1, 0, 0b00, Rm, 0, Rn, Rd))
#define SUBSx_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(1, 1, 1, 0b00, Rm, 0, Rn, Rd))
#define SUBSx_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(1, 1, 1, 0b00, Rm, 0, Rn, Rd))
#define SUBx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(1, 1, 0, 0b00, Rm, lsl, Rn, Rd))
#define SUBw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 1, 0, 0b00, Rm, 0, Rn, Rd))
#define SUBw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(0, 1, 0, 0b00, Rm, lsl, Rn, Rd))
#define SUBSw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 1, 1, 0b00, Rm, 0, Rn, Rd))
#define SUBSw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(0, 1, 1, 0b00, Rm, lsl, Rn, Rd))
#define SUBSw_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(0, 1, 1, 0b00, Rm, 0, Rn, Rd))
#define SUBSw_REG_LSL(Rd, Rn, Rm, lsl) FEMIT(ADDSUB_REG_gen(0, 1, 1, 0b00, Rm, lsl, Rn, Rd))
#define SUBxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 1, 0, 0b00, Rm, 0, Rn, Rd))
#define SUBz_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.is32bits?0:1, 1, 0, 0b00, Rm, 0, Rn, Rd))
#define SUBSxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 1, 1, 0b00, Rm, 0, Rn, Rd))
#define SUBSxw_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(rex.w, 1, 1, 0b00, Rm, 0, Rn, Rd))
#define CMPSx_REG(Rn, Rm) SUBSx_REG(xZR, Rn, Rm)
#define CMPSw_REG(Rn, Rm) SUBSw_REG(wZR, Rn, Rm)
#define CMPSxw_REG(Rn, Rm) SUBSxw_REG(xZR, Rn, Rm)
@@ -183,12 +224,12 @@ int convert_bitmask(uint64_t bitmask);
#define NEGSxw_REG(Rd, Rm) SUBSxw_REG(Rd, xZR, Rm);
#define SUBx_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(1, 1, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBSx_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(1, 1, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBSx_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(1, 1, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(0, 1, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBSw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(0, 1, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBSw_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(0, 1, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBxw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.w, 1, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBz_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.is32bits?0:1, 1, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBSxw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.w, 1, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBSxw_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(rex.w, 1, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define CMPSx_U12(Rn, imm12) SUBSx_U12(xZR, Rn, imm12)
#define CMPSw_U12(Rn, imm12) SUBSw_U12(wZR, Rn, imm12)
#define CMPSxw_U12(Rn, imm12) SUBSxw_U12(xZR, Rn, imm12)
@@ -200,18 +241,18 @@ int convert_bitmask(uint64_t bitmask);
#define SBCx_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(1, 1, 0, Rm, Rn, Rd))
#define SBCw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(0, 1, 0, Rm, Rn, Rd))
#define SBCxw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(rex.w, 1, 0, Rm, Rn, Rd))
#define ADCSx_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(1, 0, 1, Rm, Rn, Rd))
#define ADCSw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(0, 0, 1, Rm, Rn, Rd))
#define ADCSxw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(rex.w, 0, 1, Rm, Rn, Rd))
#define SBCSx_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(1, 1, 1, Rm, Rn, Rd))
#define SBCSw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(0, 1, 1, Rm, Rn, Rd))
#define SBCSxw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(rex.w, 1, 1, Rm, Rn, Rd))
#define ADCSx_REG(Rd, Rn, Rm) FEMIT(ADDSUBC_gen(1, 0, 1, Rm, Rn, Rd))
#define ADCSw_REG(Rd, Rn, Rm) FEMIT(ADDSUBC_gen(0, 0, 1, Rm, Rn, Rd))
#define ADCSxw_REG(Rd, Rn, Rm) FEMIT(ADDSUBC_gen(rex.w, 0, 1, Rm, Rn, Rd))
#define SBCSx_REG(Rd, Rn, Rm) FEMIT(ADDSUBC_gen(1, 1, 1, Rm, Rn, Rd))
#define SBCSw_REG(Rd, Rn, Rm) FEMIT(ADDSUBC_gen(0, 1, 1, Rm, Rn, Rd))
#define SBCSxw_REG(Rd, Rn, Rm) FEMIT(ADDSUBC_gen(rex.w, 1, 1, Rm, Rn, Rd))
// CCMP compare if cond is true, set nzcv if false
#define CCMP_reg(sf, Rm, cond, Rn, nzcv) ((sf)<<31 | 1<<30 | 1<<29 | 0b11010010<<21 | (Rm)<<16 | (cond)<<12 | (Rn)<<5 | (nzcv))
#define CCMPw(Wn, Wm, nzcv, cond) EMIT(CCMP_reg(0, Wm, cond, Wn, nzcv))
#define CCMPx(Xn, Xm, nzcv, cond) EMIT(CCMP_reg(1, Xm, cond, Xn, nzcv))
#define CCMPxw(Xn, Xm, nzcv, cond) EMIT(CCMP_reg(rex.w, Xm, cond, Xn, nzcv))
#define CCMPw(Wn, Wm, nzcv, cond) FEMIT(CCMP_reg(0, Wm, cond, Wn, nzcv))
#define CCMPx(Xn, Xm, nzcv, cond) FEMIT(CCMP_reg(1, Xm, cond, Xn, nzcv))
#define CCMPxw(Xn, Xm, nzcv, cond) FEMIT(CCMP_reg(rex.w, Xm, cond, Xn, nzcv))
// ADR
#define ADR_gen(immlo, immhi, Rd) ((immlo)<<29 | 0b10000<<24 | (immhi)<<5 | (Rd))
@@ -248,13 +289,19 @@ int convert_bitmask(uint64_t bitmask);
#define LDRx_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b011, 0, Rn, Rt))
#define LDRx_REG_LSL3(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b011, 1, Rn, Rt))
#define LDRx_REG_UXTW3(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b010, 1, Rn, Rt))
#define LDRx_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b110, 0, Rn, Rt))
#define LDRw_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10, Rm, 0b011, 0, Rn, Rt))
#define LDRw_REG_LSL2(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10, Rm, 0b011, 1, Rn, Rt))
#define LDRw_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10, Rm, 0b110, 0, Rn, Rt))
#define LDRxw_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10+rex.w, Rm, 0b011, 0, Rn, Rt))
#define LDRz_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(rex.is32bits?0b10:0b11, Rm, 0b011, 0, Rn, Rt))
#define LDRxw_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10+rex.w, Rm, 0b110, 0, Rn, Rt))
#define LDRz_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(rex.is32bits?0b10:0b11, Rm, 0b110, 0, Rn, Rt))
#define LDRB_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b011, 0, Rn, Rt))
#define LDRB_REG_UXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b010, 0, Rn, Rt))
#define LDRB_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b110, 0, Rn, Rt))
#define LDRH_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b01, Rm, 0b011, 0, Rn, Rt))
#define LDRH_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b01, Rm, 0b110, 0, Rn, Rt))
#define LDRS_U12_gen(size, op1, opc, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | (opc)<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
#define LDRSHx_U12(Rt, Rn, imm12) EMIT(LDRS_U12_gen(0b01, 0b01, 0b10, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
@@ -266,6 +313,7 @@ int convert_bitmask(uint64_t bitmask);
#define LDRS_REG_gen(size, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 0b10<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | (0b10)<<10 | (Rn)<<5 | (Rt))
#define LDRSW_REG(Rt, Rn, Rm) EMIT(LDRS_REG_gen(0b10, Rm, 0b011, 0, Rn, Rt))
#define LDRSW_REG_SXTW(Rt, Rn, Rm) EMIT(LDRS_REG_gen(0b10, Rm, 0b110, 0, Rn, Rt))
#define LDR_PC_gen(opc, imm19, Rt) ((opc)<<30 | 0b011<<27 | (imm19)<<5 | (Rt))
#define LDRx_literal(Rt, imm19) EMIT(LDR_PC_gen(0b01, ((imm19)>>2)&0x7FFFF, Rt))
@@ -336,12 +384,18 @@ int convert_bitmask(uint64_t bitmask);
#define STRx_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(0b11, Rm, 0b011, 0, Rn, Rt))
#define STRx_REG_LSL3(Rt, Rn, Rm) EMIT(STR_REG_gen(0b11, Rm, 0b011, 1, Rn, Rt))
#define STRx_REG_UXTW(Rt, Rn, Rm) EMIT(STR_REG_gen(0b11, Rm, 0b010, 0, Rn, Rt))
#define STRx_REG_SXTW(Rt, Rn, Rm) EMIT(STR_REG_gen(0b11, Rm, 0b110, 0, Rn, Rt))
#define STRw_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(0b10, Rm, 0b011, 0, Rn, Rt))
#define STRw_REG_LSL2(Rt, Rn, Rm) EMIT(STR_REG_gen(0b10, Rm, 0b011, 1, Rn, Rt))
#define STRw_REG_SXTW(Rt, Rn, Rm) EMIT(STR_REG_gen(0b10, Rm, 0b110, 0, Rn, Rt))
#define STRB_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(0b00, Rm, 0b011, 0, Rn, Rt))
#define STRB_REG_SXTW(Rt, Rn, Rm) EMIT(STR_REG_gen(0b00, Rm, 0b110, 0, Rn, Rt))
#define STRH_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(0b01, Rm, 0b011, 0, Rn, Rt))
#define STRH_REG_SXTW(Rt, Rn, Rm) EMIT(STR_REG_gen(0b01, Rm, 0b110, 0, Rn, Rt))
#define STRxw_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(rex.w?0b11:0b10, Rm, 0b011, 0, Rn, Rt))
#define STRxw_REG_SXTW(Rt, Rn, Rm) EMIT(STR_REG_gen(rex.w?0b11:0b10, Rm, 0b110, 0, Rn, Rt))
#define STRz_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(rex.is32bits?0b10:0b11, Rm, 0b011, 0, Rn, Rt))
#define STRz_REG_SXTW(Rt, Rn, Rm) EMIT(STR_REG_gen(rex.is32bits?0b10:0b11, Rm, 0b110, 0, Rn, Rt))
// LOAD/STORE PAIR
#define MEMPAIR_gen(size, L, op2, imm7, Rt2, Rn, Rt) ((size)<<31 | 0b101<<27 | (op2)<<23 | (L)<<22 | (imm7)<<15 | (Rt2)<<10 | (Rn)<<5 | (Rt))
@@ -441,12 +495,19 @@ int convert_bitmask(uint64_t bitmask);
// Data Memory Barrier
#define DMB_gen(CRm) (0b1101010100<<22 | 0b011<<16 | 0b0011<<12 | (CRm)<<8 | 1<<7 | 0b01<<5 | 0b11111)
#define DMB_ISH() EMIT(DMB_gen(0b1011))
#define DMB_ISHLD() EMIT(DMB_gen(0b1001))
#define DMB_ISHST() EMIT(DMB_gen(0b1010))
#define DMB_LD() EMIT(DMB_gen(0b1101))
#define DMB_ST() EMIT(DMB_gen(0b1110))
#define DMB_SY() EMIT(DMB_gen(0b1111))
// Data Synchronization Barrier
#define DSB_gen(CRm) (0b1101010100<<22 | 0b011<<16 | 0b0011<<12 | (CRm)<<8 | 1<<7 | 0b00<<5 | 0b11111)
#define DSB_ISH() EMIT(DSB_gen(0b1011))
#define DSB_ISHLD() EMIT(DSB_gen(0b1001))
#define DSB_ISHST() EMIT(DSB_gen(0b1010))
#define DSB_LD() EMIT(DSB_gen(0b1101))
#define DSB_ST() EMIT(DSB_gen(0b1110))
#define DSB_SY() EMIT(DSB_gen(0b1111))
// Break
@@ -457,6 +518,7 @@ int convert_bitmask(uint64_t bitmask);
#define BR_gen(Z, op, A, M, Rn, Rm) (0b1101011<<25 | (Z)<<24 | (op)<<21 | 0b11111<<16 | (A)<<11 | (M)<<10 | (Rn)<<5 | (Rm))
#define BR(Rn) EMIT(BR_gen(0, 0b00, 0, 0, Rn, 0))
#define BLR(Rn) EMIT(BR_gen(0, 0b01, 0, 0, Rn, 0))
#define RET(Rn) EMIT(BR_gen(0, 0b10, 0, 0, Rn, 0))
#define CB_gen(sf, op, imm19, Rt) ((sf)<<31 | 0b011010<<25 | (op)<<24 | (imm19)<<5 | (Rt))
#define CBNZx(Rt, imm19) EMIT(CB_gen(1, 1, ((imm19)>>2)&0x7FFFF, Rt))
@@ -482,6 +544,10 @@ int convert_bitmask(uint64_t bitmask);
#define BL(imm26) EMIT(BL_gen(((imm26)>>2)&0x3ffffff))
#define NOP EMIT(0b11010101000000110010000000011111)
#define WFE EMIT(0b11010101000000110010000001011111)
#define WFI EMIT(0b11010101000000110010000001111111)
#define YIELD EMIT(0b11010101000000110010000000111111)
#define SEVL EMIT(0b11010101000000110010000010111111)
#define CSINC_gen(sf, Rm, cond, Rn, Rd) ((sf)<<31 | 0b11010100<<21 | (Rm)<<16 | (cond)<<12 | 1<<10 | (Rn)<<5 | (Rd))
#define CSINCx(Rd, Rn, Rm, cond) EMIT(CSINC_gen(1, Rm, cond, Rn, Rd))
@@ -521,9 +587,9 @@ int convert_bitmask(uint64_t bitmask);
#define ANDx_mask(Rd, Rn, N, immr, imms) EMIT(LOGIC_gen(1, 0b00, N, immr, imms, Rn, Rd))
#define ANDw_mask(Rd, Rn, immr, imms) EMIT(LOGIC_gen(0, 0b00, 0, immr, imms, Rn, Rd))
#define ANDxw_mask(Rd, Rn, N, immr, imms) EMIT(LOGIC_gen(rex.w, 0b00, rex.w?(N):0, immr, imms, Rn, Rd))
#define ANDSx_mask(Rd, Rn, N, immr, imms) EMIT(LOGIC_gen(1, 0b11, N, immr, imms, Rn, Rd))
#define ANDSw_mask(Rd, Rn, immr, imms) EMIT(LOGIC_gen(0, 0b11, 0, immr, imms, Rn, Rd))
#define ANDSxw_mask(Rd, Rn, N, immr, imms) EMIT(LOGIC_gen(rex.w, 0b11, rex.w?(N):0, immr, imms, Rn, Rd))
#define ANDSx_mask(Rd, Rn, N, immr, imms) FEMIT(LOGIC_gen(1, 0b11, N, immr, imms, Rn, Rd))
#define ANDSw_mask(Rd, Rn, immr, imms) FEMIT(LOGIC_gen(0, 0b11, 0, immr, imms, Rn, Rd))
#define ANDSxw_mask(Rd, Rn, N, immr, imms) FEMIT(LOGIC_gen(rex.w, 0b11, rex.w?(N):0, immr, imms, Rn, Rd))
#define ORRx_mask(Rd, Rn, N, immr, imms) EMIT(LOGIC_gen(1, 0b01, N, immr, imms, Rn, Rd))
#define ORRw_mask(Rd, Rn, immr, imms) EMIT(LOGIC_gen(0, 0b01, 0, immr, imms, Rn, Rd))
#define ORRxw_mask(Rd, Rn, N, immr, imms) EMIT(LOGIC_gen(rex.w, 0b01, rex.w?(N):0, immr, imms, Rn, Rd))
@@ -539,9 +605,10 @@ int convert_bitmask(uint64_t bitmask);
#define ANDw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b00, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(0, 0b00, 0b01, 0, Rm, lsr, Rn, Rd))
#define ANDxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b00, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDSx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b11, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDSw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b11, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDSxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b11, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDSx_REG(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(1, 0b11, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDSw_REG(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(0, 0b11, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDSxw_REG(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(rex.w, 0b11, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDSw_REG_LSL(Rd, Rn, Rm, lsl) FEMIT(LOGIC_REG_gen(0, 0b11, 0b00, 0, Rm, lsl, Rn, Rd))
#define ORRx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 0, Rm, 0, Rn, Rd))
#define ORRx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
#define ORRw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(0, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
@@ -592,10 +659,10 @@ int convert_bitmask(uint64_t bitmask);
#define BICx(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
#define BICw(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
#define BICw_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(0, 0b00, 0b00, 1, Rm, lsl, Rn, Rd))
#define BICSx(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
#define BICSw(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
#define BICxw(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
#define BICSxw(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
#define BICSx(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(1, 0b11, 0b00, 1, Rm, 0, Rn, Rd))
#define BICSw(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(0, 0b11, 0b00, 1, Rm, 0, Rn, Rd))
#define BICxw(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(rex.w, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
#define BICSxw(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(rex.w, 0b11, 0b00, 1, Rm, 0, Rn, Rd))
#define BICx_REG BICx
#define BICw_REG BICw
#define BICxw_REG BICxw
@@ -771,9 +838,9 @@ int convert_bitmask(uint64_t bitmask);
#define MRS_gen(L, o0, op1, CRn, CRm, op2, Rt) (0b1101010100<<22 | (L)<<21 | 1<<20 | (o0)<<19 | (op1)<<16 | (CRn)<<12 | (CRm)<<8 | (op2)<<5 | (Rt))
// mrs x0, nzcv : 1101010100 1 1 1 011 0100 0010 000 00000 o0=1(op0=3), op1=0b011(3) CRn=0b0100(4) CRm=0b0010(2) op2=0
// MRS : from System register
#define MRS_nzvc(Rt) EMIT(MRS_gen(1, 1, 3, 4, 2, 0, Rt))
#define MRS_nzcv(Rt) EMIT(MRS_gen(1, 1, 3, 4, 2, 0, Rt))
// MSR : to System register
#define MSR_nzvc(Rt) EMIT(MRS_gen(0, 1, 3, 4, 2, 0, Rt))
#define MSR_nzcv(Rt) FEMIT(MRS_gen(0, 1, 3, 4, 2, 0, Rt))
// mrs x0, fpcr : 1101010100 1 1 1 011 0100 0100 000 00000 o0=1(op0=3), op1=0b011(3) CRn=0b0100(4) CRm=0b0100(4) op2=0
#define MRS_fpcr(Rt) EMIT(MRS_gen(1, 1, 3, 4, 4, 0, Rt))
#define MSR_fpcr(Rt) EMIT(MRS_gen(0, 1, 3, 4, 4, 0, Rt))
@@ -782,8 +849,10 @@ int convert_bitmask(uint64_t bitmask);
#define MSR_fpsr(Rt) EMIT(MRS_gen(0, 1, 3, 4, 4, 1, Rt))
// mrs x0, cntvct_el0 op0=0b11 op1=0b011 CRn=0b1110 CRm=0b0000 op2=0b010
#define MRS_cntvct_el0(Rt) EMIT(MRS_gen(1, 1, 0b011, 0b1110, 0b0000, 0b010, Rt))
// mrs x0, cntpctss_el0 op0=0b11 op1=0b011 CRn=0b1110 CRm=0b0000 op2=0b101
// mrs x0, cntpctss_el0 op0=0b11 op1=0b011 CRn=0b1110 CRm=0b0000 op2=0b101
#define MRS_cntpctss_el0(Rt) EMIT(MRS_gen(1, 1, 0b011, 0b1110, 0b0000, 0b101, Rt))
// mrs rt, rndr op0=0b11 op1=0b011 CRn=0b0010 CRm=0b0100 op2=0b000
#define MRS_rndr(Rt) EMIT(MRS_gen(1, 1, 0b011, 0b0010, 0b0100, 0b000, Rt))
// NEON Saturation Bit
#define FPSR_QC 27
// NEON Input Denormal Cumulative
@@ -798,6 +867,14 @@ int convert_bitmask(uint64_t bitmask);
#define FPSR_DZC 1
// NEON Invalid Operation Cumulative
#define FPSR_IOC 0
// NZCV N
#define NZCV_N 31
// NZCV Z
#define NZCV_Z 30
// NZCV C
#define NZCV_C 29
// NZCV V
#define NZCV_V 28
// FCSEL
#define FCSEL_scalar(type, Rm, cond, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | (Rm)<<16 | (cond)<<12 | 0b11<<10 | (Rn)<<5 | (Rd))
@@ -859,18 +936,24 @@ int convert_bitmask(uint64_t bitmask);
#define VMEM_REG_gen(size, opc, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | 0b10<<10 | (Rn)<<5 | (Rt))
#define VLDR32_REG(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b01, Rm, 0b011, 0, Rn, Dt))
#define VLDR32_REG_SXTW(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b01, Rm, 0b110, 0, Rn, Dt))
#define VLDR32_REG_LSL2(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b01, Rm, 0b011, 1, Rn, Dt))
#define VLDR64_REG(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b01, Rm, 0b011, 0, Rn, Dt))
#define VLDR64_REG_SXTW(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b01, Rm, 0b110, 0, Rn, Dt))
#define VLDR64_REG_LSL3(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b01, Rm, 0b011, 1, Rn, Dt))
#define VLDR128_REG(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b11, Rm, 0b011, 0, Rn, Qt))
#define VLDR128_REG_LSL4(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b11, Rm, 0b011, 1, Rn, Qt))
#define VLDR128_REG_SXTW(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b11, Rm, 0b110, 0, Rn, Qt))
#define VSTR32_REG(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b00, Rm, 0b011, 0, Rn, Dt))
#define VSTR32_REG_LSL2(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b00, Rm, 0b011, 1, Rn, Dt))
#define VSTR32_REG_SXTW(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b00, Rm, 0b110, 0, Rn, Dt))
#define VSTR64_REG(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b00, Rm, 0b011, 0, Rn, Dt))
#define VSTR64_REG_LSL3(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b00, Rm, 0b011, 1, Rn, Dt))
#define VSTR64_REG_SXTW(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b00, Rm, 0b110, 0, Rn, Dt))
#define VSTR128_REG(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b10, Rm, 0b011, 0, Rn, Qt))
#define VSTR128_REG_LSL4(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b10, Rm, 0b011, 1, Rn, Qt))
#define VSTR128_REG_SXTW(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b10, Rm, 0b110, 0, Rn, Qt))
#define VLDR_PC_gen(opc, imm19, Rt) ((opc)<<30 | 0b011<<27 | 1<<26 | (imm19)<<5 | (Rt))
#define VLDR32_literal(Vt, imm19) EMIT(VLDR_PC_gen(0b00, ((imm19)>>2)&0x7FFFF, Vt))
@@ -1080,6 +1163,12 @@ int convert_bitmask(uint64_t bitmask);
#define VMOVHto(Wd, Vn, index) EMIT(UMOV_gen(0, ((index)<<2) | 2, Vn, Wd))
#define VMOVSto(Wd, Vn, index) EMIT(UMOV_gen(0, ((index)<<3) | 4, Vn, Wd))
#define SMOV_gen(Q, imm5, Rn, Rd) ((Q)<<30 | 0b01110000<<21 | (imm5)<<16 | 0b01<<13 | 0<<12 | 1<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define SMOVQDto(Xd, Vn, index) EMIT(SMOV_gen(1, ((index)<<4) | 8, Vn, Xd))
#define SMOVQBto(Xd, Vn, index) EMIT(SMOV_gen(1, ((index)<<1) | 1, Vn, Xd))
#define SMOVQHto(Xd, Vn, index) EMIT(SMOV_gen(1, ((index)<<2) | 2, Vn, Xd))
#define SMOVQSto(Xd, Vn, index) EMIT(SMOV_gen(1, ((index)<<3) | 4, Vn, Xd))
#define MVN_vector(Q, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | 0b10000<<17 | 0b00101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define VMVNQ(Rd, Rn) EMIT(MVN_vector(1, Rn, Rd))
@@ -1150,6 +1239,13 @@ int convert_bitmask(uint64_t bitmask);
#define FABSS(Sd, Sn) EMIT(FNEGABS_scalar(0b00, 0b01, Sn, Sd))
#define FABSD(Dd, Dn) EMIT(FNEGABS_scalar(0b01, 0b01, Dn, Dd))
#define FNEGABS_vector(Q, U, sz, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | 1<<23 | (sz)<<22 | 0b10000<<17 | 0b01111<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define VFNEGS(Vd, Vn) EMIT(FNEGABS_vector(0, 1, 0, Vn, Vd))
#define VFNEGQS(Vd, Vn) EMIT(FNEGABS_vector(1, 1, 0, Vn, Vd))
#define VFNEGQD(Vd, Vn) EMIT(FNEGABS_vector(1, 1, 1, Vn, Vd))
#define VFABSS(Vd, Vn) EMIT(FNEGABS_vector(0, 0, 0, Vn, Vd))
#define VFABSQS(Vd, Vn) EMIT(FNEGABS_vector(1, 0, 0, Vn, Vd))
#define VFABSQD(Vd, Vn) EMIT(FNEGABS_vector(1, 0, 1, Vn, Vd))
// MUL
#define FMUL_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11011<<11 | 1<<10 | (Rn)<<5 | (Rd))
@@ -1161,11 +1257,6 @@ int convert_bitmask(uint64_t bitmask);
#define FMULS(Sd, Sn, Sm) EMIT(FMUL_scalar(0b00, Sm, Sn, Sd))
#define FMULD(Dd, Dn, Dm) EMIT(FMUL_scalar(0b01, Dm, Dn, Dd))
#define FMLA_vector(Q, op, sz, Rm, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (op)<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11001<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VFMLAS(Sd, Sn, Sm) EMIT(FMLA_vector(0, 0, 0, Sm, Sn, Sd))
#define VFMLAQS(Sd, Sn, Sm) EMIT(FMLA_vector(1, 0, 0, Sm, Sn, Sd))
#define VFMLAQD(Dd, Dn, Dm) EMIT(FMLA_vector(1, 0, 1, Dm, Dn, Dd))
// DIV
#define FDIV_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11111<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VFDIVS(Sd, Sn, Sm) EMIT(FDIV_vector(0, 0, Sm, Sn, Sd))
@@ -1208,10 +1299,10 @@ int convert_bitmask(uint64_t bitmask);
// CMP
#define FCMP_scalar(type, Rn, Rm, opc) (0b11110<<24 | (type)<<22 | 1<<21 | (Rm)<<16 | 0b1000<<10 | (Rn)<<5 | (opc)<<3)
#define FCMPS(Sn, Sm) EMIT(FCMP_scalar(0b00, Sn, Sm, 0b00))
#define FCMPD(Dn, Dm) EMIT(FCMP_scalar(0b01, Dn, Dm, 0b00))
#define FCMPS_0(Sn) EMIT(FCMP_scalar(0b00, Sn, 0, 0b01))
#define FCMPD_0(Dn) EMIT(FCMP_scalar(0b01, Dn, 0, 0b01))
#define FCMPS(Sn, Sm) FEMIT(FCMP_scalar(0b00, Sn, Sm, 0b00))
#define FCMPD(Dn, Dm) FEMIT(FCMP_scalar(0b01, Dn, Dm, 0b00))
#define FCMPS_0(Sn) FEMIT(FCMP_scalar(0b00, Sn, 0, 0b01))
#define FCMPD_0(Dn) FEMIT(FCMP_scalar(0b01, Dn, 0, 0b01))
// CVT
#define FCVT_scalar(sf, type, rmode, opcode, Rn, Rd) ((sf)<<31 | 0b11110<<24 | (type)<<22 | 1<<21 | (rmode)<<19 | (opcode)<<16 | (Rn)<<5 | (Rd))
@@ -1367,18 +1458,30 @@ int convert_bitmask(uint64_t bitmask);
#define FCVTN(Vd, Vn) EMIT(FCVTN_vector(0, 1, Vn, Vd))
// Convert Vn from 2*Double to higher Vd as 2*float, use FPCR rounding
#define FCVTN2(Vd, Vn) EMIT(FCVTN_vector(1, 1, Vn, Vd))
// Convert Vn from 2*Float to lower Vd as 2*float16 and clears the upper half, use FPCR rounding
#define FCVTN16(Vd, Vn) EMIT(FCVTN_vector(0, 0, Vn, Vd))
// Convert Vn from 2*Float to higher Vd as 2*float16, use FPCR rounding
#define FCVTN162(Vd, Vn) EMIT(FCVTN_vector(1, 0, Vn, Vd))
#define FCVTXN_vector(Q, sz, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 0b10000<<17 | 0b10110<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
// Convert Vn from 2*Double to lower Vd as 2*float and clears the upper half
#define FCVTXN(Vd, Vn) EMIT(FCVTXN_vector(0, 1, Vn, Vd))
// Convert Vn from 2*Double to higher Vd as 2*float
#define FCVTXN2(Vd, Vn) EMIT(FCVTXN_vector(1, 1, Vn, Vd))
// Convert Vn from 2*Float to lower Vd as 2*float16 and clears the upper half
#define FCVTXN16(Vd, Vn) EMIT(FCVTXN_vector(0, 0, Vn, Vd))
// Convert Vn from 2*Float to higher Vd as 2*float16
#define FCVTXN162(Vd, Vn) EMIT(FCVTXN_vector(1, 0, Vn, Vd))
#define FCVTL_vector(Q, sz, Rn, Rd) ((Q)<<30 | 0<<29 | 0b01110<<24 | (sz)<<22 | 0b10000<<17 | 0b10111<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
// Convert lower Vn from 2*float to Vd as 2*double
#define FCVTL(Vd, Vn) EMIT(FCVTL_vector(0, 1, Vn, Vd))
// Convert higher Vn from 2*float to Vd as 2*double
#define FCVTL2(Vd, Vn) EMIT(FCVTL_vector(1, 1, Vn, Vd))
// Convert lower Vn from 2*float16 to Vd as 2*float
#define FCVTL16(Vd, Vn) EMIT(FCVTL_vector(0, 0, Vn, Vd))
// Convert higher Vn from 2*float16 to Vd as 2*float
#define FCVTL162(Vd, Vn) EMIT(FCVTL_vector(1, 0, Vn, Vd))
#define SCVTF_scalar(sf, type, rmode, opcode, Rn, Rd) ((sf)<<31 | 0b11110<<24 | (type)<<22 | 1<<21 | (rmode)<<19 | (opcode)<<16 | (Rn)<<5 | (Rd))
#define SCVTFSw(Sd, Wn) EMIT(SCVTF_scalar(0, 0b00, 0b00, 0b010, Wn, Sd))
@@ -1450,6 +1553,37 @@ int convert_bitmask(uint64_t bitmask);
// FMAXNM NaN vs Number: number is picked
#define FMAXNMD(Dd, Dn, Dm) EMIT(FMINMAX_scalar(0b01, Dm, 0b10, Dn, Dd))
// Fused Add Multiply
#define FMADD_gen(type, o1, Rm, o0, Ra, Rn, Rd) (0b11111<<24 | (type)<<22 | (o1)<<21 | (Rm)<<16 | (o0)<<15 | (Ra)<<10 | (Rn)<<5 | (Rd))
// scalar Rd = Ra + Rn*Rm
#define FMADD_32(Sd, Sa, Sn, Sm) EMIT(FMADD_gen(0b00, 0, Sm, 0, Sa, Sn, Sd))
// scalar Rd = Ra + Rn*Rm
#define FMADD_64(Dd, Da, Dn, Dm) EMIT(FMADD_gen(0b01, 0, Dm, 0, Da, Dn, Dd))
// scalar Rd = -Ra - Rn*Rm
#define FNMADD_32(Sd, Sa, Sn, Sm) EMIT(FMADD_gen(0b00, 1, Sm, 0, Sa, Sn, Sd))
// scalar Rd = -Ra - Rn*Rm
#define FNMADD_64(Dd, Da, Dn, Dm) EMIT(FMADD_gen(0b01, 1, Dm, 0, Da, Dn, Dd))
// scalar Rd = Ra - Rn*Rm
#define FMSUB_32(Sd, Sa, Sn, Sm) EMIT(FMADD_gen(0b00, 0, Sm, 1, Sa, Sn, Sd))
// scalar Rd = Ra - Rn*Rm
#define FMSUB_64(Dd, Da, Dn, Dm) EMIT(FMADD_gen(0b01, 0, Dm, 1, Da, Dn, Dd))
// scalar Rd = -Ra + Rn*Rm
#define FNMSUB_32(Sd, Sa, Sn, Sm) EMIT(FMADD_gen(0b00, 1, Sm, 1, Sa, Sn, Sd))
// scalar Rd = -Ra + Rn*Rm
#define FNMSUB_64(Dd, Da, Dn, Dm) EMIT(FMADD_gen(0b01, 1, Dm, 1, Da, Dn, Dd))
#define FMLA_vector(Q, op, sz, Rm, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (op)<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11001<<11 | 1<<10 | (Rn)<<5 | (Rd))
// Vd += Vn*Vm
#define VFMLAS(Vd, Vn, Vm) EMIT(FMLA_vector(0, 0, 0, Vm, Vn, Vd))
// Vd += Vn*Vm
#define VFMLAQS(Vd, Vn, Vm) EMIT(FMLA_vector(1, 0, 0, Vm, Vn, Vd))
// Vd += Vn*Vm
#define VFMLAQD(Vd, Vn, Vm) EMIT(FMLA_vector(1, 0, 1, Vm, Vn, Vd))
// Vd -= Vn*Vm
#define VFMLSQS(Vd, Vn, Vm) EMIT(FMLA_vector(1, 1, 0, Vm, Vn, Vd))
// Vd -= Vn*Vm
#define VFMLSQD(Vd, Vn, Vm) EMIT(FMLA_vector(1, 1, 1, Vm, Vn, Vd))
// ZIP / UZP
#define ZIP_gen(Q, size, Rm, op, Rn, Rd) ((Q)<<30 | 0b001110<<24 | (size)<<22 | (Rm)<<16 | (op)<<14 | 0b11<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define VZIP1Q_8(Rt, Rn, Rm) EMIT(ZIP_gen(1, 0b00, Rm, 0, Rn, Rt))
@@ -1483,6 +1617,16 @@ int convert_bitmask(uint64_t bitmask);
#define VUZP1Q_64(Rt, Rn, Rm) EMIT(UZP_gen(1, 0b11, Rm, 0, Rn, Rt))
#define VUZP2Q_64(Rt, Rn, Rm) EMIT(UZP_gen(1, 0b11, Rm, 1, Rn, Rt))
#define BITBIF_gen(Q, opc2, Rm, Rn, Rd) ((Q)<<30 | 0b101110<<24 | (opc2)<<22 | 1<<21 | (Rm)<<16 | 0b000111<<10 | (Rn)<<5 | (Rd))
// Bitwise insert Vn in Vd if Vm is "0"
#define VBIF(Vd, Vn,Vm) EMIT(BITBIF_gen(0, 0b11, Vm, Vn, Vd))
// Bitwise insert Vn in Vd if Vm is "0"
#define VBIFQ(Vd, Vn,Vm) EMIT(BITBIF_gen(1, 0b11, Vm, Vn, Vd))
// Bitwise insert Vn in Vd if Vm is "1"
#define VBIT(Vd, Vn,Vm) EMIT(BITBIF_gen(0, 0b10, Vm, Vn, Vd))
// Bitwise insert Vn in Vd if Vm is "1"
#define VBITQ(Vd, Vn,Vm) EMIT(BITBIF_gen(1, 0b10, Vm, Vn, Vd))
#define DUP_element(Q, imm5, Rn, Rd) ((Q)<<30 | 0b01110000<<21 | (imm5)<<16 | 1<<10 | (Rn)<<5 | (Rd))
#define VDUP_8(Vd, Vn, idx) EMIT(DUP_element(0, ((idx)<<1|1), Vn, Vd))
#define VDUPQ_8(Vd, Vn, idx) EMIT(DUP_element(1, ((idx)<<1|1), Vn, Vd))
@@ -1627,8 +1771,8 @@ int convert_bitmask(uint64_t bitmask);
#define VCHIQQ_64(Rd, Rn, Rm) EMIT(CMG_vector(1, 1, 0b11, 0, Rm, Rn, Rd))
// Less Than 0
#define CMLT_0_vector(Q, size, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b01010<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define CMLT_0_8(Rd, Rn) EMIT(CMLT_0_vector(0, 0b00, Rn, Rd))
#define CMLT_0_vector(Q, size, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b01010<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define CMLT_0_8(Rd, Rn) EMIT(CMLT_0_vector(0, 0b00, Rn, Rd))
#define CMLT_0_16(Rd, Rn) EMIT(CMLT_0_vector(0, 0b01, Rn, Rd))
#define CMLT_0_32(Rd, Rn) EMIT(CMLT_0_vector(0, 0b10, Rn, Rd))
#define CMLTQ_0_8(Rd, Rn) EMIT(CMLT_0_vector(1, 0b00, Rn, Rd))
@@ -1812,8 +1956,12 @@ int convert_bitmask(uint64_t bitmask);
#define MOVI_vector(Q, op, abc, cmode, defgh, Rd) ((Q)<<30 | (op)<<29 | 0b0111100000<<19 | (abc)<<16 | (cmode)<<12 | 1<<10 | (defgh)<<5 | (Rd))
#define MOVIQ_8(Rd, imm8) EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
#define MOVIQ_16(Rd, imm8, lsl8) EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), 0b1000|((lsl8)?0b10:0), ((imm8)&0b11111), Rd))
#define MOVIQ_32(Rd, imm8) EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), 0b0000, ((imm8)&0b11111), Rd))
#define MOVIQ_32_lsl(Rd, imm8, lsl8) EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), (lsl8<<1), ((imm8)&0b11111), Rd))
#define MOVIQ_64(Rd, imm8) EMIT(MOVI_vector(1, 1, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
#define MOVI_8(Rd, imm8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
#define MOVI_16(Rd, imm8, lsl8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b1000|((lsl8)?0b10:0), ((imm8)&0b11111), Rd))
#define MOVI_32_lsl(Rd, imm8, lsl8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), (lsl8<<1), ((imm8)&0b11111), Rd))
#define MOVI_32(Rd, imm8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b0000, ((imm8)&0b11111), Rd))
#define MOVI_64(Rd, imm8) EMIT(MOVI_vector(0, 1, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
@@ -1915,6 +2063,33 @@ int convert_bitmask(uint64_t bitmask);
#define UMINQ_32(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b10, Vm, 1, Vn, Vd))
//#define UMINQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b11, Vm, 1, Vn, Vd))
// MIN or MAX accros vector
#define MAXMINV_vector(Q, U, size, op, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b11000<<17 | (op)<<16 | 0b1010<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define SMAXV_8(Vd, Vn) EMIT(MAXMINV_vector(0, 0, 0b00, 0, Vn, Vd))
#define SMINV_8(Vd, Vn) EMIT(MAXMINV_vector(0, 0, 0b00, 1, Vn, Vd))
#define UMAXV_8(Vd, Vn) EMIT(MAXMINV_vector(0, 1, 0b00, 0, Vn, Vd))
#define UMINV_8(Vd, Vn) EMIT(MAXMINV_vector(0, 1, 0b00, 1, Vn, Vd))
#define SMAXV_16(Vd, Vn) EMIT(MAXMINV_vector(0, 0, 0b01, 0, Vn, Vd))
#define SMINV_16(Vd, Vn) EMIT(MAXMINV_vector(0, 0, 0b01, 1, Vn, Vd))
#define UMAXV_16(Vd, Vn) EMIT(MAXMINV_vector(0, 1, 0b01, 0, Vn, Vd))
#define UMINV_16(Vd, Vn) EMIT(MAXMINV_vector(0, 1, 0b01, 1, Vn, Vd))
#define SMAXV_32(Vd, Vn) EMIT(MAXMINV_vector(0, 0, 0b10, 0, Vn, Vd))
#define SMINV_32(Vd, Vn) EMIT(MAXMINV_vector(0, 0, 0b10, 1, Vn, Vd))
#define UMAXV_32(Vd, Vn) EMIT(MAXMINV_vector(0, 1, 0b10, 0, Vn, Vd))
#define UMINV_32(Vd, Vn) EMIT(MAXMINV_vector(0, 1, 0b10, 1, Vn, Vd))
#define SMAXVQ_8(Vd, Vn) EMIT(MAXMINV_vector(1, 0, 0b00, 0, Vn, Vd))
#define SMINVQ_8(Vd, Vn) EMIT(MAXMINV_vector(1, 0, 0b00, 1, Vn, Vd))
#define UMAXVQ_8(Vd, Vn) EMIT(MAXMINV_vector(1, 1, 0b00, 0, Vn, Vd))
#define UMINVQ_8(Vd, Vn) EMIT(MAXMINV_vector(1, 1, 0b00, 1, Vn, Vd))
#define SMAXVQ_16(Vd, Vn) EMIT(MAXMINV_vector(1, 0, 0b01, 0, Vn, Vd))
#define SMINVQ_16(Vd, Vn) EMIT(MAXMINV_vector(1, 0, 0b01, 1, Vn, Vd))
#define UMAXVQ_16(Vd, Vn) EMIT(MAXMINV_vector(1, 1, 0b01, 0, Vn, Vd))
#define UMINVQ_16(Vd, Vn) EMIT(MAXMINV_vector(1, 1, 0b01, 1, Vn, Vd))
#define SMAXVQ_32(Vd, Vn) EMIT(MAXMINV_vector(1, 0, 0b10, 0, Vn, Vd))
#define SMINVQ_32(Vd, Vn) EMIT(MAXMINV_vector(1, 0, 0b10, 1, Vn, Vd))
#define UMAXVQ_32(Vd, Vn) EMIT(MAXMINV_vector(1, 1, 0b10, 0, Vn, Vd))
#define UMINVQ_32(Vd, Vn) EMIT(MAXMINV_vector(1, 1, 0b10, 1, Vn, Vd))
// HADD vector
#define HADD_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 1<<10 | (Rn)<<5 | (Rd))
#define SHADD_8(Vd, Vn, Vm) EMIT(HADD_vector(0, 0, 0b00, Vm, Vn, Vd))
@@ -2053,7 +2228,7 @@ int convert_bitmask(uint64_t bitmask);
#define LDSETLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b011, Rn, Rt))
#define STSETH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b011, Rn, 0b11111))
#define STSETLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b011, Rn, 0b11111))
// Atomic Signel Max
// Atomic Signed Max
#define LDSMAXxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b100, Rn, Rt))
#define LDSMAXAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b100, Rn, Rt))
#define LDSMAXALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b100, Rn, Rt))
@@ -2169,23 +2344,23 @@ int convert_bitmask(uint64_t bitmask);
// FLAGM extension
// Invert Carry Flag
#define CFINV() EMIT(0b1101010100<<22 | 0b0100<<12 | 0b000<<5 | 0b11111)
#define CFINV() FEMIT(0b1101010100<<22 | 0b0100<<12 | 0b000<<5 | 0b11111)
#define RMIF_gen(imm6, Rn, mask) (0b10111010000<<21 | (imm6)<<15 | 0b00001<<10 | (Rn)<<5 | (mask))
// Rotate right reg and use as NZCV
#define RMIF(Xn, shift, mask) EMIT(RMIF_gen(shift, Xn, mask))
#define RMIF(Xn, shift, mask) FEMIT(RMIF_gen(shift, Xn, mask))
#define SETF_gen(sz, Rn) (0b00111010000<<21 | (sz)<<14 | 0b0010<<10 | (Rn)<<5 | 0b1101)
// Set NZVc with 8bit value of reg: N=bit7, Z=[0..7]==0, V=bit8 eor bit7, C unchanged
#define SETF8(Wn) EMIT(SETF_gen(0, Wn))
#define SETF8(Wn) FEMIT(SETF_gen(0, Wn))
// Set NZVc with 16bit value of reg: N=bit15, Z=[0..15]==0, V=bit16 eor bit15, C unchanged
#define SETF16(Wn) EMIT(SETF_gen(1, Wn))
#define SETF16(Wn) FEMIT(SETF_gen(1, Wn))
// FLAGM2 extension
// NZCV -> N=0 Z=C|V C=C&!V V=0
#define AXFLAG() EMIT(0b1101010100<<22 | 0b0100<<12 | 0b010<<5 | 0b11111)
#define AXFLAG() FEMIT(0b1101010100<<22 | 0b0100<<12 | 0b010<<5 | 0b11111)
// NZCV -> N=!C&!Z Z=Z&C C=C|Z V=!C&Z
#define XAFLAG() EMIT(0b1101010100<<22 | 0b0100<<12 | 0b001<<5 | 0b11111)
#define XAFLAG() FEMIT(0b1101010100<<22 | 0b0100<<12 | 0b001<<5 | 0b11111)
// FRINTTS extension
#define FRINTxx_scalar(type, op, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b0100<<17 | (op)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
+73 -71
View File
@@ -5,82 +5,84 @@
// Returns the packed valid-N-imms-immr (1-1-6-6 bits); returns 0 if bitmask is not encodable
int convert_bitmask(uint64_t bitmask) {
if (!bitmask || !~bitmask) return 0;
uint64_t size, mask, pat;
for (size = 6; size > 1; --size) {
mask = (one << (1 << (size - 1))) - 1;
pat = bitmask & mask;
// printf("%016lX/%lu: %016lX %016lX %2d\n", bitmask, size, mask, pat, (1 << (size - 1)));
if (pat != ((bitmask >> (1 << (size - 1))) & mask)) {
// printf("%016lX/%lu: %016lX %016lX xx\n", bitmask, size, pat, (bitmask >> (1 << (size - 1))) & mask);
break;
}
}
mask = (size >= 6) ? ((uint64_t)-1) : ((one << (1 << size)) - 1);
pat = bitmask & mask;
for (uint64_t i = 1; i < 7 - size; ++i) {
uint64_t boff = i * (1 << size);
if (((bitmask >> boff) & mask) != pat) {
// printf("%016lX/%lu: no %lu %lu %016lX %016lX %016lX\n", bitmask, size, i, size, boff, mask, pat);
return 0;
}
}
// Note that here, pat != 0 and ~pat & (1 << size) != 0 (otherwise size = 1 and bitmask = all 0 or all 1)
int immr = 0;
uint64_t last_bit = one << ((1 << size) - 1);
// printf("%016lX/%lu: %016lX %016lX %lu\n", bitmask, size, mask, pat, last_bit);
if (pat & 1) {
while (pat & last_bit) {
pat = ((pat - last_bit) << 1) + 1;
++immr;
}
} else {
immr = 1 << size;
while (!(pat & 1)) {
pat >>= 1;
--immr;
}
}
// printf("%016lX/%lu: %016lX %016lX %lu %d\n", bitmask, size, mask, pat, last_bit, immr);
if (pat & (pat + 1)) return 0; // Not 0...01...1
int to = 1;
while (pat & (one << to)) ++to;
// printf("%016lX/%lu: returning %c%c%02lX%02lX\n", bitmask, size, '2' + (size == 6), (uint64_t)(((0x1E << size) & 0x3F) + (to - 1)), (uint64_t)immr);
return 0x2000 + ((size == 6) << 12) + ((((0x1E << size) & 0x3F) + (to - 1)) << 6) + immr;
if (bitmask == 0 || bitmask == ~0ULL) return 0;
uint64_t size, mask, pat;
for (size = 6; size > 1; --size) {
mask = (one << (1 << (size - 1))) - 1;
pat = bitmask & mask;
if (pat != ((bitmask >> (1 << (size - 1))) & mask)) {
break;
}
}
mask = (size >= 6) ? ~0ULL : ((one << (1 << size)) - 1);
pat = bitmask & mask;
for (uint64_t i = 1; i < 7 - size; ++i) {
uint64_t boff = i * (1 << size);
if (((bitmask >> boff) & mask) != pat) {
return 0;
}
}
int immr = 0;
uint64_t last_bit = one << ((1 << size) - 1);
if (pat & 1) {
while (pat & last_bit) {
pat = ((pat - last_bit) << 1) | 1;
++immr;
}
} else {
immr = 1 << size;
while (!(pat & 1)) {
pat >>= 1;
--immr;
}
}
if (pat & (pat + 1)) return 0;
int to = 1;
while (pat & (one << to)) ++to;
return 0x2000 + ((size == 6) << 12) + ((((0x1E << size) & 0x3F) + (to - 1)) << 6) + immr;
}
#if 0
#include <unordered_set>
int main() {
std::unordered_set<uint64_t> okvals;
uint64_t val;
for (int n = 1; n < 7; ++n) {
int imms0 = ((n == 6) ? 0xC0 : 0x80) + ((0x1E << n) & 0x3F);
for (int nones = 0; nones < (1 << n) - 1; ++nones) {
val = (one << (nones + 1)) - 1;
for (int j = 0; j < 6 - n; ++j) {
val = val + (val << (1 << (n + j)));
}
for (int immr = 0; immr < (1 << n); ++immr) {
int exp = ((imms0 + nones) << 6) + immr;
int got = convert_bitmask(val);
if (exp != got) {
printf("0x%016lX: expected %04X, got %04X\n", val, exp, got);
}
okvals.emplace(val);
val = (val >> 1) + ((val & 1) << 63);
}
}
}
std::unordered_set<uint64_t> okvals;
uint64_t val;
for (int n = 1; n < 7; ++n) {
int imms0 = ((n == 6) ? 0xC0 : 0x80) + ((0x1E << n) & 0x3F);
for (int nones = 0; nones < (1 << n) - 1; ++nones) {
val = (one << (nones + 1)) - 1;
for (int j = 0; j < 6 - n; ++j) {
val += val << (1 << (n + j));
}
for (int immr = 0; immr < (1 << n); ++immr) {
int exp = ((imms0 + nones) << 6) + immr;
int got = convert_bitmask(val);
if (exp != got) {
printf("0x%016lX: expected %04X, got %04X\n", val, exp, got);
}
okvals.emplace(val);
val = (val >> 1) | ((val & 1) << 63);
}
}
}
#pragma omp parallel for
for (uint64_t i = 1; i < 0xFFFFFFFFFFFFFFFFu; ++i) {
int got = convert_bitmask(val);
if (!!got != (okvals.find(val) != okvals.cend())) {
printf("0x%016lX: expected %s, got %04X\n", val, (!!got ? "0000" : "non0"), got);
}
}
for (uint64_t i = 1; i < 0xFFFFFFFFFFFFFFFFu; ++i) {
int got = convert_bitmask(i);
if (!!got != (okvals.find(i) != okvals.cend())) {
printf("0x%016lX: expected %s, got %04X\n", i, (!!got ? "non0" : "0000"), got);
}
}
}
#endif
+83 -4
View File
@@ -124,6 +124,22 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "NOP");
return buff;
}
if(isMask(opcode, "11010101000000110010000001011111", &a)) {
snprintf(buff, sizeof(buff), "WFE");
return buff;
}
if(isMask(opcode, "11010101000000110010000001111111", &a)) {
snprintf(buff, sizeof(buff), "WFI");
return buff;
}
if(isMask(opcode, "11010101000000110010000000111111", &a)) {
snprintf(buff, sizeof(buff), "YIELD");
return buff;
}
if(isMask(opcode, "11010101000000110010000010111111", &a)) {
snprintf(buff, sizeof(buff), "SEVL");
return buff;
}
// --- LDR / STR
if(isMask(opcode, "f010100011iiiiiii22222nnnnnttttt", &a)) {
int offset = signExtend(imm, 7)<<(2+sf);
@@ -573,6 +589,14 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "BIC %s, %s, %s, %s %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], shifts[shift], imm);
return buff;
}
if(isMask(opcode, "f1101010hh1mmmmmiiiiiinnnnnddddd", &a)) {
const char* shifts[] = { "LSL", "LSR", "ASR", "ROR" };
if(shift==0 && imm==0)
snprintf(buff, sizeof(buff), "BICS %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm]);
else
snprintf(buff, sizeof(buff), "BICS %s, %s, %s, %s %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], shifts[shift], imm);
return buff;
}
if(isMask(opcode, "f01100100Nrrrrrrssssssnnnnnddddd", &a)) {
uint64_t i = DecodeBitMasks(a.N, imms, immr);
if(!sf) i&=0xffffffff;
@@ -916,7 +940,6 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
}
// UMOV
if(isMask(opcode, "0Q001110000rrrrr001111nnnnnddddd", &a)) {
char q = a.Q?'Q':'D';
char s = '?';
int sz=0;
if(a.Q==0 && immr&1) {s='B'; sz=0; }
@@ -925,9 +948,24 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
else if(a.Q==1 && (immr&15)==8) {s='D'; sz=3; }
int index = (immr)>>(sz+1);
if(sz>2)
snprintf(buff, sizeof(buff), "MOV %s, %c%d.%c[%d]", a.Q?Xt[Rd]:Wt[Rd], q, Rn, s, index);
snprintf(buff, sizeof(buff), "MOV %s, V%d.%c[%d]", a.Q?Xt[Rd]:Wt[Rd], Rn, s, index);
else
snprintf(buff, sizeof(buff), "UMOV %s, %c%d.%c[%d]", a.Q?Xt[Rd]:Wt[Rd], q, Rn, s, index);
snprintf(buff, sizeof(buff), "UMOV %s, V%d.%c[%d]", a.Q?Xt[Rd]:Wt[Rd], Rn, s, index);
return buff;
}
// SMOV
if(isMask(opcode, "0Q001110000rrrrr001011nnnnnddddd", &a)) {
char s = '?';
int sz=0;
if(a.Q==0 && immr&1) {s='B'; sz=0; }
else if(/*a.Q==0 &&*/ (immr&3)==2) {s='H'; sz=1; }
else if(/*a.Q==0 &&*/ (immr&7)==4) {s='S'; sz=2; }
else if(a.Q==1 && (immr&15)==8) {s='D'; sz=3; }
int index = (immr)>>(sz+1);
if(sz>2)
snprintf(buff, sizeof(buff), "MOV %s, V%d.%c[%d]", a.Q?Xt[Rd]:Wt[Rd], Rn, s, index);
else
snprintf(buff, sizeof(buff), "SMOV %s, V%d.%c[%d]", a.Q?Xt[Rd]:Wt[Rd], Rn, s, index);
return buff;
}
// VEOR
@@ -952,6 +990,12 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "VMUL V%d.%s, V%d.%s, V%d.%s", Rd, Vd, Rn, Vd, Rm, Vd);
return buff;
}
// VBIT / VBIF
if(isMask(opcode, "0Q1011101o1mmmmm000111nnnnnddddd", &a)) {
char q = a.Q?'Q':'D';
snprintf(buff, sizeof(buff), "VBI%c %c%d, %c%d, %c%d", a.o?'F':'T', q, Rd, q, Rn, q, Rm);
return buff;
}
// CMP
if(isMask(opcode, "0Q101110ff1mmmmm100011nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
@@ -1007,6 +1051,19 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "MOVI V%d.%s, #0x%x", Rd, Vd, imm<<8);
return buff;
}
// MOV immediate 64bits
if(isMask(opcode, "0Q10111100000iii111001iiiiiddddd", &a)) {
uint64_t tmp64u = 0;
for(int i=0; i<8; ++i)
if((imm)&(1<<i))
tmp64u |= 0xffLL<<(i*8);
if(a.Q)
snprintf(buff, sizeof(buff), "MOVI V%d.2D, #0x%016lx", Rd, tmp64u);
else
snprintf(buff, sizeof(buff), "MOVI D%d, #0x%016lx", Rd, tmp64u);
return buff;
}
// Shift
if(isMask(opcode, "0QU011110hhhhrrr000001nnnnnddddd", &a)) {
@@ -1297,6 +1354,28 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "F%s%s V%d.%d%c, V%d.%d%c, V%d.%d%c", option?"MIN":"MAX", a.Q?"Q":"", Rd, n, s, Rn, n, s, Rm, n, s);
return buff;
}
// FMADD
if(isMask(opcode, "00011111tt0mmmmmoaaaaannnnnddddd", &a)) {
char s = (a.t==0b00)?'S':((a.t==0b01)?'D':'?');
int n = (a.t==0)?1:2;
snprintf(buff, sizeof(buff), "FM%s V%d.%d%c, V%d.%d%c, V%d.%d%c, V%d.%d%c", option?"SUB":"ADD", Rd, n, s, Ra, n, s, Rn, n, s, Rm, n, s);
return buff;
}
// FNMADD
if(isMask(opcode, "00011111tt1mmmmmoaaaaannnnnddddd", &a)) {
char s = (a.t==0b00)?'S':((a.t==0b01)?'D':'?');
int n = (a.t==0)?1:2;
snprintf(buff, sizeof(buff), "FNM%s V%d.%d%c, V%d.%d%c, V%d.%d%c, V%d.%d%c", option?"SUB":"ADD", Rd, n, s, Ra, n, s, Rn, n, s, Rm, n, s);
return buff;
}
// FMLA
if(isMask(opcode, "0Q001110of1mmmmm110011nnnnnddddd", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
int n = (sf==0)?2:1;
n *= a.Q?2:1;
snprintf(buff, sizeof(buff), "FML%s%s V%d.%d%c, V%d.%d%c, V%d.%d%c", option?"S":"A", a.Q?"Q":"", Rd, n, s, Rn, n, s, Rm, n, s);
return buff;
}
// NEG
if(isMask(opcode, "0Q101110ff100000101110nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
@@ -1596,7 +1675,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
if((imm&0b0001)==0b0001) sz=0;
else if((imm&0b0011)==0b0010) sz=1;
else if((imm&0b0111)==0b0100) sz=2;
int sh=imm - (1<<sz);
int sh=(imm>>sz) - 1;
const char* Vd = Y[(sz<<1)|a.Q];
const char* Vn = Z[sz];
snprintf(buff, sizeof(buff), "DUP V%d.%s, V%d.%s[%d]", Rd, Vd, Rn, Vn, sh);
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+177 -100
View File
@@ -13,13 +13,14 @@
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "emu/x87emu_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "custommem.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -77,9 +78,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x05:
INST_NAME("ADD AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
i16 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
MOV32w(x2, i16);
emit_add16(dyn, ninst, x1, x2, x3, x4);
BFIz(xRAX, x1, 0, 16);
break;
@@ -101,7 +102,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_or16(dyn, ninst, x1, x2, x4, x2);
emit_or16(dyn, ninst, x1, x2, x4, x5);
EWBACK;
break;
case 0x0B:
@@ -116,10 +117,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x0D:
INST_NAME("OR AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
i16 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_or16(dyn, ninst, x1, x2, x3, x4);
emit_or16c(dyn, ninst, x1, i16, x3, x4);
BFIz(xRAX, x1, 0, 16);
break;
@@ -154,9 +154,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("ADC AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
u16 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
MOV32w(x2, u16);
emit_adc16(dyn, ninst, x1, x2, x3, x4);
BFIz(xRAX, x1, 0, 16);
break;
@@ -224,10 +224,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x25:
INST_NAME("AND AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
i16 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_and16(dyn, ninst, x1, x2, x3, x4);
emit_and16c(dyn, ninst, x1, i16, x3, x4);
BFIz(xRAX, x1, 0, 16);
break;
@@ -252,9 +251,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x2D:
INST_NAME("SUB AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
i16 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
MOV32w(x2, i16);
emit_sub16(dyn, ninst, x1, x2, x3, x4);
BFIz(xRAX, x1, 0, 16);
break;
@@ -280,10 +279,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x35:
INST_NAME("XOR AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
i16 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_xor16(dyn, ninst, x1, x2, x3, x4);
emit_xor16c(dyn, ninst, x1, i16, x3, x4);
BFIz(xRAX, x1, 0, 16);
break;
@@ -306,10 +304,10 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x3D:
INST_NAME("CMP AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
u16 = F16;
UXTHw(x1, xRAX);
if(i32) {
MOV32w(x2, i32);
if(u16) {
MOV32w(x2, u16);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
} else {
emit_cmp16_0(dyn, ninst, x1, x3, x4);
@@ -325,11 +323,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x46:
case 0x47:
INST_NAME("INC Reg16 (32bits)");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
gd = xRAX + (opcode&7);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
gd = TO_NAT (opcode&7);
UXTHw(x1, gd);
emit_inc16(dyn, ninst, x1, x2, x3);
BFIw(gd, x1, 0, 16);
BFIz(gd, x1, 0, 16);
break;
case 0x48:
case 0x49:
@@ -340,11 +338,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x4E:
case 0x4F:
INST_NAME("DEC Reg16 (32bits)");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
gd = xRAX + (opcode&7);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
gd = TO_NAT (opcode&7);
UXTHw(x1, gd);
emit_dec16(dyn, ninst, x1, x2, x3);
BFIw(gd, x1, 0, 16);
BFIz(gd, x1, 0, 16);
break;
case 0x50:
case 0x51:
@@ -355,7 +353,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x56:
case 0x57:
INST_NAME("PUSH reg");
gd = xRAX+(opcode&0x07)+(rex.b<<3);
gd = TO_NAT((opcode & 0x07) + (rex.b << 3));
if (gd==xRSP) {
MOVw_REG(x1, xRSP);
PUSH1_16(x1);
@@ -372,9 +370,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x5E:
case 0x5F:
INST_NAME("POP reg");
gd = xRAX+(opcode&0x07)+(rex.b<<3);
gd = TO_NAT((opcode & 0x07) + (rex.b << 3));
POP1_16(x1);
BFIw(gd, x1, 0, 16);
BFIz(gd, x1, 0, 16);
break;
case 0x60:
if(rex.is32bits) {
@@ -396,20 +394,20 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(rex.is32bits) {
INST_NAME("POPA 16bits (32bits)");
POP1_16(x1);
BFIw(xRDI, x1, 0, 16);
BFIz(xRDI, x1, 0, 16);
POP1_16(x1);
BFIw(xRSI, x1, 0, 16);
BFIz(xRSI, x1, 0, 16);
POP1_16(x1);
BFIw(xRBP, x1, 0, 16);
BFIz(xRBP, x1, 0, 16);
POP1_16(x1); // RSP ignored
POP1_16(x1);
BFIw(xRBX, x1, 0, 16);
BFIz(xRBX, x1, 0, 16);
POP1_16(x1);
BFIw(xRDX, x1, 0, 16);
BFIz(xRDX, x1, 0, 16);
POP1_16(x1);
BFIw(xRCX, x1, 0, 16);
BFIz(xRCX, x1, 0, 16);
POP1_16(x1);
BFIw(xRAX, x1, 0, 16);
BFIz(xRAX, x1, 0, 16);
} else {
DEFAULT;
}
@@ -449,6 +447,12 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GWBACK;
UFLAG_DF(x1, d_imul16);
break;
case 0x6A:
INST_NAME("PUSH Ib");
u16 = (uint16_t)F8S;
MOV32w(x2, u16);
PUSH1_16(x2);
break;
case 0x70:
case 0x71:
@@ -487,8 +491,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_or16(dyn, ninst, x1, x5, x2, x4);
emit_or16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 2: //ADC
@@ -497,7 +500,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
MOVZw(x5, (uint16_t)i16);
emit_adc16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -507,7 +510,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
MOVZw(x5, (uint16_t)i16);
emit_sbb16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -516,8 +519,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_and16(dyn, ninst, x1, x5, x2, x4);
emit_and16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 5: //SUB
@@ -534,8 +536,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_xor16(dyn, ninst, x1, x5, x2, x4);
emit_xor16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 7: //CMP
@@ -574,8 +575,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETGD;
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(!ALIGNED_ATOMICH) {
TSTx_mask(ed, 1, 0, 0); // mask=1
B_MARK(cNE);
TBNZ_MARK(ed, 0);
}
if(arm64_atomics) {
SWPALH(gd, x1, ed);
@@ -612,7 +612,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGD; // don't need GETGW here
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if(ed!=gd) {
BFIz(ed, gd, 0, 16);
}
@@ -627,7 +627,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGD; // don't need GETGW neither
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if(ed!=gd) {
BFIz(gd, ed, 0, 16);
}
@@ -644,7 +644,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
u8 = (nextop&0x38)>>3;
LDRH_U12(x3, xEmu, offsetof(x64emu_t, segs[u8]));
if((nextop&0xC0)==0xC0) { // reg <= seg
BFIz(xRAX+(nextop&7)+(rex.b<<3), x3, 0, 16);
BFIz(TO_NAT((nextop & 7) + (rex.b << 3)), x3, 0, 16);
} else { // mem <= seg
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
STH(x3, wback, fixedaddress);
@@ -657,7 +657,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
u8 = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
@@ -672,7 +672,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
POP1_16(x1);
if((nextop&0xC0)==0xC0) {
wback = xRAX+(nextop&7)+(rex.b<<3);
wback = TO_NAT((nextop & 7) + (rex.b << 3));
BFIz(wback, x1, 0, 16);
} else {
SMREAD();
@@ -688,7 +688,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x95:
case 0x96:
case 0x97:
gd = xRAX+(opcode&0x07)+(rex.b<<3);
gd = TO_NAT((opcode & 0x07) + (rex.b << 3));
if(gd==xRAX) {
INST_NAME("NOP");
} else {
@@ -705,13 +705,12 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x99:
INST_NAME("CWD");
SXTHw(x1, xRAX);
BFXILx(xRDX, x1, 16, 16);
SXTHw(x1, xRAX); // sign extend ax to x1
BFXILx(xRDX, x1, 16, 16); // insert high 16bits of x1 as low DX
break;
case 0x9C:
INST_NAME("PUSHF");
READFLAGS(X_ALL);
WILLWRITE();
PUSH1_16(xFlags);
SMWRITE();
break;
@@ -727,7 +726,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SET_DFNONE(x1);
if(box64_wine) { // should this be done all the time?
TBZ_NEXT(xFlags, F_TF);
// go to epilog, TF should trigger at end of next opcode, so using Interpretor only
// go to epilog, TF should trigger at end of next opcode, so using Interpreter only
jump_to_epilog(dyn, addr, 0, ninst);
}
break;
@@ -752,12 +751,38 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
else
u64 = F64;
MOV64z(x1, u64);
if(isLockAddress(u64)) lock=1; else lock = 0;
WILLWRITELOCK(lock);
lock = isLockAddress(u64);
STRH_U12(xRAX, x1, 0);
SMWRITELOCK(lock);
break;
case 0xA4:
SMREAD();
if(rep) {
INST_NAME("REP MOVSB");
CBZx_NEXT(xRCX);
TBNZ_MARK2(xFlags, F_DF);
MARK; // Part with DF==0
LDRB_S9_postindex(x1, xRSI, 1);
STRB_S9_postindex(x1, xRDI, 1);
SUBx_U12(xRCX, xRCX, 1);
CBNZx_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
LDRB_S9_postindex(x1, xRSI, -1);
STRB_S9_postindex(x1, xRDI, -1);
SUBx_U12(xRCX, xRCX, 1);
CBNZx_MARK2(xRCX);
// done
} else {
INST_NAME("MOVSB");
GETDIR(x3, 1);
LDRB_U12(x1, xRSI, 0);
STRB_U12(x1, xRDI, 0);
ADDx_REG(xRSI, xRSI, x3);
ADDx_REG(xRDI, xRDI, x3);
}
SMWRITE();
break;
case 0xA5:
SMREAD();
if(rep) {
@@ -793,7 +818,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 1:
case 2:
if(rep==1) {INST_NAME("REPNZ CMPSW");} else {INST_NAME("REPZ CMPSW");}
MAYSETFLAGS();
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
CBZx_NEXT(xRCX);
TBNZ_MARK2(xFlags, F_DF);
@@ -832,13 +858,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("TEST AX,Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
u16 = F16;
MOV32w(x2, u16);
UBFXx(x1, xRAX, 0, 16);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
emit_test16c(dyn, ninst, x1, u16, x3, x4, x5);
break;
case 0xAB:
WILLWRITE();
if(rep) {
INST_NAME("REP STOSW");
CBZx_NEXT(xRCX);
@@ -894,7 +918,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 1:
case 2:
if(rep==1) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");}
MAYSETFLAGS();
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
CBZx_NEXT(xRCX);
UXTHw(x1, xRAX);
@@ -938,7 +963,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("MOV Reg16, Iw");
u16 = F16;
MOV32w(x1, u16);
gd = xRAX+(opcode&7)+(rex.b<<3);
gd = TO_NAT((opcode & 7) + (rex.b << 3));
BFIz(gd, x1, 0, 16);
break;
@@ -949,9 +974,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("ROL Ew, Ib");
u8 = geted_ib(dyn, addr, ninst, nextop) & 15;
if (u8) {
SETFLAGS(X_CF | X_OF, SF_SUBSET_PENDING);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 1);
u8 = F8;
u8 = (F8)&0x1f;
emit_rol16c(dyn, ninst, x1, u8, x4, x5);
EWBACK;
} else {
@@ -962,9 +987,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 1:
INST_NAME("ROR Ew, Ib");
if (geted_ib(dyn, addr, ninst, nextop) & 15) {
SETFLAGS(X_CF | X_OF, SF_SUBSET_PENDING);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 1);
u8 = F8;
u8 = (F8)&0x1f;
emit_ror16c(dyn, ninst, x1, u8, x4, x5);
EWBACK;
} else {
@@ -978,7 +1003,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 1);
u8 = F8;
u8 = (F8)&0x1f;
emit_rcl16c(dyn, ninst, ed, u8, x4, x5);
EWBACK;
} else {
@@ -992,7 +1017,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 1);
u8 = F8;
u8 = (F8)&0x1f;
emit_rcr16c(dyn, ninst, ed, u8, x4, x5);
EWBACK;
} else {
@@ -1047,7 +1072,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("MOV Ew, Iw");
nextop = F8;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
u16 = F16;
MOV32w(x1, u16);
BFIz(ed, x1, 0, 16);
@@ -1065,14 +1090,14 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ew, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 0);
emit_rol16c(dyn, ninst, x1, 1, x5, x4);
EWBACK;
break;
case 1:
INST_NAME("ROR Ew, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 0);
emit_ror16c(dyn, ninst, x1, 1, x5, x4);
EWBACK;
@@ -1127,8 +1152,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
TSTw_mask(xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
CBZw_NEXT(x2);
}
ANDw_mask(x2, xRCX, 0, 0b00011); //mask=0x00000000f
MOV32w(x4, 16);
@@ -1138,9 +1163,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
LSRw_REG(ed, ed, x2);
EWBACK;
UFLAG_IF { // calculate flags directly
CMPSw_U12(x2, 15);
B_MARK(cNE);
ADDxw_REG_LSR(x3, ed, ed, 15);
SUBw_U12(x2, x2, 15);
CBNZw_MARK(x2);
EORw_REG_LSR(x3, ed, ed, 15);
BFIw(xFlags, x3, F_OF, 1);
MARK;
BFIw(xFlags, ed, F_CF, 1);
@@ -1153,8 +1178,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
TSTw_mask(xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
CBZw_NEXT(x2);
}
ANDw_mask(x2, xRCX, 0, 0b00011); //mask=0x00000000f
GETEW(x1, 0);
@@ -1162,8 +1187,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
LSRw_REG(ed, ed, x2);
EWBACK;
UFLAG_IF { // calculate flags directly
CMPSw_U12(x2, 1);
B_MARK(cNE);
SUBw_U12(x2, x2, 1);
CBNZw_MARK(x2);
LSRxw(x2, ed, 14); // x2 = d>>14
EORw_REG_LSR(x2, x2, x2, 1); // x2 = ((d>>14) ^ ((d>>14)>>1))
BFIw(xFlags, x2, F_OF, 1);
@@ -1202,11 +1227,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
UFLAG_IF {
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
} else {
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
CBZw_NEXT(x2);
}
GETEW(x1, 0);
emit_shl16(dyn, ninst, x1, x2, x5, x4);
@@ -1217,11 +1240,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
UFLAG_IF {
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
} else {
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
CBZw_NEXT(x2);
}
GETEW(x1, 0);
emit_shr16(dyn, ninst, x1, x2, x5, x4);
@@ -1232,11 +1253,10 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
UFLAG_IF {
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
CBZw_NEXT(x2);
} else {
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
}
GETSEW(x1, 0);
emit_sar16(dyn, ninst, x1, x2, x5, x4);
@@ -1244,6 +1264,54 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
}
break;
case 0xD9:
nextop = F8;
if(MODREG) {
DEFAULT;
} else
switch((nextop>>3)&7) {
case 6:
INST_NAME("FNSTENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
MOV32w(x2, 1);
CALL(fpu_savenv, -1);
break;
default:
DEFAULT;
}
break;
case 0xDD:
nextop = F8;
if(MODREG) {
DEFAULT;
} else
switch((nextop>>3)&7) {
case 4:
INST_NAME("FRSTOR Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(native_frstor16, -1);
break;
case 6:
INST_NAME("FNSAVE Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(native_fsave16, -1);
CALL(reset_fpu, -1);
break;
default:
DEFAULT;
}
break;
case 0xF0:
return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
@@ -1257,8 +1325,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, 2);
u16 = F16;
MOV32w(x2, u16);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
emit_test16c(dyn, ninst, x1, u16, x3, x4, x5);
break;
case 2:
INST_NAME("NOT Ew");
@@ -1298,7 +1365,6 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 6:
INST_NAME("DIV Ew");
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE(x1);
GETEW(x1, 0);
UXTHw(x2, xRAX);
BFIw(x2, xRDX, 16, 16);
@@ -1316,12 +1382,17 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MSUBw(x4, x3, ed, x2); // x4 = x2 mod ed (i.e. x2 - x3*ed)
BFIz(xRAX, x3, 0, 16);
BFIz(xRDX, x4, 0, 16);
SET_DFNONE(x2);
IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF)
if(box64_dynarec_test) {
MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF));
BICw(xFlags, xFlags, x1);
}
break;
case 7:
INST_NAME("IDIV Ew");
SKIPTEST(x1);
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE(x1);
GETSEW(x1, 0);
if(box64_dynarec_div0) {
CBNZw_MARK3(ed);
@@ -1339,6 +1410,12 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MSUBw(x4, x3, ed, x2); // x4 = x2 mod ed (i.e. x2 - x3*ed)
BFIz(xRAX, x3, 0, 16);
BFIz(xRDX, x4, 0, 16);
SET_DFNONE(x2);
IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF)
if(box64_dynarec_test) {
MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF));
BICw(xFlags, xFlags, x1);
}
break;
}
break;
@@ -1360,14 +1437,14 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 0:
INST_NAME("INC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
GETEW(x1, 0);
emit_inc16(dyn, ninst, x1, x2, x4);
EWBACK;
break;
case 1:
INST_NAME("DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
GETEW(x1, 0);
emit_dec16(dyn, ninst, x1, x2, x4);
EWBACK;
File diff suppressed because it is too large. Load diff
+33 -18
View File
@@ -18,7 +18,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog)
@@ -61,11 +61,14 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
grab_segdata(dyn, addr, ninst, x4, seg);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
v1 = fpu_get_scratch(dyn);
VLDR64_REG(v1, ed, x4);
v1 = fpu_get_scratch(dyn, ninst);
if(rex.is32bits)
VLDR64_REG_SXTW(v1, x4, ed);
else
VLDR64_REG(v1, ed, x4);
}
FCMPD(v0, v1);
FCOMI(x1, x2);
FCOMI(x1, x2, 0, v0, v1, 0); //disable precise cmp
break;
case 0x6F:
@@ -80,7 +83,10 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
SMREAD();
VLDR128_REG(v0, ed, x4);
if(rex.is32bits)
VLDR128_REG_SXTW(v0, x4, ed);
else
VLDR128_REG(v0, ed, x4);
}
break;
@@ -94,7 +100,10 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VSTR128_REG(v0, ed, x4);
if(rex.is32bits)
VSTR128_REG_SXTW(v0, x4, ed);
else
VSTR128_REG(v0, ed, x4);
SMWRITE2();
}
break;
@@ -110,7 +119,10 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VSTR64_REG(v0, ed, x4);
if(rex.is32bits)
VSTR64_REG_SXTW(v0, x4, ed);
else
VSTR64_REG(v0, ed, x4);
SMWRITE();
}
break;
@@ -139,8 +151,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
grab_segdata(dyn, addr, ninst, x1, seg);
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_or16(dyn, ninst, x1, x5, x2, x4);
emit_or16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 2: //ADC
@@ -171,8 +182,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
grab_segdata(dyn, addr, ninst, x1, seg);
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_and16(dyn, ninst, x1, x5, x2, x4);
emit_and16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 5: //SUB
@@ -191,8 +201,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
grab_segdata(dyn, addr, ninst, x1, seg);
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_xor16(dyn, ninst, x1, x5, x2, x4);
emit_xor16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 7: //CMP
@@ -215,7 +224,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGD; // don't need GETGW here
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if(rex.w) {
MOVx_REG(ed, gd);
} else {
@@ -229,18 +238,21 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(rex.w) {
STRx_REG(gd, ed, x4);
} else {
STRH_REG(gd, ed, x4);
if(rex.is32bits)
STRH_REG_SXTW(gd, x4, ed);
else
STRH_REG(gd, ed, x4);
}
SMWRITE();
}
break;
case 0x8B:
INST_NAME("MOV Gd, FS:Ed");
INST_NAME("MOV Gw, FS:Ew");
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if(rex.w) {
MOVx_REG(gd, ed);
} else {
@@ -255,7 +267,10 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(rex.w) {
LDRx_REG(gd, ed, x4);
} else {
LDRH_REG(x1, ed, x4);
if(rex.is32bits)
LDRH_REG_SXTW(x1, x4, ed);
else
LDRH_REG(x1, ed, x4);
BFIx(gd, x1, 0, 16);
}
}
+78 -62
View File
@@ -18,7 +18,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -30,7 +30,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
uint8_t nextop;
uint8_t gd, ed, u8;
uint8_t wback, wb1, wb2, gb1, gb2;
int32_t i32;
int16_t i16;
int64_t i64, j64;
int64_t fixedaddress;
int unscaled;
@@ -55,7 +55,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGW(x5);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_add16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
@@ -85,7 +85,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGW(x5);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_or16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
@@ -120,7 +120,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGD;
UXTHw(x6, xRAX);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
UXTHw(x1, ed);
CMPSxw_REG(x6, x1);
@@ -177,10 +177,10 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("LOCK XADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3));
UXTHx(x5, gd);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
BFIx(gd, ed, 0, 16);
emit_add16(dyn, ninst, x5, gd, x3, x4);
BFIx(ed, x5, 0, 16);
@@ -216,7 +216,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGW(x5);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_adc16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
@@ -237,7 +237,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGW(x5);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_and16(dyn, ninst, x6, gd, x3, x4);
BFIx(ed, x6, 0, 16);
@@ -274,16 +274,16 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV32w(x5, i16);
UXTHw(x6, ed);
emit_add16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
if(!ALIGNED_ATOMICH) {
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
@@ -325,27 +325,32 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(opcode==0x81) {INST_NAME("LOCK OR Ew, Iw");} else {INST_NAME("LOCK OR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_or16(dyn, ninst, x6, x5, x3, x4);
emit_or16c(dyn, ninst, x6, i16, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(!i64) {MOV32w(x5, i16);}
if(arm64_atomics) {
UFLAG_IF {
LDSETALH(x5, x1, wback);
emit_or16(dyn, ninst, x1, x5, x3, x4);
emit_or16c(dyn, ninst, x1, i16, x3, x4);
} else {
STSETLH(x5, wback);
}
} else {
i64 = convert_bitmask_w(i16);
if(!i64) {MOV32w(x5, i16);}
MARKLOCK;
LDAXRH(x1, wback);
emit_or16(dyn, ninst, x1, x5, x3, x4);
if(i64) {
emit_or16c(dyn, ninst, x1, i16, x3, x4);
} else {
emit_or16(dyn, ninst, x1, x5, x3, x4);
}
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
@@ -357,16 +362,16 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV32w(x5, i16);
UXTHw(x6, ed);
emit_adc16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MARKLOCK;
LDAXRH(x1, wback);
emit_adc16(dyn, ninst, x1, x5, x3, x4);
@@ -380,16 +385,16 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV32w(x5, i16);
UXTHw(x6, ed);
emit_sbb16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MARKLOCK;
LDAXRH(x1, wback);
emit_sbb16(dyn, ninst, x1, x5, x3, x4);
@@ -402,29 +407,37 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(opcode==0x81) {INST_NAME("LOCK AND Ew, Iw");} else {INST_NAME("LOCK AND Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_and16(dyn, ninst, x6, x5, x3, x4);
emit_and16c(dyn, ninst, x6, i16, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
if(opcode==0x81) i16 = F16S; else i16 = F8S;
i64 = convert_bitmask_w(i16);
if(arm64_atomics) {
MOV32w(x5, ~i32);
MOV32w(x5, ~i16);
UFLAG_IF {
LDCLRALH(x5, x1, wback);
MVNw_REG(x5, x5);
emit_and16(dyn, ninst, x1, x5, x3, x4);
if(i64) {
emit_and16c(dyn, ninst, x1, i16, x3, x4);
} else {
MVNw_REG(x5, x5);
emit_and16(dyn, ninst, x1, x5, x3, x4);
}
} else {
STCLRLH(x5, wback);
}
} else {
MOV32w(x5, i32);
if(!i64) {MOV32w(x5, i16);}
MARKLOCK;
LDAXRH(x1, wback);
emit_and16(dyn, ninst, x1, x5, x3, x4);
if(i64) {
emit_and16c(dyn, ninst, x1, i16, x3, x4);
} else {
emit_and16(dyn, ninst, x1, x5, x3, x4);
}
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
@@ -435,16 +448,16 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(opcode==0x81) {INST_NAME("LOCK SUB Ew, Iw");} else {INST_NAME("LOCK SUB Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV32w(x5, i16);
UXTHw(x6, ed);
emit_sub16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
if(!ALIGNED_ATOMICH) {
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
@@ -489,27 +502,30 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(opcode==0x81) {INST_NAME("LOCK XOR Ew, Iw");} else {INST_NAME("LOCK XOR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_xor16(dyn, ninst, x6, x5, x3, x4);
emit_xor16c(dyn, ninst, x6, i16, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
i64 = convert_bitmask_w(i16);
if(arm64_atomics) {
UFLAG_IF {
LDEORALH(x5, x1, wback);
emit_xor16(dyn, ninst, x1, x5, x3, x4);
emit_xor16c(dyn, ninst, x1, i16, x3, x4);
} else {
STEORLH(x5, wback);
}
} else {
if(!i64) {MOV32w(x5, i16);}
MARKLOCK;
LDAXRH(x1, wback);
emit_xor16(dyn, ninst, x1, x5, x3, x4);
if(i64)
emit_xor16c(dyn, ninst, x1, i16, x3, x4);
else
emit_xor16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
@@ -522,9 +538,9 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEW(x6, (opcode==0x81)?2:1);
(void)wb1;
// No need to LOCK, this is readonly
if(opcode==0x81) i32 = F16S; else i32 = F8S;
if(i32) {
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
MOV32w(x5, i16);
emit_cmp16(dyn, ninst, x6, x5, x3, x4, x6);
} else {
emit_cmp16_0(dyn, ninst, ed, x3, x4);
@@ -539,9 +555,9 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
{
case 0: // INC Ew
INST_NAME("LOCK INC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_inc16(dyn, ninst, x6, x5, x3);
BFIx(ed, x6, 0, 16);
@@ -567,9 +583,9 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 1: //DEC Ew
INST_NAME("LOCK DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_dec16(dyn, ninst, x6, x5, x3);
BFIx(ed, x6, 0, 16);
+1 -1
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "emu/x64compstrings.h"
uintptr_t dynarec64_66F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
+22 -1
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "emu/x64compstrings.h"
uintptr_t dynarec64_66F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
@@ -56,6 +56,27 @@ uintptr_t dynarec64_66F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
switch(opcode) {
case 0xBD:
INST_NAME("LZCNT Gw, Ew");
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
SET_DFNONE(x1);
nextop = F8;
GETEW(x1, 0);
GETGW(x2);
IFX(X_CF) {
TSTxw_REG(ed, ed);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_CF, 1); // CF = is source 0?
}
LSLw_IMM(ed, ed, 16);
CLZw(gd, ed);
IFX(X_ZF) {
TSTxw_REG(gd, gd);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
}
EWBACK;
break;
default:
DEFAULT;
+446 -62
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
#define GETGm gd = ((nextop&0x38)>>3)
@@ -37,6 +37,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t u8;
int32_t i32;
int64_t j64, i64;
int16_t i16;
int cacheupd = 0;
int lock;
int v0, v1, s0;
@@ -54,11 +55,18 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
return addr;
}
while(opcode==0x67) opcode = F8;
// reset rex after 67
GETREX();
rep = 0;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
while((opcode==0xF2) || (opcode==0xF3) || (opcode>=0x40 && opcode<=0x4F)) {
if((opcode==0xF2) || (opcode==0xF3))
rep = opcode-0xF1;
if(opcode>=0x40 && opcode<=0x4F)
rex.rex = opcode;
opcode = F8;
}
@@ -201,13 +209,46 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
s0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
} else {
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
}
FCMPS(v0, s0);
FCOMI(x1, x2);
FCOMI(x1, x2, 0, v0, s0, 1); //disabled precise cmp
break;
default:
DEFAULT;
}
break;
case 0x38: /* MAP 0F38 */
opcode = F8;
switch(opcode) {
case 0xF6:
switch(rep) {
case 2:
INST_NAME("ADOX Gd, Ed");
nextop = F8;
READFLAGS(X_OF);
SETFLAGS(X_OF, SF_SUBSET);
GETED32(0);
GETGD;
MRS_nzcv(x3);
LSRw(x4, xFlags, F_OF);
BFIx(x3, x4, 29, 1); // set C
MSR_nzcv(x3); // load CC into ARM CF
IFX(X_OF) {
ADCSxw_REG(gd, gd, ed);
CSETw(x3, cCS);
BFIw(xFlags, x3, F_OF, 1);
} else {
ADCxw_REG(gd, gd, ed);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
@@ -265,6 +306,19 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SMWRITE();
}
break;
case 2:
INST_NAME("MOVDQU Ex, Gx");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VST128(v0, ed, fixedaddress);
SMWRITE();
}
break;
default:
DEFAULT;
}
@@ -276,11 +330,11 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETGD;
if(MODREG) {
if(rex.rex) {
eb1 = xRAX+(nextop&7)+(rex.b<<3);
eb1 = TO_NAT((nextop & 7) + (rex.b << 3));
eb2 = 0;
} else {
ed = (nextop&7);
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
}
UBFXxw(gd, eb1, eb2*8, 8);
@@ -295,7 +349,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UBFXxw(gd, ed, 0, 16);
} else {
SMREAD();
@@ -628,13 +682,32 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
emit_cmp32_0(dyn, ninst, rex, xRAX, x3, x4);
break;
case 0x50:
case 0x51:
case 0x52:
case 0x53:
case 0x54:
case 0x55:
case 0x56:
case 0x57:
case 0x58:
case 0x59:
case 0x5A:
case 0x5B:
case 0x5C:
case 0x5D:
case 0x5E:
case 0x5F:
// just use regular conditional jump
return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog);
case 0x63:
INST_NAME("MOVSXD Gd, Ed");
nextop = F8;
GETGD;
if(rex.w) {
if(MODREG) { // reg <= reg
SXTWx(gd, xRAX+(nextop&7)+(rex.b<<3));
SXTWx(gd, TO_NAT((nextop & 7) + (rex.b << 3)));
} else { // mem <= reg
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
@@ -642,7 +715,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
} else {
if(MODREG) { // reg <= reg
MOVw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
MOVw_REG(gd, TO_NAT((nextop & 7) + (rex.b << 3)));
} else { // mem <= reg
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
@@ -656,18 +729,166 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETREX();
switch(opcode) {
case 0x0F:
nextop = F8;
switch(nextop) {
case 0x6F:
INST_NAME("MOVDQA Gx,Ex");
nextop = F8;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
GETGX_empty(v0);
VMOVQ(v0, v1);
} else {
GETGX_empty(v0);
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VLD128(v0, ed, fixedaddress);
}
break;
case 0x7E:
INST_NAME("MOVD Ed,Gx");
nextop = F8;
GETGX(v0, 0);
if(rex.w) {
if(MODREG) {
ed = TO_NAT((nextop & 0x07) + (rex.b << 3));
VMOVQDto(ed, v0, 0);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v0, ed, fixedaddress);
SMWRITE2();
}
} else {
if(MODREG) {
ed = TO_NAT((nextop & 0x07) + (rex.b << 3));
VMOVSto(ed, v0, 0);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VST32(v0, ed, fixedaddress);
SMWRITE2();
}
}
break;
case 0xD6:
INST_NAME("MOVQ Ex, Gx");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
FMOVD(v1, v0);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v0, ed, fixedaddress);
SMWRITE2();
}
break;
case 0xFE:
INST_NAME("PADDD Gx,Ex");
nextop = F8;
GETGX(v0, 1);
GETEX32(v1, 0, 0);
VADDQ_32(v0, v0, v1);
break;
default:
DEFAULT;
}
break;
case 0x81:
case 0x83:
nextop = F8;
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {INST_NAME("ADD Ew, Iw");} else {INST_NAME("ADD Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_add16(dyn, ninst, ed, x5, x2, x4);
EWBACK;
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("OR Ew, Iw");} else {INST_NAME("OR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_or16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 2: //ADC
if(opcode==0x81) {INST_NAME("ADC Ew, Iw");} else {INST_NAME("ADC Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_adc16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 3: //SBB
if(opcode==0x81) {INST_NAME("SBB Ew, Iw");} else {INST_NAME("SBB Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_sbb16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("AND Ew, Iw");} else {INST_NAME("AND Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_and16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("SUB Ew, Iw");} else {INST_NAME("SUB Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_sub16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("XOR Ew, Iw");} else {INST_NAME("XOR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_xor16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("CMP Ew, Iw");} else {INST_NAME("CMP Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
MOVZw(x2, i16);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
} else
emit_cmp16_0(dyn, ninst, x1, x3, x4);
break;
}
break;
case 0x89:
INST_NAME("MOV Ew, Gw");
nextop = F8;
GETGD; // don't need GETGW here
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if(ed!=gd) {
BFIx(ed, gd, 0, 16);
}
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, &lock, 0, 0);
WILLWRITELOCK(lock);
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff << 1, 1, rex, &lock, 0, 0);
STH(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
@@ -706,9 +927,22 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UFLAG_IF {
SMULH(x3, ed, x4);
MULx(gd, ed, x4);
UFLAG_OP1(x3);
UFLAG_RES(gd);
UFLAG_DF(x3, d_imul64);
SET_DFNONE(x1);
IFX(X_ZF | X_PF | X_AF | X_SF) {
MOV32w(x1, (1<<F_ZF)|(1<<F_AF)|(1<<F_PF)|(1<<F_SF));
BICw(xFlags, xFlags, x1);
}
IFX(X_CF | X_OF) {
ASRx(x4, gd, 63);
CMPSx_REG(x3, x4);
CSETw(x1, cNE);
IFX(X_CF) {
BFIw(xFlags, x1, F_CF, 1);
}
IFX(X_OF) {
BFIw(xFlags, x1, F_OF, 1);
}
}
} else {
MULxw(gd, ed, x4);
}
@@ -716,17 +950,49 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
// 32bits imul
UFLAG_IF {
SMULL(gd, ed, x4);
UFLAG_RES(gd);
LSRx(x3, gd, 32);
UFLAG_OP1(x3);
UFLAG_DF(x3, d_imul32);
MOVw_REG(gd, gd);
SET_DFNONE(x1);
IFX(X_ZF | X_PF | X_AF | X_SF) {
MOV32w(x1, (1<<F_ZF)|(1<<F_AF)|(1<<F_PF)|(1<<F_SF));
BICw(xFlags, xFlags, x1);
}
IFX(X_CF | X_OF) {
ASRw(x4, gd, 31);
CMPSw_REG(x3, x4);
CSETw(x1, cNE);
IFX(X_CF) {
BFIw(xFlags, x1, F_CF, 1);
}
IFX(X_OF) {
BFIw(xFlags, x1, F_OF, 1);
}
}
} else {
MULxw(gd, ed, x4);
}
}
break;
case 0x70:
case 0x71:
case 0x72:
case 0x73:
case 0x74:
case 0x75:
case 0x76:
case 0x77:
case 0x78:
case 0x79:
case 0x7A:
case 0x7B:
case 0x7C:
case 0x7D:
case 0x7E:
case 0x7F:
// just use regular conditional jump
return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog);
case 0x81:
case 0x83:
nextop = F8;
@@ -811,10 +1077,10 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
gd = ((nextop&0x38)>>3)+(rex.r<<3);
if(rex.rex) {
gb2 = 0;
gb1 = xRAX + gd;
gb1 = TO_NAT(gd);
} else {
gb2 = ((gd&4)<<1);
gb1 = xRAX+(gd&3);
gb1 = TO_NAT(gd & 3);
}
if(gb2) {
gd = x4;
@@ -825,16 +1091,15 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
ed = (nextop&7) + (rex.b<<3);
if(rex.rex) {
eb1 = xRAX+ed;
eb1 = TO_NAT(ed);
eb2 = 0;
} else {
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = ((ed&4)>>2); // L or H
}
BFIx(eb1, gd, eb2*8, 8);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff, 0, rex, &lock, 0, 0);
WILLWRITELOCK(lock);
STB(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
@@ -844,10 +1109,9 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);
MOVxw_REG(TO_NAT((nextop & 7) + (rex.b << 3)), gd);
} else { // mem <= reg
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
WILLWRITELOCK(lock);
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff << (2 + rex.w), (1 << (2 + rex.w)) - 1, rex, &lock, 0, 0);
STxw(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
@@ -856,21 +1120,21 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("MOV Gb, Eb");
nextop = F8;
if(rex.rex) {
gb1 = gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
gb1 = gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3));
gb2=0;
} else {
gd = (nextop&0x38)>>3;
gb1 = xRAX+(gd&3);
gb1 = TO_NAT(gd & 3);
gb2 = ((gd&4)<<1);
}
if(MODREG) {
if(rex.rex) {
wback = xRAX+(nextop&7)+(rex.b<<3);
wback = TO_NAT((nextop & 7) + (rex.b << 3));
wb2 = 0;
} else {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xRAX+(wback&3);
wback = TO_NAT(wback & 3);
}
if(wb2) {
UBFXw(x4, wback, wb2*8, 8);
@@ -891,7 +1155,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop=F8;
GETGD;
if(MODREG) {
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
MOVxw_REG(gd, TO_NAT((nextop & 7) + (rex.b << 3)));
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
SMREADLOCK(lock);
@@ -913,12 +1177,38 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
gd = TO_NAT((opcode & 0x07) + (rex.b << 3));
if(gd==xRAX) {
INST_NAME("NOP");
} else {
INST_NAME("XCHG EAX, Reg");
MOVxw_REG(x2, xRAX);
MOVxw_REG(xRAX, gd);
MOVxw_REG(gd, x2);
}
break;
case 0xA9:
INST_NAME("TEST EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_test32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5);
break;
case 0xC1:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ed, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_rol32c(dyn, ninst, rex, ed, u8, x3, x4);
@@ -926,7 +1216,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 1:
INST_NAME("ROR Ed, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_ror32c(dyn, ninst, rex, ed, u8, x3, x4);
@@ -953,11 +1243,13 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 4:
case 6:
INST_NAME("SHL Ed, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4);
WBACK;
if(u8) { //should create the geted32_ib utility function for that
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4);
WBACK;
}
break;
case 5:
INST_NAME("SHR Ed, Ib");
@@ -982,6 +1274,53 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xC4:
nextop = F8;
if(rex.is32bits && !(MODREG)) {
DEFAULT;
} else {
if(rex.is32bits) {
DEFAULT;
return addr;
}
vex_t vex = {0};
vex.rex = rex;
u8 = nextop;
vex.m = u8&0b00011111;
vex.rex.b = (u8&0b00100000)?0:1;
vex.rex.x = (u8&0b01000000)?0:1;
vex.rex.r = (u8&0b10000000)?0:1;
u8 = F8;
vex.p = u8&0b00000011;
vex.l = (u8>>2)&1;
vex.v = ((~u8)>>3)&0b1111;
vex.rex.w = (u8>>7)&1;
addr = dynarec64_67_AVX(dyn, addr, ip, ninst, vex, ok, need_epilog);
}
break;
case 0xC5:
nextop = F8;
if(rex.is32bits && !(MODREG)) {
DEFAULT;
} else {
if(rex.is32bits) {
DEFAULT;
return addr;
}
vex_t vex = {0};
vex.rex = rex;
u8 = nextop;
vex.p = u8&0b00000011;
vex.l = (u8>>2)&1;
vex.v = ((~u8)>>3)&0b1111;
vex.rex.r = (u8&0b10000000)?0:1;
vex.rex.b = 0;
vex.rex.x = 0;
vex.rex.w = 0;
vex.m = VEX_M_0F;
addr = dynarec64_67_AVX(dyn, addr, ip, ninst, vex, ok, need_epilog);
}
break;
case 0xC6:
INST_NAME("MOV Eb, Ib");
nextop=F8;
@@ -989,10 +1328,10 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
u8 = F8;
if(!rex.rex) {
ed = (nextop&7);
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
} else {
eb1 = xRAX+(nextop&7)+(rex.b<<3);
eb1 = TO_NAT((nextop & 7) + (rex.b << 3));
eb2 = 0;
}
MOV32w(x3, u8);
@@ -1005,7 +1344,6 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = x3;
} else
ed = xZR;
WILLWRITELOCK(lock);
STB(ed, wback, fixedaddress);
SMWRITELOCK(lock);
}
@@ -1015,13 +1353,12 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop=F8;
if(MODREG) { // reg <= i32
i64 = F32S;
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV64xw(ed, i64);
} else { // mem <= i32
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 4);
i64 = F32S;
MOV64xw(x3, i64);
WILLWRITELOCK(lock);
STxw(x3, ed, fixedaddress);
SMWRITELOCK(lock);
}
@@ -1043,21 +1380,23 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else { \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size);\
SKIP_SEVL(i32); \
B(i32); \
} \
} else { \
/* inside the block */ \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
Bcond(YES, i32); \
SKIP_SEVL(i32); \
Bcond(YES, i32); \
}
case 0xE0:
INST_NAME("LOOPNZ (32bits)");
READFLAGS(X_ZF);
i8 = F8S;
MOVw_REG(x1, xRCX);
SUBSw_U12(x1, x1, 1);
SUBw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 32);
B_NEXT(cEQ); // ECX is 0, no LOOP
CBZw_NEXT(x1); // ECX is 0, no LOOP
TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
GO(cNE, cEQ);
break;
@@ -1066,9 +1405,9 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
READFLAGS(X_ZF);
i8 = F8S;
MOVw_REG(x1, xRCX);
SUBSw_U12(x1, x1, 1);
SUBw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 32);
B_NEXT(cEQ); // ECX is 0, no LOOP
CBZw_NEXT(x1); // ECX is 0, no LOOP
TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
GO(cEQ, cNE);
break;
@@ -1101,8 +1440,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32H(x1, 4);
i64 = F32S;
MOV64xw(x2, i64);
emit_test32(dyn, ninst, rex, ed, x2, x3, x4, x5);
emit_test32c(dyn, ninst, rex, ed, i64, x3, x4, x5);
break;
case 2:
INST_NAME("NOT Ed");
@@ -1119,7 +1457,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 4:
INST_NAME("MUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
SETFLAGS(X_ALL, SF_SET);
GETED32(0);
if(rex.w) {
if(ed==xRDX) gd=x3; else gd=xRDX;
@@ -1131,9 +1469,25 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVw_REG(xRAX, xRDX);
LSRx(xRDX, xRDX, 32);
}
UFLAG_RES(xRAX);
UFLAG_OP1(xRDX);
UFLAG_DF(x2, rex.w?d_mul64:d_mul32);
UFLAG_IF {
SET_DFNONE(x4);
IFX(X_CF|X_OF) {
CMPSxw_U12(xRDX, 0);
CSETw(x3, cNE);
IFX(X_CF) {
BFIw(xFlags, x3, F_CF, 1);
}
IFX(X_OF) {
BFIw(xFlags, x3, F_OF, 1);
}
}
IFX(X_AF | X_PF | X_ZF | X_SF)
if(box64_dynarec_test) {
// to avoid noise during test
MOV32w(x3, (1<<F_ZF)|(1<<F_AF)|(1<<F_PF)|(1<<F_SF));
BICw(xFlags, xFlags, x3);
}
}
break;
case 5:
INST_NAME("IMUL EAX, Ed");
@@ -1156,7 +1510,6 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 6:
INST_NAME("DIV Ed");
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE(x2);
if(!rex.w) {
GETED32(0);
MOVw_REG(x3, xRAX);
@@ -1190,12 +1543,17 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVx_REG(xRAX, x2);
}
}
SET_DFNONE(x2);
IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF)
if(box64_dynarec_test) {
MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF));
BICw(xFlags, xFlags, x1);
}
break;
case 7:
INST_NAME("IDIV Ed");
NOTEST(x1);
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE(x2);
if(!rex.w) {
GETSED32w(0);
MOVw_REG(x3, xRAX);
@@ -1227,12 +1585,32 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVx_REG(xRAX, x2);
}
}
SET_DFNONE(x2);
IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF)
if(box64_dynarec_test) {
MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF));
BICw(xFlags, xFlags, x1);
}
break;
}
break;
case 0xFF:
nextop = F8;
switch((nextop>>3)&7) {
case 0: // INC Ed
INST_NAME("INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
GETED32(0);
emit_inc32(dyn, ninst, rex, ed, x3, x4);
WBACK;
break;
case 1: //DEC Ed
INST_NAME("DEC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
GETED32(0);
emit_dec32(dyn, ninst, rex, ed, x3, x4);
WBACK;
break;
case 2: // CALL Ed
INST_NAME("CALL Ed");
PASS2IF((box64_dynarec_safeflags>1) ||
@@ -1246,7 +1624,6 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETED32(0);
if(box64_dynarec_callret && box64_dynarec_bigblock>1) {
BARRIER(BARRIER_FULL);
BARRIER_NEXT(BARRIER_FULL);
} else {
BARRIER(BARRIER_FLOAT);
*need_epilog = 0;
@@ -1262,15 +1639,22 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ADR_S20(x4, j64);
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
} else {
MESSAGE(LOG_NONE, "\tCALLRET set return to Jmptable(%p)\n", (void*)addr);
j64 = getJumpTableAddress64(addr);
TABLE64(x4, j64);
LDRx_U12(x4, x4, 0);
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
ADR_S20(x4, j64);
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
}
STPx_S7_preindex(x4, xRIP, xSP, -16);
}
PUSH1z(xRIP);
jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
if(box64_dynarec_callret && addr >= (dyn->start + dyn->isize)) {
// jumps out of current dynablock...
MARK;
j64 = getJumpTableAddress64(addr);
TABLE64(x4, j64);
LDRx_U12(x4, x4, 0);
BR(x4);
}
break;
default:
DEFAULT;
+4 -4
View File
@@ -18,7 +18,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
#define GETGm gd = ((nextop&0x38)>>3)
@@ -66,7 +66,7 @@ uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, in
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);
MOVxw_REG(TO_NAT((nextop & 7) + (rex.b << 3)), gd);
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, 0);
@@ -79,7 +79,7 @@ uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, in
nextop=F8;
GETGD;
if(MODREG) { // reg => reg
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
MOVxw_REG(gd, TO_NAT((nextop & 7) + (rex.b << 3)));
} else { // mem => reg
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, 0);
@@ -92,7 +92,7 @@ uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, in
nextop=F8;
if(MODREG) { // reg <= reg
POP1_32(x1);
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), x1);
MOVxw_REG(TO_NAT((nextop & 7) + (rex.b << 3)), x1);
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
POP1_32(x1);
+10 -8
View File
@@ -18,7 +18,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
#define GETGm gd = ((nextop&0x38)>>3)
@@ -80,21 +80,23 @@ uintptr_t dynarec64_67_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
} else { \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size);\
SKIP_SEVL(i32); \
B(i32); \
} \
} else { \
/* inside the block */ \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
Bcond(YES, i32); \
SKIP_SEVL(i32); \
Bcond(YES, i32); \
}
case 0xE0:
INST_NAME("LOOPNZ (16bits)");
READFLAGS(X_ZF);
i8 = F8S;
UXTHw(x1, xRCX);
SUBSw_U12(x1, x1, 1);
SUBw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 16);
B_NEXT(cEQ); // ECX is 0, no LOOP
CBZw_NEXT(x1); // ECX is 0, no LOOP
TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
GO(cNE, cEQ);
break;
@@ -103,9 +105,9 @@ uintptr_t dynarec64_67_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
READFLAGS(X_ZF);
i8 = F8S;
UXTHw(x1, xRCX);
SUBSw_U12(x1, x1, 1);
SUBw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 16);
B_NEXT(cEQ); // ECX is 0, no LOOP
CBZw_NEXT(x1); // ECX is 0, no LOOP
TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
GO(cEQ, cNE);
break;
+133
View File
@@ -0,0 +1,133 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "../dynarec_helper.h"
static const char* avx_prefix_string(uint16_t p)
{
switch(p) {
case VEX_P_NONE: return "0";
case VEX_P_66: return "66";
case VEX_P_F2: return "F2";
case VEX_P_F3: return "F3";
default: return "??";
}
}
static const char* avx_map_string(uint16_t m)
{
switch(m) {
case VEX_M_NONE: return "0";
case VEX_M_0F: return "0F";
case VEX_M_0F38: return "0F38";
case VEX_M_0F3A: return "0F3A";
default: return "??";
}
}
uintptr_t dynarec64_67_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed, vd;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
rex_t rex = vex.rex;
if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_F2)) {
switch(opcode) {
case 0xF6:
INST_NAME("MULX Gd, Vd, Ed (,RDX)");
nextop = F8;
GETGD;
GETED32(0);
GETVD;
if(rex.w) {
// 64bits mul
UMULH(x3, xRDX, ed);
MULx(vd, xRDX, ed);
MOVx_REG(gd, x3);
} else {
// 32bits mul
UMULL(x3, xRDX, ed);
MOVw_REG(vd, x3);
LSRx(gd, x3, 32);
}
break;
default:
DEFAULT;
}
}
else if((vex.m==VEX_M_0F) && (vex.p==VEX_P_66)) {
switch(opcode) {
case 0xD6:
INST_NAME("VMOVQ Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOV(v1, v0);
YMM0((nextop&7)+(rex.b<<3));
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
}
break;
default:
DEFAULT;
}
}
else {DEFAULT;}
if((*ok==-1) && (box64_dynarec_log>=LOG_INFO || box64_dynarec_dump || box64_dynarec_missing==1)) {
dynarec_log(LOG_NONE, "Dynarec unimplemented AVX opcode size %d prefix %s map %s opcode %02X ", 128<<vex.l, avx_prefix_string(vex.p), avx_map_string(vex.m), opcode);
}
return addr;
}
+78
View File
@@ -0,0 +1,78 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "../dynarec_helper.h"
static const char* avx_prefix_string(uint16_t p)
{
switch(p) {
case VEX_P_NONE: return "0";
case VEX_P_66: return "66";
case VEX_P_F2: return "F2";
case VEX_P_F3: return "F3";
default: return "??";
}
}
static const char* avx_map_string(uint16_t m)
{
switch(m) {
case VEX_M_NONE: return "0";
case VEX_M_0F: return "0F";
case VEX_M_0F38: return "0F38";
case VEX_M_0F3A: return "0F3A";
default: return "??";
}
}
uintptr_t dynarec64_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = PK(0);
rex_t rex = vex.rex;
if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_NONE))
addr = dynarec64_AVX_0F(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_NONE))
addr = dynarec64_AVX_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_66))
addr = dynarec64_AVX_66_0F(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_F2))
addr = dynarec64_AVX_F2_0F(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_F3))
addr = dynarec64_AVX_F3_0F(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_66))
addr = dynarec64_AVX_66_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F3A) && (vex.p==VEX_P_66))
addr = dynarec64_AVX_66_0F3A(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_F2))
addr = dynarec64_AVX_F2_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F3A) && (vex.p==VEX_P_F2))
addr = dynarec64_AVX_F2_0F3A(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_F3))
addr = dynarec64_AVX_F3_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog);
else {DEFAULT;}
if((*ok==-1) && (box64_dynarec_log>=LOG_INFO || box64_dynarec_dump || box64_dynarec_missing==1)) {
dynarec_log(LOG_NONE, "Dynarec unimplemented AVX opcode size %d prefix %s map %s opcode %02X ", 128<<vex.l, avx_prefix_string(vex.p), avx_map_string(vex.m), opcode);
}
return addr;
}
+712
View File
@@ -0,0 +1,712 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "my_cpuid.h"
#include "emu/x87emu_private.h"
#include "emu/x64shaext.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
#if STEP > 1
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
#endif
rex_t rex = vex.rex;
switch(opcode) {
case 0x10:
INST_NAME("VMOVUPS Gx,Ex");
nextop = F8;
GETG;
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg(dyn, ninst, x1, ed, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if(v0!=v1) VMOVQ(v0, v1);
if(vex.l) {
v1 = ymm_get_reg(dyn, ninst, x1, ed, 0, gd, -1, -1);
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, ed, -1, -1);
if(v0!=v1) VMOVQ(v0, v1);
}
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress); // no alignment issue with ARMv8 NEON :)
if(vex.l) {
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, -1, -1, -1);
VLDR128_U12(v0, ed, fixedaddress+16);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x11:
INST_NAME("VMOVUPS Ex,Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
if(vex.l) {
v0 = ymm_get_reg(dyn, ninst, x1, gd, 0, ed, -1, -1);
v1 = ymm_get_reg_empty(dyn, ninst, x1, ed, gd, -1, -1);
VMOVQ(v1, v0);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
if(vex.l) {
v0 = ymm_get_reg(dyn, ninst, x1, gd, 0, ed, -1, -1);
VSTR128_U12(v0, ed, fixedaddress+16);
}
SMWRITE2();
}
break;
case 0x12:
nextop = F8;
GETVX(v2, 0);
if(MODREG) {
INST_NAME("VMOVHLPS Gx, Vx, Ex");
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
GETGX_empty(v0);
if((v0!=v2) && (v0!=v1))
VMOVQ(v0, v2);
VMOVeD(v0, 0, v1, 1);
if((v0!=v2) && (v0==v1))
VMOVeD(v0, 1, v2, 1);
} else {
INST_NAME("VMOVLPS Gx, Vx, Ex");
GETGX_empty(v0);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(v0!=v2)
VMOVQ(v0, v2);
VLD1_64(v0, 0, ed);
}
YMM0(gd);
break;
case 0x13:
nextop = F8;
INST_NAME("VMOVLPS Ex, Vx, Gx");
GETGX(v0, 0);
GETVX(v2, 0);
if(v1!=v2)
VMOVQ(v0, v2);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1);
if(v0!=v1) VMOVeD(v1, 0, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VST1_64(v0, 0, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
SMWRITE2();
}
break;
case 0x14:
INST_NAME("VUNPCKLPS Gx, Vx, Ex");
nextop = F8;
SMREAD();
GETGX_empty_VXEX(v0, v2, v1, 0);
VZIP1Q_32(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VZIP1Q_32(v0, v2, v1);
} else YMM0(gd);
break;
case 0x15:
INST_NAME("VUNPCKHPS Gx, Vx, Ex");
nextop = F8;
SMREAD();
GETGX_empty_VXEX(v0, v2, v1, 0);
VZIP2Q_32(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VZIP2Q_32(v0, v2, v1);
} else YMM0(gd);
break;
case 0x16:
nextop = F8;
if(MODREG) {
INST_NAME("VMOVLHPS Gx, Vx, Ex");
GETGX(v0, 1);
GETVX(v2, 0);
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
if(v0!=v2 && v0!=v1) VMOVQ(v0, v2);
VMOVeD(v0, 1, v1, 0);
if(v0!=v2 && v0==v1) VMOVeD(v0, 0, v2, 0);
} else {
INST_NAME("VMOVHPS Gx, Vx, Ex");
SMREAD();
GETGX(v0, 1);
GETVX(v2, 0);
if(v0!=v2) VMOVQ(v0, v2);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VLD1_64(v0, 1, ed);
}
YMM0(gd);
break;
case 0x17:
INST_NAME("VMOVHPS Ex,Gx");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1);
VMOVeD(v1, 0, v0, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VST1_64(v0, 1, ed);
}
break;
case 0x28:
INST_NAME("VMOVAPS Gx, Ex");
nextop = F8;
GETG;
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg(dyn, ninst, x1, ed, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
if(vex.l) {
GETGY_empty_EY(v0, v1);
VMOVQ(v0, v1);
}
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
if(vex.l) {
GETGY_empty(v0, -1, -1, -1);
VLDR128_U12(v0, ed, fixedaddress+16);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x29:
INST_NAME("VMOVAPS Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
if(vex.l) {
GETGYEY_empty(v0, v1);
VMOVQ(v1, v0);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
if(vex.l) {
GETGY(v0, 0, -1, -1, -1);
VSTR128_U12(v0, ed, fixedaddress+16);
}
SMWRITE2();
}
break;
case 0x2B:
INST_NAME("VMOVNTPS Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
if(vex.l) {
GETGYEY_empty(v0, v1);
VMOVQ(v1, v0);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
if(vex.l) {
GETGY(v0, 0, -1, -1, -1);
VSTR128_U12(v0, ed, fixedaddress+16);
}
}
break;
case 0x2E:
// no special check...
case 0x2F:
if(opcode==0x2F) {INST_NAME("VCOMISS Gx, Ex");} else {INST_NAME("VUCOMISS Gx, Ex");}
SETFLAGS(X_ALL, SF_SET_NODF);
nextop = F8;
GETGX(v0, 0);
GETEXSS(s0, 0, 0);
FCMPS(v0, s0);
FCOMI(x1, x2, 0, v0, s0, 1); //disable precise cmp
break;
case 0x50:
INST_NAME("VMOVMSPKPS Gd, Ex");
nextop = F8;
GETGD;
MOV32w(gd, 0);
if(MODREG) {
// EX is an xmm reg
q0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETEX(v0, 0, 0); } else { GETEY(v0); }
SQXTN_16(q0, v0); // reduces the 4 32bits to 4 16bits
VMOVQDto(x1, q0, 0);
LSRx(x1, x1, 15);
BFIx(gd, x1, 0+(l*4), 1);
LSRx(x1, x1, 16);
BFIx(gd, x1, 1+(l*4), 1);
LSRx(x1, x1, 16);
BFIx(gd, x1, 2+(l*4), 1);
LSRx(x1, x1, 16);
BFIx(gd, x1, 3+(l*4), 1);
}
} else {
// EX is memory
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, (0xfff<<3)-24, 7, rex, NULL, 0, 0);
for(int l=0; l<1+vex.l; ++l) {
LDRx_U12(x1, ed, fixedaddress+16*l);
LSRx(x1, x1, 31);
BFIx(gd, x1, 0+(l*4), 1);
LSRx(x1, x1, 32);
BFIx(gd, x1, 1+(l*4), 1);
LDRx_U12(x1, ed, fixedaddress+8+16*l);
LSRx(x1, x1, 31);
BFIx(gd, x1, 2+(l*4), 1);
LSRx(x1, x1, 32);
BFIx(gd, x1, 3+(l*4), 1);
}
}
break;
case 0x51:
INST_NAME("VSQRTPS Gx, Ex");
nextop = F8;
SKIPTEST(x1);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_EX(q0, q1, 0); } else { GETGY_empty_EY(q0, q1); }
VFSQRTQS(q0, q1);
}
if(!vex.l) YMM0(gd);
break;
case 0x52:
INST_NAME("VRSQRTPS Gx, Ex");
nextop = F8;
SKIPTEST(x1);
v0 = fpu_get_scratch(dyn, ninst);
VFMOVSQ_8(v0, 0b01110000); //1.0f
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_EX(q0, q1, 0); } else { GETGY_empty_EY(q0, q1); }
#if 0
// the aproximation doesn't not work on Death Stranding. code around 0x1419c9100 fail...
if(!l) {
if(q1==q0)
v1 = fpu_get_scratch(dyn, ninst);
else
v1 = q1;
}
// more precise
VFRSQRTEQS(v0, q1);
VFMULQS(v1, v0, q1);
VFRSQRTSQS(v1, v1, v0);
VFMULQS(q0, v1, v0);
#else
VFSQRTQS(q0, q1);
VFDIVQS(q0, v0, q0);
#endif
}
if(!vex.l) YMM0(gd);
break;
case 0x53:
INST_NAME("VRCPPS Gx, Ex");
nextop = F8;
SKIPTEST(x1);
q0 = fpu_get_scratch(dyn, ninst);
VFMOVSQ_8(q0, 0b01110000); //1.0f
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
GETGX_empty_EX(v0, v1, 0);
#if 0
if(v0==v1)
q1 = fpu_get_scratch(dyn, ninst);
#endif
} else {
GETGY_empty_EY(v0, v1);
}
#if 0
if(v0!=v1) q1 = v0;
VFRECPEQS(q0, v1);
VFRECPSQS(q1, q0, v1);
VFMULQS(v0, q0, q1);
#else
VFDIVQS(v0, q0, v1);
#endif
}
if(!vex.l) YMM0(gd);
break;
case 0x54:
INST_NAME("VANDPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VANDQ(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VANDQ(v0, v2, v1);
} else YMM0(gd)
break;
case 0x55:
INST_NAME("VANDNPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VBICQ(v0, v1, v2);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VBICQ(v0, v1, v2);
} else YMM0(gd)
break;
case 0x56:
INST_NAME("VORPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VORRQ(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VORRQ(v0, v2, v1);
} else YMM0(gd)
break;
case 0x57:
INST_NAME("VXORPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VEORQ(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VEORQ(v0, v2, v1);
} else YMM0(gd)
break;
case 0x58:
INST_NAME("VADDPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VFADDQS(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VFADDQS(v0, v2, v1);
} else YMM0(gd)
break;
case 0x59:
INST_NAME("VMULPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VFMULQS(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VFMULQS(v0, v2, v1);
} else YMM0(gd)
break;
case 0x5A:
INST_NAME("VCVTPS2PD Gx, Ex");
nextop = F8;
GETGX_empty_EX(v0, v1, 0);
if(vex.l) {
GETGY_empty(q0, -1, -1, -1);
FCVTL2(q0, v1);
} else YMM0(gd)
FCVTL(v0, v1);
break;
case 0x5B:
INST_NAME("VCVTDQ2PS Gx, Ex");
nextop = F8;
GETGX_empty_EX(v0, v1, 0);
SCVTQFS(v0, v1);
if(vex.l) {
GETGY_empty_EY(v0, v1);
SCVTQFS(v0, v1);
} else YMM0(gd)
break;
case 0x5C:
INST_NAME("VSUBPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VFSUBQS(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VFSUBQS(v0, v2, v1);
} else YMM0(gd)
break;
case 0x5D:
INST_NAME("VMINPS Gx, Vx, Ex");
nextop = F8;
if(!box64_dynarec_fastnan) {
q0 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
// FMIN/FMAX wll not copy a NaN if either is NaN
// but x86 will copy src2 if either value is NaN, so lets force a copy of Src2 (Ex) if result is NaN
VFMINQS(v0, v2, v1);
if(!box64_dynarec_fastnan && (v2!=v1)) {
VFCMEQQS(q0, v0, v0); // 0 is NaN, 1 is not NaN, so MASK for NaN
VBIFQ(v0, v1, q0); // copy dest where source is NaN
}
}
if(!vex.l) YMM0(gd);
break;
case 0x5E:
INST_NAME("VDIVPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VFDIVQS(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VFDIVQS(v0, v2, v1);
} else YMM0(gd)
break;
case 0x5F:
INST_NAME("VMAXPS Gx, Vx, Ex");
nextop = F8;
if(!box64_dynarec_fastnan) {
q0 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
// FMIN/FMAX wll not copy a NaN if either is NaN
// but x86 will copy src2 if either value is NaN, so lets force a copy of Src2 (Ex) if result is NaN
VFMAXQS(v0, v2, v1);
if(!box64_dynarec_fastnan && (v2!=v1)) {
VFCMEQQS(q0, v0, v0); // 0 is NaN, 1 is not NaN, so MASK for NaN
VBIFQ(v0, v1, q0); // copy dest where source is NaN
}
}
if(!vex.l) YMM0(gd);
break;
case 0x77:
if(!vex.l) {
INST_NAME("VZEROUPPER");
if(vex.v!=0) {
UDF(0);
} else {
for(int i=0; i<(rex.is32bits?8:16); ++i) {
YMM0(i);
}
}
} else {
INST_NAME("VZEROALL");
if(vex.v!=0) {
UDF(0);
} else {
for(int i=0; i<(rex.is32bits?8:16); ++i) {
v0 = sse_get_reg_empty(dyn, ninst, x1, i);
VEORQ(v0, v0, v0);
YMM0(i);
}
}
}
break;
case 0xAE:
nextop = F8;
if(MODREG) {
DEFAULT;
} else
switch((nextop>>3)&7) {
case 2:
INST_NAME("VLDMXCSR Md");
GETED(0);
STRw_U12(ed, xEmu, offsetof(x64emu_t, mxcsr));
if(box64_sse_flushto0) {
MRS_fpcr(x1); // get fpscr
LSRw_IMM(x3, ed, 15); // get FZ bit
BFIw(x1, x3, 24, 1); // inject FZ bit
EORw_REG_LSR(x3, x3, ed, 1); // FZ xor DAZ
BFIw(x1, x3, 1, 1); // inject AH bit
MSR_fpcr(x1); // put new fpscr
}
break;
case 3:
INST_NAME("VSTMXCSR Md");
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
LDRw_U12(x4, xEmu, offsetof(x64emu_t, mxcsr));
STW(x4, ed, fixedaddress);
break;
default:
DEFAULT;
}
break;
case 0xC2:
INST_NAME("VCMPPS Gx, Vx, Ex, Ib");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 1); u8 = F8; } else { GETGY_empty_VYEY(v0, v2, v1); }
if(((u8&15)==3) || ((u8&15)==7) || ((u8&15)==8) || ((u8&15)==9) || ((u8&15)==10) || ((u8&15)==12) || ((u8&15)==13) || ((u8&15)==14)) {
VFMAXQS(q0, v2, v1); // propagate NAN
VFCMEQQS(((u8&15)==7)?v0:q0, q0, q0); // 0 if NAN, 1 if not NAN
}
switch(u8&0xf) {
// the inversion of the params in the comparison is there to handle NaN the same way SSE does
case 0x00: VFCMEQQS(v0, v2, v1); break; // Equal, not unordered
case 0x01: VFCMGTQS(v0, v1, v2); break; // Less than
case 0x02: VFCMGEQS(v0, v1, v2); break; // Less or equal
case 0x03: VMVNQ(v0, q0); break; // unordered
case 0x04: VFCMEQQS(v0, v2, v1); VMVNQ(v0, v0); break; // Not Equal (or unordered on ARM, not on X86...)
case 0x05: VFCMGTQS(v0, v1, v2); VMVNQ(v0, v0); break; // Greater or equal or unordered
case 0x06: VFCMGEQS(v0, v1, v2); VMVNQ(v0, v0); break; // Greater or unordered
case 0x07: break; // ordered
case 0x08: VFCMEQQS(v0, v2, v1); VORNQ(v0, v0, q0); break; // Equal, or unordered
case 0x09: VFCMGTQS(v0, v1, v2); VORNQ(v0, v0, q0); break; // Less than or unordered
case 0x0a: VFCMGEQS(v0, v1, v2); VORNQ(v0, v0, q0); break; // Less or equal or unordered
case 0x0b: VEORQ(v0, v0, v0); break; // false
case 0x0c: VFCMEQQS(v0, v2, v1); VBICQ(v0, q0, v0); break;
case 0x0d: VFCMGEQS(v0, v2, v1); break;
case 0x0e: VFCMGTQS(v0, v2, v1); break;
case 0x0f: MOVIQ_64(v0, 0xff); break; //true
}
}
if(!vex.l) YMM0(gd);
break;
case 0xC6:
INST_NAME("VSHUFPS Gx, Vx, Ex, Ib");
nextop = F8;
GETVX(v2, 0);
if(!MODREG) {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
v1 = -1; // to avoid a warning
} else
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
GETGX_empty(v0);
u8 = F8;
if(v2==v1 && (u8&0x3)==((u8>>2)&3) && (u8&0xf)==((u8>>4)&0xf)) {
VDUPQ_32(v0, v2, u8&3);
} else if(v2==v1 && (u8==0xe0)) { // easy special case
VMOVQ(v0, v2);
VMOVeS(v0, 1, v0, 0);
} else if(v2==v1 && (u8==0xe5)) { // easy special case
VMOVQ(v0, v2);
VMOVeS(v0, 0, v0, 1);
} else if(MODREG && u8==0x88) {
VUZP1Q_32(v0, v2, v1);
} else if(MODREG && u8==0xdd) {
VUZP2Q_32(v0, v2, v1);
} else {
if((v0==v1) || (v0==v2)) {
d0 = fpu_get_scratch(dyn, ninst); s0 = 0;
} else {
d0 = v0; s0 = 1;
}
// first two elements from Vx
for(int i=0; i<2; ++i) {
VMOVeS(d0, i, v2, (u8>>(i*2))&3);
}
// second two from Ex
if(MODREG) {
for(int i=2; i<4; ++i) {
VMOVeS(d0, i, v1, (u8>>(i*2))&3);
}
} else {
SMREAD();
for(int i=2; i<4; ++i) {
ADDx_U12(x2, ed, ((u8>>(i*2))&3)*4);
VLD1_32(d0, i, x2);
}
}
if(v0!=d0) VMOVQ(v0, d0);
}
if(vex.l) {
if(MODREG)
v1 = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, gd, vex.v, -1);
GETGY_empty_VY(v0, v2, 0, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
if(v2==v1 && (u8&0x3)==((u8>>2)&3) && (u8&0xf)==((u8>>4)&0xf)) {
VDUPQ_32(v0, v2, u8&3);
} else if(v2==v1 && (u8==0xe0)) {
VMOVQ(v0, v2);
VMOVeS(v0, 1, v0, 0);
} else if(v2==v1 && (u8==0xe5)) {
VMOVQ(v0, v2);
VMOVeS(v0, 0, v0, 1);
} else if(MODREG && u8==0x88) {
VUZP1Q_32(v0, v2, v1);
} else if(MODREG && u8==0xdd) {
VUZP2Q_32(v0, v2, v1);
} else {
if(s0) d0 = v0;
for(int i=0; i<2; ++i) {
VMOVeS(d0, i, v2, (u8>>(i*2))&3);
}
if(MODREG) {
for(int i=2; i<4; ++i) {
VMOVeS(d0, i, v1, (u8>>(i*2))&3);
}
} else {
SMREAD();
for(int i=2; i<4; ++i) {
ADDx_U12(x2, ed, 16+((u8>>(i*2))&3)*4);
VLD1_32(d0, i, x2);
}
}
VMOVQ(v0, d0);
}
} else YMM0(gd);
break;
default:
DEFAULT;
}
return addr;
}
+161
View File
@@ -0,0 +1,161 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "my_cpuid.h"
#include "emu/x87emu_private.h"
#include "emu/x64shaext.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed, vd;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
rex_t rex = vex.rex;
switch(opcode) {
case 0xF2:
INST_NAME("ANDN Gd, Vd, Ed");
nextop = F8;
SETFLAGS(X_ALL, SF_SET);
GETGD;
GETED(0);
GETVD;
IFX(X_ZF)
BICSxw(gd, ed, vd);
else
BICxw(gd, ed, vd);
IFX(X_ZF) {
CSETw(x1, cEQ);
BFIw(xFlags, x1, F_ZF, 1);
}
IFX(X_OF)
BFCw(xFlags, F_OF, 1);
IFX(X_CF)
BFCw(xFlags, F_CF, 1);
IFX(X_SF) {
LSRxw_IMM(x1, gd, rex.w?63:31);
BFIw(xFlags, x1, F_SF, 1);
}
break;
case 0xF3:
nextop = F8;
switch((nextop>>3)&7) {
case 1:
INST_NAME("BLSR Vd, Ed");
SETFLAGS(X_ALL, SF_SET);
GETED(0);
GETVD;
IFX(X_CF) {
TSTxw_REG(ed, ed);
CSETMw(x3, cEQ);
BFIw(xFlags, x3, F_CF, 1);
}
SUBxw_U12(x3, ed, 1);
IFX(X_ZF)
ANDSxw_REG(vd, ed, x3);
else
ANDxw_REG(vd, ed, x3);
IFX(X_ZF) {
CSETMw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(x3, vd, rex.w?63:31);
BFIw(xFlags, x3, F_SF, 1);
}
IFX(X_OF) BFCw(xFlags, F_OF, 1);
if(box64_dynarec_test) {
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_PF) BFCw(xFlags, F_PF, 1);
}
break;
default:
DEFAULT;
}
break;
case 0xF5:
INST_NAME("BZHI Gd, Ed, Vd");
nextop = F8;
SETFLAGS(X_ALL, SF_SET);
GETGD;
GETED(0);
GETVD;
UXTBw(x1, vd);
CMPSw_U12(x1, rex.w?64:32);
CSETxw(x2, cPL);
IFX(F_CF) {
BFIw(xFlags, x2, F_CF, 1);
}
MVNxw_REG(x2, x2); //prepare mask
B_MARK(cPL);
LSLxw_REG(x2, x2, x1);
MARK;
IFX(X_ZF) {
BICSxw(gd, ed, x2);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1);
} else
BICxw(gd, ed, x2);
IFX(X_SF) {
LSRxw(x3, gd, rex.w?63:31);
BFIw(xFlags, x3, F_SF, 1);
}
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_PF) BFCw(xFlags, F_PF, 1);
IFX(X_OF) BFCw(xFlags, F_OF, 1);
break;
default:
DEFAULT;
}
return addr;
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,777 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "my_cpuid.h"
#include "emu/x87emu_private.h"
#include "emu/x64shaext.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_66_0F3A(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
#if STEP > 1
static const int8_t round_round[] = { 0, 2, 1, 3};
#endif
rex_t rex = vex.rex;
switch(opcode) {
case 0x00:
case 0x01:
if(opcode) {INST_NAME("VPERMPD Gx, Ex, Imm8");} else {INST_NAME("VPERMQ Gx, Ex, Imm8");}
nextop = F8;
GETGX_empty_EX(v0, q0, 1);
u8 = F8;
if(v0==q0) d0 = fpu_get_scratch(dyn, ninst);
if(v0==q0 || !MODREG) d1 = fpu_get_scratch(dyn, ninst);
q1 = d1;
GETGY_empty_EY(v1, q1);
if(v0==q0) { VMOVQ(d0, q0); VMOVQ(d1, q1); } else {d1 = q1; d0 = q0;}
VMOVeD(v0, 0, ((u8>>1)&1)?d1:d0, (u8>>0)&1);
VMOVeD(v0, 1, ((u8>>3)&1)?d1:d0, (u8>>2)&1);
VMOVeD(v1, 0, ((u8>>5)&1)?d1:d0, (u8>>4)&1);
VMOVeD(v1, 1, ((u8>>7)&1)?d1:d0, (u8>>6)&1);
break;
case 0x02:
INST_NAME("VPBLENDD Gx, Vx, Ex, u8");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 1); u8 = F8;} else { GETGY_empty_VYEY(v0, v2, v1); u8 >>=4;}
wb1 = 0; // mask
for(int i=0; i<4; ++i)
if(u8&(1<<i))
wb1 |= (3<<(i*2));
MOVI_64(q0, wb1); // load 8bits value as a 8bytes mask
SXTL_16(q0, q0); // expand 16bits to 32bits...
if(v0==v1) {
VBIFQ(v0, v2, q0);
} else {
if(v0!=v2) VMOVQ(v0, v2);
VBITQ(v0, v1, q0);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x04:
INST_NAME("VPERMILPS Gx, Ex, Imm8");
nextop = F8;
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
GETGX_empty_EX(v0, v1, 1);
u8 = F8;
if(v0==v1) {q1 = fpu_get_scratch(dyn, ninst); VMOVQ(q1, v1);}
} else {
GETGY_empty_EY(v0, v1);
if(v0==v1) {VMOVQ(q1, v1);}
}
if(u8==0x00 || u8==0x55 || u8==0xAA || u8==0xFF)
VDUPQ_32(v0, (v0==v1)?q1:v1, u8&3);
else if(u8==0x50)
VZIP1Q_32(v0, v1, v1);
else if(u8==0xFA)
VZIP2Q_32(v0, v1, v1);
else if(u8==0xA0)
VTRNQ1_32(v0, v1, v1);
else if(u8==0xF5)
VTRNQ2_32(v0, v1, v1);
else for(int i=0; i<4; ++i)
VMOVeS(v0, i, (v0==v1)?q1:v1, (u8>>(i*2))&3);
}
if(!vex.l) YMM0(gd);
break;
case 0x05:
INST_NAME("VPERMILD Gx, Ex, Imm8");
nextop = F8;
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
GETGX_empty_EX(v0, v1, 1);
u8 = F8;
if(v0==v1) {q1 = fpu_get_scratch(dyn, ninst); VMOVQ(q1, v1);}
} else {
GETGY_empty_EY(v0, v1);
if(v0==v1) {VMOVQ(q1, v1);}
}
if(((u8>>(l*2))&1)==((u8>>(1+l*2))&1))
VDUPQ_64(v0, (v0==v1)?q1:v1, ((u8>>(l*2))&1));
else for(int i=0; i<2; ++i)
VMOVeD(v0, i, (v0==v1)?q1:v1, (u8>>(i+l*2))&1);
}
if(!vex.l) YMM0(gd);
break;
case 0x06:
case 0x46:
if(opcode==0x06) { INST_NAME("VPERM2F128 Gx, Vx, Ex, Imm8"); } else { INST_NAME("VPERM2I128 Gx, Vx, Ex, Imm8"); }
nextop = F8;
if(!vex.l) UDF(0);
if(MODREG) {
s0 = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg(dyn, ninst, x1, s0, 0);
} else {
s0 = -1;
v1 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
}
u8 = F8;
GETVX(v2, 0);
GETGX_empty(v0);
if((v0==v2) && ((u8&0xf0)==0)) {
q0 = fpu_get_scratch(dyn, ninst);
VMOVQ(q0, v2);
v2 = q0;
}
if((v0==v1) && ((u8&0xf0)==0x20)) {
q1 = fpu_get_scratch(dyn, ninst);
VMOVQ(q1, v1);
v1 = q1;
}
switch(u8&0x0f) {
case 0: if(v0!=v2) VMOVQ(v0, v2); break;
case 1: d2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, s0, -1); VMOVQ(v0, d2); break;
case 2: if(MODREG) { if(v0!=v1) VMOVQ(v0, v1); } else { VLDR128_U12(v0, ed, fixedaddress); } break;
case 3: if(MODREG) { d1 = ymm_get_reg(dyn, ninst, x1, s0, 0, gd, vex.v, -1); VMOVQ(v0, d1); } else { VLDR128_U12(v0, ed, fixedaddress+16); } break;
default: VEORQ(v0, v0, v0);
}
if((u8&0xf0)==0x10) { if((u8&0x0f)!=1) d2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, s0, -1); }
if(MODREG && ((u8&0xf0)==0x30)) { if((u8&0x0f)!=3) d1 = ymm_get_reg(dyn, ninst, x1, s0, 0, gd, vex.v, -1); }
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, vex.v, s0, -1);
switch((u8>>4)&0x0f) {
case 0: VMOVQ(v0, v2); break;
case 1: if(v0!=d2) VMOVQ(v0, d2); break;
case 2: if(MODREG) { if(v0!=v1) VMOVQ(v0, v1); } else { VLDR128_U12(v0, ed, fixedaddress); } break;
case 3: if(MODREG) { if(v0!=d1) VMOVQ(v0, d1); } else { VLDR128_U12(v0, ed, fixedaddress+16); } break;
default: VEORQ(v0, v0, v0);
}
break;
case 0x08:
INST_NAME("VROUNDPS Gx, Ex, Ib");
nextop = F8;
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_EX(v0, v1, 1); u8 = F8; } else { GETGY_empty_EY(v0, v1); }
if(u8&4) {
if(!l) wb1 = sse_setround(dyn, ninst, x1, x2, x4);
VFRINTISQ(v0, v1);
if(l || !vex.l) x87_restoreround(dyn, ninst, wb1);
} else {
VFRINTRSQ(v0, v1, round_round[u8&3]);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x09:
INST_NAME("VROUNDPD Gx, Ex, Ib");
nextop = F8;
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_EX(v0, v1, 1); u8 = F8; } else { GETGY_empty_EY(v0, v1); }
if(u8&4) {
if(!l) wb1 = sse_setround(dyn, ninst, x1, x2, x4);
VFRINTIDQ(v0, v1);
if(l || !vex.l) x87_restoreround(dyn, ninst, wb1);
} else {
VFRINTRDQ(v0, v1, round_round[u8&3]);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x0A:
INST_NAME("VROUNDSS Gx, Vx, Ex, Ib");
nextop = F8;
GETEXSS(v1, 0, 1);
GETGX_empty_VX(v0, v2);
u8 = F8;
d1 = fpu_get_scratch(dyn, ninst);
if(u8&4) {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
FRINTXS(d1, v1);
x87_restoreround(dyn, ninst, u8);
} else {
FRINTRRS(d1, v1, round_round[u8&3]);
}
if(v0!=v2) VMOVQ(v0, v2);
VMOVeS(v0, 0, d1, 0);
YMM0(gd);
break;
case 0x0B:
INST_NAME("VROUNDSD Gx, Vx, Ex, Ib");
nextop = F8;
GETEXSD(v1, 0, 1);
GETGX_empty_VX(v0, v2);
u8 = F8;
d1 = fpu_get_scratch(dyn, ninst);
if(u8&4) {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
FRINTXD(d1, v1);
x87_restoreround(dyn, ninst, u8);
} else {
FRINTRRD(d1, v1, round_round[u8&3]);
}
if(v0!=v2) VMOVQ(v0, v2);
VMOVeD(v0, 0, d1, 0);
YMM0(gd);
break;
case 0x0C:
INST_NAME("VBLENDPS Gx, Vx, Ex, Ib");
nextop = F8;
GETGX_empty_VXEX(q0, q2, q1, 1);
u8 = F8;
if((u8&0xf)==0xf) {
if(q0!=q1) VMOVQ(q0, q1);
} else if(q0==q1) {
for(int i=0; i<4; ++i)
if(u8&(1<<i)) {
VMOVeS(q0, i, q1, i);
} else if(q0!=q2)
VMOVeS(q0, i, q2, i);
} else {
if(q0!=q2)
VMOVQ(q0, q2);
if((u8&15)==0b0011) {
VMOVeD(q0, 0, q1, 0);
} else if((u8&15)==0b1100) {
VMOVeD(q0, 1, q1, 1);
} else for(int i=0; i<4; ++i)
if(u8&(1<<i)) {
VMOVeS(q0, i, q1, i);
}
}
if(vex.l) {
GETGY_empty_VYEY(q0, q2, q1);
if((u8&0xf0)==0xf0) {
if(q0!=q1) VMOVQ(q0, q1);
} else if(q0==q1) {
for(int i=0; i<4; ++i)
if(u8&(1<<(i+4))) {
VMOVeS(q0, i, q1, i);
} else if(q0!=q2)
VMOVeS(q0, i, q2, i);
} else {
if(q0!=q2)
VMOVQ(q0, q2);
if((u8>>4)==0b0011) {
VMOVeD(q0, 0, q1, 0);
} else if((u8>>4)==0b1100) {
VMOVeD(q0, 1, q1, 1);
} else for(int i=0; i<4; ++i)
if(u8&(1<<(i+4))) {
VMOVeS(q0, i, q1, i);
}
}
} else YMM0(gd);
break;
case 0x0D:
INST_NAME("VPBLENDPD Gx, Vx, Ex, Ib");
nextop = F8;
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(q0, q2, q1, 1); u8 = F8; } else { GETGY_empty_VYEY(q0, q2, q1); }
switch(u8>>(l*2)&3) {
case 0b00: if(q0!=q2) VMOVQ(q0, q2); break; // VxVx
case 0b01: if(q0!=q1) VMOVeD(q0, 0, q1, 0); if(q0!=q2) VMOVeD(q0, 1, q2, 1); break; // Ex[0]Vx[1]
case 0b10: if(q0!=q2) VMOVeD(q0, 0, q2, 0); if(q0!=q1) VMOVeD(q0, 1, q1, 1); break; // Vx[0]Ex[1]
case 0b11: if(q0!=q1) VMOVQ(q0, q1); break; // ExEx
}
}
if(!vex.l) YMM0(gd);
break;
case 0x0E:
INST_NAME("VPBLENDW Gx, Vx, Ex, u8");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 1); u8 = F8;} else { GETGY_empty_VYEY(v0, v2, v1); }
if(!l) {
MOVI_64(q0, u8);
SXTL_8(q0, q0); // expand 8bits to 16bits...
}
if(v0==v1) {
VBIFQ(v0, v2, q0);
} else {
if(v0!=v2) VMOVQ(v0, v2);
VBITQ(v0, v1, q0);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x0F:
INST_NAME("VPALIGNR Gx, Vx, Ex, Ib");
nextop = F8;
d0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
GETGX_empty_VXEX(v0, v2, v1, 1);
u8 = F8;
} else {
GETGY_empty_VYEY(v0, v2, v1);
}
if(u8>31) {
VEORQ(v0, v0, v0);
} else if(u8>15) {
if(!l) VEORQ(d0, d0, d0);
VEXTQ_8(v0, v2, d0, u8-16);
} else {
VEXTQ_8(v0, v1, v2, u8);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x14:
INST_NAME("VPEXTRB Ed, Gx, imm8");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff, 0, rex, NULL, 0, 1);
ed = x1;
}
u8 = F8;
VMOVBto(ed, v0, u8&0x0f);
if(!MODREG) {
STB(ed, wback, fixedaddress);
}
break;
case 0x15:
INST_NAME("VPEXTRW Ed, Gx, imm8");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 1);
ed = x1;
}
u8 = F8;
VMOVHto(ed, v0, u8&7);
if(!MODREG) {
STH(ed, wback, fixedaddress);
}
break;
case 0x16:
INST_NAME("VPEXTRD/Q Ed, Gx, imm8");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
ed = x1;
}
u8 = F8;
if(rex.w) {
VMOVQDto(ed, v0, u8&1);
} else {
VMOVSto(ed, v0, u8&3);
}
if(!MODREG) {
STxw(ed, wback, fixedaddress);
}
break;
case 0x17:
INST_NAME("VEXTRACTPS Ed, Gx, imm8");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 1);
ed = x1;
}
u8 = F8;
VMOVSto(ed, v0, u8&3);
if(!MODREG) {
STW(ed, wback, fixedaddress);
}
break;
case 0x18:
case 0x38:
if(opcode==0x18) {INST_NAME("VINSERTF128 Gx, Vx, Ex, imm8");} else {INST_NAME("VINSERTI128 Gx, Vx, Ex, imm8");}
nextop = F8;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 1);
v1 = -1; // to avoid a warning
}
u8 = F8;
GETVX(v2, 0);
GETGX_empty(v0);
if(v0==v2 && u8==1) {
GETGY_empty(q0, 0, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
q2 = q0;
} else {
GETGY_empty_VY(q0, q2, 0, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
}
if(MODREG)
VMOVQ((u8&1)?q0:v0, v1);
else
VLD128((u8&1)?q0:v0, ed, fixedaddress);
if(v0!=v2)
VMOVQ((u8&1)?v0:q0, (u8&1)?v2:q2);
break;
case 0x19:
case 0x39:
if(opcode==0x19) {INST_NAME("VEXTRACTF128 Ex, Gx, imm8");} else {INST_NAME("VEXTRACTI128 Ex, Gx, imm8");}
nextop = F8;
u8 = geted_ib(dyn, addr, ninst, nextop);
GETGX(v0, 0);
if(u8&1) {GETGY(v0, ((nextop&7)+(rex.b<<3)==gd && MODREG)?1:0, -1, -1, -1);}
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOVQ(v1, v0);
if((nextop&7)+(rex.b<<3)==gd && (u8&1))
VEORQ(v0, v0, v0); // special case like vextractf128 xmm3, ymm3, 0x01
else
YMM0((nextop&7)+(rex.b<<3));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 1);
VST128(v0, ed, fixedaddress);
}
F8; // read u8, but it's been already handled
break;
case 0x1D:
INST_NAME("VCVTPS2PH Ex, Gx");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x3, (nextop&7)+(rex.b<<3));
} else {
v1 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, &unscaled, 0xfff<<(3+vex.l), vex.l?15:7, rex, NULL, 0, 1);
}
if(vex.l && v0==v1) {
q0 = fpu_get_scratch(dyn, ninst);
VMOVQ(q0, v0);
v0 = q0;
}
u8 = F8;
if(u8&4) {
s0 = sse_setround(dyn, ninst, x1, x2, x6);
} else {
u8&=3;
if(u8==1) u8=2;
else if(u8==2) u8=1;
MRS_fpcr(x1); // get fpscr
MOV32w(x2, u8);
MOVx_REG(x6, x1);
BFIx(x1, x2, 22, 2); // inject new round
MSR_fpcr(x1); // put new fpscr
s0 = x6;
}
FCVTN16(v1, v0);
if(vex.l) {
GETGY(v0, 0, MODREG?((nextop&7)+(rex.b<<3)):-1, -1,-1);
FCVTN162(v1, v0);
}
x87_restoreround(dyn, ninst, s0);
if(MODREG) {
YMM0((nextop&7)+(rex.b<<3));
} else {
if(vex.l) {
VST128(v1, ed, fixedaddress);
} else {
VST64(v1, ed, fixedaddress);
}
SMWRITE2();
}
break;
case 0x20:
INST_NAME("VINSERTD Gx, Vx, Ex, Ib");
nextop = F8;
GETGX_empty_VX(v0, v2);
GETED(1);
u8 = F8;
if(v0!=v2) VMOVQ(v0, v2);
VMOVQBfrom(v0, u8&0xf, ed);
YMM0(gd);
break;
case 0x21:
INST_NAME("VINSERTPS Gx, Vx, Ex, Ib");
nextop = F8;
if (MODREG) {
GETGX_empty_VXEX(v0, v2, v1, 1);
u8 = F8;
if(v0==v1) {
d0 = fpu_get_scratch(dyn, ninst);
VMOVQ(d0, v1);
if(v0!=v2) VMOVQ(v0, v2);
VMOVeS(v0, (u8>>4)&3, d0, (u8>>6)&3);
} else {
if(v0!=v2) VMOVQ(v0, v2);
VMOVeS(v0, (u8>>4)&3, v1, (u8>>6)&3);
}
} else {
GETGX_empty_VX(v0, v2);
if(v0!=v2) VMOVQ(v0, v2);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 1);
u8 = F8;
LDW(x2, wback, fixedaddress);
VMOVQSfrom(v0, (u8>>4)&3, x2);
}
uint8_t zmask = u8 & 0xf;
for (uint8_t i=0; i<4; i++) {
if (zmask & (1<<i)) {
VMOVQSfrom(v0, i, wZR);
}
}
YMM0(gd);
break;
case 0x22:
INST_NAME("VINSERTD Gx, Vx, Ex, Ib");
nextop = F8;
GETGX_empty_VX(v0, v2);
GETED(1);
u8 = F8;
if(v0!=v2) VMOVQ(v0, v2);
if(rex.w)
VMOVQDfrom(v0, u8&1, ed);
else
VMOVQSfrom(v0, u8&3, ed);
YMM0(gd);
break;
case 0x40:
INST_NAME("VDPPS Gx, Vx, Ex, Ib");
nextop = F8;
u8 = geted_ib(dyn, addr, ninst, nextop);
q0 = fpu_get_scratch(dyn, ninst);
// first mask
wb1 = 0; // mask
for(int i=0; i<4; ++i)
if(u8&(1<<i))
wb1 |= (3<<(i*2));
MOVI_64(q0, wb1); // load 8bits value as a 8bytes mask
SXTL_16(q0, q0); // expand 16bits to 32bits...
q1 = fpu_get_scratch(dyn, ninst);
// second mask
wb1 = 0; // mask
for(int i=0; i<4; ++i)
if((u8>>4)&(1<<i))
wb1 |= (3<<(i*2));
MOVI_64(q1, wb1); // load 8bits value as a 8bytes mask
SXTL_16(q1, q1); // expand 16bits to 32bits...
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 1); u8 = F8; } else { GETGY_empty_VYEY(v0, v2, v1); }
VFMULQS(v0, v2, v1);
VANDQ(v0, v0, q1); // second mask
VFADDPQS(v0, v0, v0);
FADDPS(v0, v0);
VDUPQ_32(v0, v0, 0);
VANDQ(v0, v0, q0); // first mask
}
if(!vex.l) YMM0(gd);
break;
case 0x44:
INST_NAME("PCLMULQDQ Gx, Vx, Ex, Ib");
nextop = F8;
if(arm64_pmull) {
d0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
GETGX_empty_VXEX(v0, v2, v1, 1);
u8 = F8;
} else {
GETGY_empty_VYEY(v0, v2, v1);
}
switch (u8&0b00010001) {
case 0b00000000:
PMULL_128(v0, v2, v1);
break;
case 0b00010001:
PMULL2_128(v0, v2, v1);
break;
case 0b00000001:
VEXTQ_8(d0, v2, v2, 8); // Swap Up/Lower 64bits parts
PMULL_128(v0, d0, v1);
break;
case 0b00010000:
VEXTQ_8(d0, v2, v2, 8); // Swap Up/Lower 64bits parts
PMULL2_128(v0, d0, v1);
break;
}
}
} else {
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
GETG;
sse_forget_reg(dyn, ninst, gd);
sse_reflect_reg(dyn, ninst, vex.v);
}
MOV32w(x1, gd); // gx
MOV32w(x2, vex.v); // vx
if(MODREG) {
if(!l) {
ed = (nextop&7)+(rex.b<<3);
sse_forget_reg(dyn, ninst, ed);
}
MOV32w(x3, ed);
} else {
if(!l) {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
if(ed!=x3) {
MOVx_REG(x3, ed);
}
} else {
ADDx_U12(x3, ed, 16);
}
}
if(!l) u8 = F8;
MOV32w(x4, u8);
CALL_(l?native_pclmul_y:native_pclmul_x, -1, x3);
}
}
if(!vex.l) YMM0(gd);
break;
//case 0x46: // see 0x06
case 0x4A:
INST_NAME("VBLENDVPS Gx, Vx, Ex, XMMImm8");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
u8 = geted_ib(dyn, addr, ninst, nextop)>>4;
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
q1 = sse_get_reg(dyn, ninst, x1, u8, 0);
GETGX_empty_VXEX(v0, v2, v1, 1);
F8;
} else {
v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, u8, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
if(MODREG)
v1 = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, gd, vex.v, u8);
else
VLDR128_U12(v1, ed, fixedaddress+16);
q1 = ymm_get_reg(dyn, ninst, x1, u8, 0, vex.v, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, vex.v, u8, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
}
VSSHRQ_32(q0, q1, 31); // create mask
if(v0==v1)
VBIFQ(v0, v2, q0);
else {
if(v0!=v2) VMOVQ(v0, v2);
VBITQ(v0, v1, q0);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x4B:
INST_NAME("VBLENDVPD Gx, Vx, Ex, XMMImm8");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
u8 = geted_ib(dyn, addr, ninst, nextop)>>4;
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
q1 = sse_get_reg(dyn, ninst, x1, u8, 0);
GETGX_empty_VXEX(v0, v2, v1, 1);
F8;
} else {
v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, u8, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
if(MODREG)
v1 = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, gd, vex.v, u8);
else
VLDR128_U12(v1, ed, fixedaddress+16);
q1 = ymm_get_reg(dyn, ninst, x1, u8, 0, vex.v, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, vex.v, u8, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
}
VSSHRQ_64(q0, q1, 63); // create mask
if(v0==v1)
VBIFQ(v0, v2, q0);
else {
if(v0!=v2) VMOVQ(v0, v2);
VBITQ(v0, v1, q0);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x4C:
INST_NAME("VBLENDPVB Gx, Vx, Ex, XMMImm8");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
u8 = geted_ib(dyn, addr, ninst, nextop)>>4;
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
q1 = sse_get_reg(dyn, ninst, x1, u8, 0);
GETGX_empty_VXEX(v0, v2, v1, 1);
F8;
} else {
v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, u8, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
if(MODREG)
v1 = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, gd, vex.v, u8);
else
VLDR128_U12(v1, ed, fixedaddress+16);
q1 = ymm_get_reg(dyn, ninst, x1, u8, 0, vex.v, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, vex.v, u8, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
}
VSSHRQ_8(q0, q1, 7); // create mask
if(v0==v1)
VBIFQ(v0, v2, q0);
else {
if(v0!=v2) VMOVQ(v0, v2);
VBITQ(v0, v1, q0);
}
}
if(!vex.l) YMM0(gd);
break;
default:
DEFAULT;
}
return addr;
}
+483
View File
@@ -0,0 +1,483 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "my_cpuid.h"
#include "emu/x87emu_private.h"
#include "emu/x64shaext.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed, vd;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u, u64;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
rex_t rex = vex.rex;
switch(opcode) {
case 0x10:
INST_NAME("VMOVSD Gx, [Vx,] Ex");
nextop = F8;
GETG;
if(MODREG) {
GETGX_empty_VXEX(v0, v2, v1, 0);
if(v0!=v1) VMOVeD(v0, 0, v1, 0);
if(v0!=v2) VMOVeD(v0, 1, v2, 1);
} else {
SMREAD();
GETGX_empty(v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v0, ed, fixedaddress); // upper part reseted
}
YMM0(gd);
break;
case 0x11:
INST_NAME("VMOVSD Ex, Vx, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
GETVXEX(v2, 0, v1, 1, 0);
if(v0!=v1) VMOVeD(v1, 0, v0, 0);
if(v1!=v2) VMOVeD(v1, 1, v2, 1);
YMM0((nextop&7)+(rex.b<<3));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v0, ed, fixedaddress);
SMWRITE2();
}
break;
case 0x12:
INST_NAME("VMOVDDUP Gx, Ex");
nextop = F8;
GETG;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
GETGX_empty(v0);
VDUPQ_64(v0, v1, 0);
if(vex.l) {
GETGY_empty_EY(v0, v1);
VDUPQ_64(v0, v1, 0);
}
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VLDQ1R_64(v0, ed);
if(vex.l) {
GETGY_empty(v0, -1, -1, -1);
ADDx_U12(x3, ed, 16);
VLDQ1R_64(v0, ed);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x2A:
INST_NAME("VCVTSI2SD Gx, Vx, Ed");
nextop = F8;
GETGX_empty_VX(v0, v1);
GETED(0);
d1 = fpu_get_scratch(dyn, ninst);
if(rex.w) {
SCVTFDx(d1, ed);
} else {
SCVTFDw(d1, ed);
}
if(v0!=v1) VMOVQ(v0, v1);
VMOVeD(v0, 0, d1, 0);
YMM0(gd);
break;
case 0x2C:
INST_NAME("VCVTTSD2SI Gd, Ex");
nextop = F8;
GETGD;
GETEXSD(q0, 0, 0);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
}
FCVTZSxwD(gd, q0);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
ORRx_mask(gd, xZR, 1, 1, 0); //0x8000000000000000
} else {
MOV32w(gd, 0x80000000);
}
}
break;
case 0x2D:
INST_NAME("VCVTSD2SI Gd, Ex");
nextop = F8;
GETGD;
GETEXSD(q0, 0, 0);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
}
u8 = sse_setround(dyn, ninst, x1, x2, x3);
d1 = fpu_get_scratch(dyn, ninst);
FRINTID(d1, q0);
x87_restoreround(dyn, ninst, u8);
FCVTZSxwD(gd, d1);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
ORRx_mask(gd, xZR, 1, 1, 0); //0x8000000000000000
} else {
MOV32w(gd, 0x80000000);
}
}
break;
case 0x51:
INST_NAME("VSQRTSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
if(!box64_dynarec_fastnan) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FCMEQD(q0, v1, v1); // 0 if NAN, 1 if not NAN
}
FSQRTD(d1, v1);
if(!box64_dynarec_fastnan) {
FCMEQD(q1, d1, d1); // 0 => out is NAN
VBIC(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
VORR(d1, d1, q1); // NAN -> -NAN
}
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x58:
INST_NAME("VADDSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FADDD(d1, v2, v1);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x59:
INST_NAME("VMULSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FMULD(d1, v2, v1);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x5A:
INST_NAME("VCVTSD2SS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FCVT_S_D(d1, v1);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeS(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x5C:
INST_NAME("VSUBSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FSUBD(d1, v2, v1);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x5D:
INST_NAME("VMINSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
// VMINSD: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
FCMPD(v2, v1);
FCSELD(d1, v1, v2, cCS);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0); // to not erase uper part
YMM0(gd)
break;
case 0x5E:
INST_NAME("VDIVSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
if(!box64_dynarec_fastnan) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(q0, v2, v1); // propagate NAN
FCMEQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
FDIVD(d1, v2, v1);
if(!box64_dynarec_fastnan) {
FCMEQD(q1, d1, d1); // 0 => out is NAN
VBIC(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
VORR(d1, d1, q1); // NAN -> -NAN
}
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x5F:
INST_NAME("VMAXSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FCMPD(v1, v2);
FCSELD(d1, v1, v2, cCS);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0); // to not erase uper part
YMM0(gd)
break;
case 0x70:
INST_NAME("VPSHUFLW Gx, Ex, Ib");
nextop = F8;
d0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETEX(v1, 0, 1); GETGX(v0, 1); u8 = F8; } else { GETGY(v0, 1, MODREG?((nextop&7)+(rex.b<<3)):-1, -1, -1); GETEY(v1); }
if(u8==0b00000000 || u8==0b01010101 || u8==0b10101010 || u8==0b11111111) {
if(v0==v1) {
VMOVQ(d0, v1);
}
VDUP_16(v0, v1, u8&3);
if(v0==v1)
v1 = d0;
} else {
// only low part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
if(!l) {
u64 = 0;
for (int i=0; i<4; ++i) {
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+0)<<(i*16+0);
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+1)<<(i*16+8);
}
MOV64x(x2, u64);
}
VMOVQDfrom(d0, 0, x2);
VTBL1_8(d0, v1, d0);
VMOVeD(v0, 0, d0, 0);
}
if(v0!=v1) {
VMOVeD(v0, 1, v1, 1);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x7C:
INST_NAME("VHADDPS Gx, Vx, Ex");
nextop = F8;
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
VFADDPQS(v0, v2, v1);
}
if(!vex.l) YMM0(gd);
break;
case 0xC2:
INST_NAME("CMPSD Gx, Ex, Ib");
nextop = F8;
GETEXSD(v1, 0, 1);
GETGX_empty_VX(v0, v2);
u8 = F8;
FCMPD(v2, v1);
if(v0!=v2) VMOVQ(v0, v2);
switch(u8&7) {
case 0: CSETMx(x2, cEQ); break; // Equal
case 1: CSETMx(x2, cCC); break; // Less than
case 2: CSETMx(x2, cLS); break; // Less or equal
case 3: CSETMx(x2, cVS); break; // NaN
case 4: CSETMx(x2, cNE); break; // Not Equal or unordered
case 5: CSETMx(x2, cCS); break; // Greater or equal or unordered
case 6: CSETMx(x2, cHI); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
case 7: CSETMx(x2, cVC); break; // not NaN
}
VMOVQDfrom(v0, 0, x2);
YMM0(gd);
break;
case 0xD0:
INST_NAME("VADDSUBPS Gx, Vx, Ex");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
static float addsubps[4] = {-1.f, 1.f, -1.f, 1.f};
MAYUSE(addsubps);
TABLE64(x2, (uintptr_t)&addsubps);
VLDR128_U12(q0, x2, 0);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); if(v0==v1) q1 = fpu_get_scratch(dyn, ninst); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(v0==v1) {
VFMULQS(q1, v1, q0);
VFADDQS(v0, v2, q1);
} else {
if(v0!=v2) VMOVQ(v0, v2);
VFMLAQS(v0, v1, q0);
}
}
if(!vex.l) YMM0(gd);
break;
case 0xE6:
INST_NAME("VCVTPD2DQ Gx, Ex");
nextop = F8;
u8 = sse_setround(dyn, ninst, x1, x2, x6);
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
GETEX_Y(v1, 0, 0);
GETGX_empty(v0);
if(!box64_dynarec_fastround || vex.l)
d0 = fpu_get_scratch(dyn, ninst);
} else {
GETEY(v1);
}
if(box64_dynarec_fastround) {
VFRINTIDQ(l?d0:v0, v1);
VFCVTNSQD(l?d0:v0, l?d0:v0); // convert double -> int64
if(!l)
SQXTN_32(v0, v0); // convert int64 -> int32 with saturation in lower part, RaZ high part
else
SQXTN2_32(v0, d0); // convert int64 -> int32 with saturation in higher part
} else {
if(!l) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
ORRw_mask(x4, xZR, 1, 0); //0x80000000
}
for(int i=0; i<2; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
if(i) {
VMOVeD(d0, 0, v1, i);
FRINTID(d0, d0);
} else {
FRINTID(d0, v1);
}
FCVTZSwD(x1, d0);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TSTw_mask(x5, 0, 0); // mask = 1 = FPSR_IOC
CSELx(x1, x1, x4, cEQ);
VMOVQSfrom(v0, i+l*2, x1);
}
if(!vex.l && !l) VMOVQDfrom(v0, 1, xZR);
}
}
x87_restoreround(dyn, ninst, u8);
YMM0(gd);
break;
case 0xF0:
INST_NAME("LDDQU Gx,Ex");
nextop = F8;
GETG;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
if(vex.l) {
GETGY_empty_EY(v0, v1);
VMOVQ(v0, v1);
}
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xffe<<4, 7, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, -1, -1, -1);
VLDR128_U12(v0, ed, fixedaddress+16);
}
if(!vex.l) YMM0(gd);
break;
default:
DEFAULT;
}
return addr;
}
@@ -0,0 +1,96 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "my_cpuid.h"
#include "emu/x87emu_private.h"
#include "emu/x64shaext.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_F2_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed, vd;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
rex_t rex = vex.rex;
switch(opcode) {
case 0xF6:
INST_NAME("MULX Gd, Vd, Ed (,RDX)");
nextop = F8;
GETGD;
GETED(0);
GETVD;
if(rex.w) {
// 64bits mul
UMULH(x3, xRDX, ed);
MULx(vd, xRDX, ed);
MOVx_REG(gd, x3);
} else {
// 32bits mul
UMULL(x3, xRDX, ed);
MOVw_REG(vd, x3);
LSRx(gd, x3, 32);
}
break;
case 0xF7:
INST_NAME("SHRX Gd, Ed, Vd");
nextop = F8;
GETGD;
GETED(0);
GETVD;
ANDx_mask(x3, vd, 1, 0, rex.w?5:4); // mask 0x3f/0x1f
LSRxw_REG(gd, ed, x3);
break;
default:
DEFAULT;
}
return addr;
}
@@ -0,0 +1,78 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "my_cpuid.h"
#include "emu/x87emu_private.h"
#include "emu/x64shaext.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_F2_0F3A(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed, vd;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
rex_t rex = vex.rex;
switch(opcode) {
case 0xF0:
INST_NAME("RORX Gd, Ed, Ib");
nextop = F8;
GETGD;
GETED(1);
u8 = F8;
u8&=rex.w?0x3f:0x1f;
RORxw(gd, ed, u8);
break;
default:
DEFAULT;
}
return addr;
}
+519
View File
@@ -0,0 +1,519 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "my_cpuid.h"
#include "emu/x87emu_private.h"
#include "emu/x64shaext.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed, vd;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u, u64;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
rex_t rex = vex.rex;
switch(opcode) {
case 0x10:
INST_NAME("VMOVSS Gx, Ex [,Vx]");
nextop = F8;
GETG;
if(MODREG) {
GETGX_empty_VXEX(v0, v2, v1, 0);
if((v0!=v2) && (v0!=v1)) VMOVQ(v0, v2);
if(v0!=v1) VMOVeS(v0, 0, v1, 0);
if((v0!=v2) && (v0==v1)) { VMOVeS(v0, 1, v2, 1); VMOVeD(v0, 1, v2, 1);}
} else {
GETGX_empty(v0);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v0, ed, fixedaddress);
}
YMM0(gd);
break;
case 0x11:
INST_NAME("VMOVSS Ex, Gx [,Vx]");
nextop = F8;
GETG;
if(MODREG) {
GETGXVXEX_empty(v0, v2, v1, 0);
if((v2!=v1) && (v2!=v0)) VMOVQ(v2, v1);
if(v2!=v0) VMOVeS(v2, 0, v0, 0);
if((v2!=v1) && (v2==v0)) { VMOVeS(v2, 1, v0, 1); VMOVeD(v2, 1, v0, 1);}
YMM0((nextop&7)+(rex.b<<3));
} else {
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VST32(v0, ed, fixedaddress);
SMWRITE2();
}
break;
case 0x12:
INST_NAME("VMOVSLDUP Gx, Ex");
nextop = F8;
GETEX_Y(q1, 0, 0);
GETGX_empty(q0);
VTRNQ1_32(q0, q1, q1);
if(vex.l) {
GETGY_empty_EY(q0, q1);
VTRNQ1_32(q0, q1, q1);
} else YMM0(gd);
break;
case 0x16:
INST_NAME("MOVSHDUP Gx, Ex");
nextop = F8;
GETEX_Y(q1, 0, 0);
GETGX_empty(q0);
VTRNQ2_32(q0, q1, q1);
if(vex.l) {
GETGY_empty_EY(q0, q1);
VTRNQ2_32(q0, q1, q1);
} else YMM0(gd);
break;
case 0x2A:
INST_NAME("VCVTSI2SS Gx, Vx, Ed");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETGX_empty_VX(v0, v1);
GETED(0);
if(rex.w) {
SCVTFSx(d1, ed);
} else {
SCVTFSw(d1, ed);
}
if(v0!=v1) VMOVQ(v0, v1);
VMOVeS(v0, 0, d1, 0);
YMM0(gd);
break;
case 0x2C:
INST_NAME("VCVTTSS2SI Gd, Ex");
nextop = F8;
GETGD;
GETEXSS(d0, 0, 0);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
}
FCVTZSxwS(gd, d0);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
ORRx_mask(gd, xZR, 1, 1, 0); //0x8000000000000000
} else {
ORRw_mask(gd, xZR, 1, 0); //0x80000000
}
}
break;
case 0x2D:
INST_NAME("VCVTSS2SI Gd, Ex");
nextop = F8;
GETGD;
GETEXSS(q0, 0, 0);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
}
u8 = sse_setround(dyn, ninst, x1, x2, x3);
d1 = fpu_get_scratch(dyn, ninst);
FRINTIS(d1, q0);
x87_restoreround(dyn, ninst, u8);
FCVTZSxwS(gd, d1);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
ORRx_mask(gd, xZR, 1, 1, 0); //0x8000000000000000
} else {
ORRw_mask(gd, xZR, 1, 0); //0x80000000
}
}
break;
case 0x51:
INST_NAME("SQRTSS Gx, Ex");
nextop = F8;
GETEXSS(d0, 0, 0);
GETGX_empty_VX(v0, v2);
d1 = fpu_get_scratch(dyn, ninst);
FSQRTS(d1, d0);
if(v0!=v2) VMOVQ(v0, v2);
VMOVeS(v0, 0, d1, 0);
YMM0(gd);
break;
case 0x52:
INST_NAME("VRSQRTSS Gx, Vx Ex");
nextop = F8;
GETGX(v0, 1);
GETVX(v2, 0);
GETEXSS(v1, 0, 0);
d0 = fpu_get_scratch(dyn, ninst);
d1 = fpu_get_scratch(dyn, ninst);
// so here: F32: Imm8 = abcd efgh that gives => aBbbbbbc defgh000 00000000 00000000
// and want 1.0f = 0x3f800000
// so 00111111 10000000 00000000 00000000
// a = 0, b = 1, c = 1, d = 1, efgh=0
// 0b01110000
FMOVS_8(d0, 0b01110000);
FSQRTS(d1, v1);
FDIVS(d0, d0, d1);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeS(v0, 0, d0, 0);
YMM0(gd);
break;
case 0x53:
INST_NAME("VRCPSS Gx, Vx, Ex");
nextop = F8;
GETGX(v0, 1);
GETVX(v2, 0);
GETEXSS(v1, 0, 0);
d0 = fpu_get_scratch(dyn, ninst);
FMOVS_8(d0, 0b01110000); //1.0f
FDIVS(d0, d0, v1);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeS(v0, 0, d0, 0);
YMM0(gd);
break;
case 0x58:
INST_NAME("VADDSS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
if(v0!=v2) {
if(v0==v1) {
VMOV(d1, v1);
v1 = d1;
}
VMOVQ(v0, v2);
}
FADDS(d1, v0, v1);
VMOVeS(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x59:
INST_NAME("VMULSS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
if(v0!=v2) {
if(v0==v1) {
VMOV(d1, v1);
v1 = d1;
}
VMOVQ(v0, v2);
}
FMULS(d1, v0, v1);
VMOVeS(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x5A:
INST_NAME("VCVTSS2SD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
if(v0!=v2) {
if(v0==v1) {
VMOV(d1, v1);
v1 = d1;
}
VMOVQ(v0, v2);
}
FCVT_D_S(d1, v1);
VMOVeD(v0, 0, d1, 0);
YMM0(gd);
break;
case 0x5B:
INST_NAME("VCVTTPS2DQ Gx, Ex");
nextop = F8;
d0 = fpu_get_scratch(dyn, ninst);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5);
ORRw_mask(x4, xZR, 1, 0); //0x80000000
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_EX(v0, v1, 0); } else { GETGY_empty_EY(v0, v1); }
if(box64_dynarec_fastround) {
VFCVTZSQS(v0, v1);
} else {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
for(int i=0; i<4; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
VMOVeS(d0, 0, v1, i);
VFCVTZSs(d0, d0);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ(x5, FPSR_IOC, 4+4);
VMOVQSfrom(d0, 0, x4);
VMOVeS(v0, i, d0, 0);
}
}
}
if(!vex.l) YMM0(gd);
break;
case 0x5C:
INST_NAME("VSUBSS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FSUBS(d1, v2, v1);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeS(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x5D:
INST_NAME("VMINSS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FCMPS(v2, v1);
FCSELS(d1, v1, v2, cCS);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeS(v0, 0, d1, 0); // to not erase uper part
YMM0(gd)
break;
case 0x5E:
INST_NAME("VDIVSS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FDIVS(d1, v2, v1);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeS(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x5F:
INST_NAME("VMAXSS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FCMPS(v1, v2);
FCSELS(d1, v1, v2, cCS);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeS(v0, 0, d1, 0); // to not erase uper part
YMM0(gd)
break;
case 0x6F:
INST_NAME("VMOVDQU Gx, Ex");// no alignment constraint on NEON here, so same as MOVDQA
nextop = F8;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
GETGX_empty(v0);
VMOVQ(v0, v1);
if(vex.l) {
v1 = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, gd, -12, -1);
GETGY_empty(v0, (nextop&7)+(rex.b<<3), -1, -1);
VMOVQ(v0, v1);
}
} else {
GETGX_empty(v0);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
if(vex.l) {
GETGY_empty(v0, -1, -1, -1);
VLDR128_U12(v0, ed, fixedaddress+16);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x70:
INST_NAME("VPSHUFHW Gx, Ex, Ib");
nextop = F8;
d0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETEX(v1, 0, 1); GETGX(v0, 1); u8 = F8; } else { GETGY(v0, 1, MODREG?((nextop&7)+(rex.b<<3)):-1, -1, -1); GETEY(v1); }
if(u8==0b00000000 || u8==0b01010101 || u8==0b10101010 || u8==0b11111111) {
VDUP_16(d0, v1, 4+(u8&3));
} else {
// only high part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
if(!l) {
u64 = 0;
for (int i=0; i<4; ++i) {
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+8)<<(i*16+0);
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+9)<<(i*16+8);
}
MOV64x(x2, u64);
}
VMOVQDfrom(d0, 0, x2);
VTBL1_8(d0, v1, d0);
}
VMOVeD(v0, 1, d0, 0);
if(v0!=v1) {
VMOVeD(v0, 0, v1, 0);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x7E:
INST_NAME("MOVQ Gx, Ex");
nextop = F8;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
GETGX_empty(v0);
FMOVD(v0, v1);
} else {
GETGX_empty(v0);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v0, ed, fixedaddress);
}
YMM0(gd);
break;
case 0x7F:
INST_NAME("VMOVDQU Ex, Gx");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
VMOVQ(v1, v0);
if(vex.l) {
GETGY(v0, 0, (nextop&7) + (rex.b<<3), -1, -1);
v1 = ymm_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3), gd, -1, -1);
VMOVQ(v1, v0);
} // no ymm raz here it seems
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
if(vex.l) {
GETGY(v0, 0, -1, -1, -1);
VSTR128_U12(v0, ed, fixedaddress+16);
}
SMWRITE2();
}
break;
case 0xC2:
INST_NAME("VCMPSS Gx, Vx, Ex, Ib");
nextop = F8;
GETEXSS(v1, 0, 1);
GETGX_empty_VX(v0, v2);
u8 = F8;
if(((u8&15)!=11) && ((u8&15)!=15)) {
if((u8&15)>7)
FCMPS(v1, v2);
else
FCMPS(v2, v1);
}
// TODO: create a test for this one, there might be an issue with cases 9, 10 and 13
if(v0!=v2) VMOVQ(v0, v2);
switch(u8&15) {
case 0x00: CSETMw(x2, cEQ); break; // Equal
case 0x01: CSETMw(x2, cCC); break; // Less than
case 0x02: CSETMw(x2, cLS); break; // Less or equal
case 0x03: CSETMw(x2, cVS); break; // NaN
case 0x04: CSETMw(x2, cNE); break; // Not Equal or unordered
case 0x05: CSETMw(x2, cCS); break; // Greater or equal or unordered
case 0x06: CSETMw(x2, cHI); break; // Greater or unordered
case 0x07: CSETMw(x2, cVC); break; // not NaN
case 0x08: CSETMw(x2, cEQ); CSETMw(x3, cVS); ORRw_REG(x2, x2, x3); break; // Equal or unordered
case 0x09: CSETMw(x2, cHI); break; // Less than or unordered
case 0x0a: CSETMw(x2, cCS); break; // Less or equal or unordered
case 0x0b: MOV32w(x2, 0); break; // false
case 0x0c: CSETMw(x2, cNE); CSETMw(x3, cVS); BICw(x2, x2, x3); break; // Not Equal not unordered
case 0x0d: CSETMw(x2, cLS); break; // Greater or equal not unordered
case 0x0e: CSETMw(x2, cCC); break; // Greater not unordered
case 0x0f: MOV32w(x2, 0xffffffff); break; // true
}
VMOVQSfrom(v0, 0, x2);
YMM0(gd);
break;
case 0xE6:
INST_NAME("VCVTDQ2PD Gx, Ex");
nextop = F8;
if(vex.l) {
GETEX_Y(v1, 0, 0);
} else {
GETEXSD(v1, 0, 0);
}
GETGX_empty(v0);
d0 = fpu_get_scratch(dyn, ninst);
if(vex.l) {
q0 = ymm_get_reg_empty(dyn, ninst, x1, gd, -1, -1, -1);
SXTL2_32(q0, v1);
SCVTQFD(q0, q0);
} else YMM0(gd);
SXTL_32(v0, v1);
SCVTQFD(v0, v0);
break;
default:
DEFAULT;
}
return addr;
}
@@ -0,0 +1,78 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "my_cpuid.h"
#include "emu/x87emu_private.h"
#include "emu/x64shaext.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_F3_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed, vd;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
rex_t rex = vex.rex;
switch(opcode) {
case 0xF7:
INST_NAME("SARX Gd, Ed, Vd");
nextop = F8;
GETGD;
GETED(0);
GETVD;
ANDx_mask(x3, vd, 1, 0, rex.w?5:4); // mask 0x3f/0x1f
ASRxw_REG(gd, ed, x3);
break;
default:
DEFAULT;
}
return addr;
}
+13 -13
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -90,7 +90,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
break;
case 0xD8:
case 0xD9:
@@ -108,7 +108,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
@@ -187,7 +187,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0:
INST_NAME("FADD ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
@@ -200,7 +200,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 1:
INST_NAME("FMUL ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
@@ -213,7 +213,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 2:
INST_NAME("FCOM ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
@@ -222,12 +222,12 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FCVT_D_S(s0, s0);
FCMPD(v1, s0);
}
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
break;
case 3:
INST_NAME("FCOMP ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
@@ -236,13 +236,13 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FCVT_D_S(s0, s0);
FCMPD(v1, s0);
}
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, s0, ST_IS_F(0));
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FSUB ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
@@ -255,7 +255,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 5:
INST_NAME("FSUBR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
@@ -268,7 +268,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 6:
INST_NAME("FDIV ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
@@ -281,7 +281,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 7:
INST_NAME("FDIVR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
+17 -11
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -128,7 +128,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD_0(v1);
}
FCOM(x1, x2, x3); // same flags...
FCOM(x1, x2, x3, x4, 0, 0, ST_IS_F(0)); // same flags...
break;
case 0xE5:
INST_NAME("FXAM");
@@ -161,15 +161,21 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
ADDw_U12(x5, x5, i2);
}
ANDw_mask(x5, x5, 0, 3); // (emu->top + i)&7
ANDw_mask(x5, x5, 0, 2); // (emu->top + i)&7
}
// load tag
LDRH_U12(x3, xEmu, offsetof(x64emu_t, fpu_tags));
TSTw_mask(x3, 0, 1); // 0b11
B_MARK3(cNE); // empty: C3,C2,C0 = 101
// load x2 with ST0 anyway, for sign extraction
ADDx_REG_LSL(x1, xEmu, x5, 3);
LDRx_U12(x2, x1, offsetof(x64emu_t, x87));
// load tag
if(i2>=0) {
LDRH_U12(x3, xEmu, offsetof(x64emu_t, fpu_tags));
if(i2>0) {
ORRw_mask(x3, x3, 0b010000, 0b001111); // 0xffff0000
LSRw_IMM(x3, x3, i2*2);
}
TSTw_mask(x3, 0, 1); // 0b11
B_MARK3(cNE); // empty: C3,C2,C0 = 101
}
}
} else {
// simply move from cache reg to x2
@@ -288,7 +294,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
CALL(native_ftan, -1);
x87_unstackcount(dyn, ninst, x1, i1);
if(PK(0)==0xdd && PK(1)==0xd8) {
MESSAGE(LOG_DUMP, "Optimized next DD D8 fstp st0, st0, not emiting 1\n");
MESSAGE(LOG_DUMP, "Optimized next DD D8 fstp st0, st0, not emitting 1\n");
u8 = F8;
u8 = F8;
} else {
@@ -331,7 +337,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
FDIVD(s0, v1, v2);
FRINTRRD(s0, s0, 0b00); // Nearest == TieToEven?
FCVTZSxD(x4, s0);
@@ -379,7 +385,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
FDIVD(s0, v1, v2);
FRINTZD(s0, s0);
FCVTZSxD(x4, s0);
@@ -490,7 +496,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(ST_IS_F(0))
s0 = v1;
else {
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
FCVT_S_D(s0, v1);
}
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
+12 -12
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -130,7 +130,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
X87_POP_OR_FAIL(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
@@ -143,7 +143,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0:
INST_NAME("FIADD ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
@@ -153,7 +153,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 1:
INST_NAME("FIMUL ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
@@ -163,30 +163,30 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 2:
INST_NAME("FICOM ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FCMPD(v1, v2);
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
break;
case 3:
INST_NAME("FICOMP ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FCMPD(v1, v2);
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FISUB ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
@@ -196,7 +196,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 5:
INST_NAME("FISUBR ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
@@ -206,7 +206,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 6:
INST_NAME("FIDIV ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
@@ -216,7 +216,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 7:
INST_NAME("FIDIVR ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
+6 -6
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -155,7 +155,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOMI(x1, x2);
FCOMI(x1, x2, x4, v1, v2, ST_IS_F(0));
break;
case 0xF0:
case 0xF1:
@@ -174,7 +174,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOMI(x1, x2);
FCOMI(x1, x2, x4, v1, v2, ST_IS_F(0));
break;
default:
@@ -194,7 +194,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FISTTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
if(arm64_frintts) {
FRINT32ZD(s0, v1);
FCVTZSwD(x5, s0);
@@ -220,7 +220,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x4); // x1 have the modified RPSCR reg
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
if(arm64_frintts) {
FRINT32XD(s0, v1);
FCVTZSwD(x5, s0);
@@ -246,7 +246,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x4); // x1 have the modified RPSCR reg
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
if(arm64_frintts) {
FRINT32XD(s0, v1);
FCVTZSwD(x5, s0);
+13 -13
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -88,7 +88,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
break;
case 0xD8:
case 0xD9:
@@ -106,7 +106,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
@@ -185,7 +185,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0:
INST_NAME("FADD ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FADDD(v1, v1, v2);
@@ -193,7 +193,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 1:
INST_NAME("FMUL ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FMULD(v1, v1, v2);
@@ -201,26 +201,26 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 2:
INST_NAME("FCOM ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
break;
case 3:
INST_NAME("FCOMP ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FSUB ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FSUBD(v1, v1, v2);
@@ -228,7 +228,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 5:
INST_NAME("FSUBR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FSUBD(v1, v2, v1);
@@ -236,7 +236,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 6:
INST_NAME("FDIV ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FDIVD(v1, v1, v2);
@@ -244,7 +244,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 7:
INST_NAME("FDIVR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FDIVD(v1, v2, v1);
+4 -4
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -118,7 +118,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
break;
case 0xE8:
case 0xE9:
@@ -136,7 +136,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
@@ -158,7 +158,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(ST_IS_I64(0)) {
VST64(v1, ed, fixedaddress);
} else {
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
if(arm64_frintts) {
FRINT64ZD(s0, v1);
FCVTZSxD(x2, s0);
+13 -13
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -90,7 +90,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD9:
@@ -102,7 +102,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
X87_POP_OR_FAIL(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
@@ -186,7 +186,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0:
INST_NAME("FIADD ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
@@ -197,7 +197,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 1:
INST_NAME("FIMUL ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
@@ -208,32 +208,32 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 2:
INST_NAME("FICOM ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
break;
case 3:
INST_NAME("FICOMP ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FISUB ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
@@ -244,7 +244,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 5:
INST_NAME("FISUBR ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
@@ -255,7 +255,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 6:
INST_NAME("FIDIV ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
@@ -266,7 +266,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 7:
INST_NAME("FIDIVR ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
+7 -7
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -109,7 +109,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOMI(x1, x2);
FCOMI(x1, x2, x4, v1, v2, ST_IS_F(0));
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF0:
@@ -130,7 +130,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOMI(x1, x2);
FCOMI(x1, x2, x4, v1, v2, ST_IS_F(0));
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
@@ -155,7 +155,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
#if 0
// this version needs ARM v8.5, and doesn't handle saturation for 32bits integer not fitting 16bits
FRINT32ZD(s0, v1);
@@ -194,7 +194,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
u8 = x87_setround(dyn, ninst, x1, x2, x4);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
#if 0
FRINT32XD(s0, v1);
// no saturation instruction on Arm, so using NEON
@@ -234,7 +234,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
u8 = x87_setround(dyn, ninst, x1, x2, x4);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
#if 0
FRINT32XD(s0, v1);
// no saturation instruction on Arm, so using NEON
@@ -323,7 +323,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
if(ST_IS_I64(0)) {
VST64(v1, wback, fixedaddress);
} else {
+358 -287
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
// emit OR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_or32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
@@ -34,57 +34,93 @@ void emit_or32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3,
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
int need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
IFXNATIVE(X_OF, NF_VF) need_tst = 1;
IFXNATIVE(X_CF, NF_CF) need_tst = 1;
if(need_tst) TSTxw_REG(s1, s1);
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit OR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_or32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
int mask = convert_bitmask_xw(c);
if(!mask) {
MOV64xw(s3, c);
emit_or32(dyn, ninst, rex, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, rex.w?d_or64:d_or32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
int mask = convert_bitmask_xw(c);
if(mask) {
ORRxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV64xw(s3, c);
ORRxw_REG(s1, s1, s3);
}
ORRxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
int need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
IFXNATIVE(X_OF, NF_VF) need_tst = 1;
IFXNATIVE(X_CF, NF_CF) need_tst = 1;
if(need_tst) TSTxw_REG(s1, s1);
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -101,57 +137,93 @@ void emit_xor32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
int need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
IFXNATIVE(X_OF, NF_VF) need_tst = 1;
IFXNATIVE(X_CF, NF_CF) need_tst = 1;
if(need_tst) TSTxw_REG(s1, s1);
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit XOR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_xor32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
int mask = convert_bitmask_xw(c);
if(!mask) {
MOV64xw(s3, c);
emit_xor32(dyn, ninst, rex, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, rex.w?d_xor64:d_xor32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
int mask = convert_bitmask_xw(c);
if(mask) {
EORxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV64xw(s3, c);
EORxw_REG(s1, s1, s3);
}
EORxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
int need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
IFXNATIVE(X_OF, NF_VF) need_tst = 1;
IFXNATIVE(X_CF, NF_CF) need_tst = 1;
if(need_tst) TSTxw_REG(s1, s1);
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -164,7 +236,7 @@ void emit_and32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_ZF) {
IFX(X_ZF|X_SF|X_CF|X_OF) {
ANDSxw_REG(s1, s1, s2);
} else {
ANDxw_REG(s1, s1, s2);
@@ -172,63 +244,85 @@ void emit_and32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_ZF) {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit AND32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_and32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
int mask = convert_bitmask_xw(c);
if(!mask) {
MOV64xw(s3, c);
emit_and32(dyn, ninst, rex, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, rex.w?d_and64:d_and32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
int mask = convert_bitmask_xw(c);
if(mask) {
IFX(X_ALL) {
ANDSxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
} else {
ANDxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
}
IFX(X_ZF|X_SF|X_CF|X_OF) {
ANDSxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV64xw(s3, c);
IFX(X_ALL) {
ANDSxw_REG(s1, s1, s3);
} else {
ANDxw_REG(s1, s1, s3);
}
ANDxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
}
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_ZF) {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -237,9 +331,9 @@ void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s3, d_or8);
SET_DF(s4, d_or8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
SET_DFNONE(s4);
}
ORRw_REG(s1, s1, s2);
IFX(X_PEND) {
@@ -251,25 +345,25 @@ void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit OR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4)
{
int mask = convert_bitmask_w(c);
if(!mask) {
MOV32w(s3, c);
emit_or8(dyn, ninst, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, d_or8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
int mask = convert_bitmask_w(c);
if(mask) {
ORRw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV32w(s3, c&0xff);
ORRw_REG(s1, s1, s3);
}
ORRw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -279,7 +373,7 @@ void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -288,9 +382,9 @@ void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s3, d_xor8);
SET_DF(s4, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
SET_DFNONE(s4);
}
EORx_REG(s1, s1, s2);
IFX(X_PEND) {
@@ -302,25 +396,25 @@ void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit XOR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4)
{
int mask = convert_bitmask_w(c);
if(!mask) {
MOV32w(s3, c&0xff);
emit_xor8(dyn, ninst, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
int mask = convert_bitmask_w(c);
if(mask) {
EORw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV32w(s3, c&0xff);
EORw_REG(s1, s1, s3);
}
EORw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -330,7 +424,7 @@ void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -339,9 +433,9 @@ void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s3, d_and8);
SET_DF(s4, d_and8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
SET_DFNONE(s4);
}
IFX(X_ZF) {
ANDSw_REG(s1, s1, s2);
@@ -355,41 +449,43 @@ void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw_REG(xFlags, xFlags, s3);
}
IFX(X_ZF) {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
if(arm64_flagm) {
COMP_ZFSF(s1, 8)
} else {
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit AND8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4)
{
int mask = convert_bitmask_w(c);
if(!mask) {
MOV32w(s3, c);
emit_and8(dyn, ninst, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, d_and8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
int mask = convert_bitmask_w(c);
if(mask) {
IFX(X_ZF) {
ANDSw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
} else {
ANDw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV32w(s3, c&0xff);
IFX(X_ZF) {
ANDSw_REG(s1, s1, s3);
} else {
ANDw_REG(s1, s1, s3);
}
ANDw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
}
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
@@ -398,28 +494,33 @@ void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
IFX(X_ZF) {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
if(arm64_flagm) {
COMP_ZFSF(s1, 8)
} else {
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit OR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s3, d_or16);
SET_DF(s4, d_or16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
SET_DFNONE(s4);
}
ORRw_REG(s1, s1, s2);
IFX(X_PEND) {
@@ -431,64 +532,46 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit OR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
//void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
//{
// IFX(X_PEND) {
// MOVW(s3, c);
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// SET_DF(s4, d_or16);
// } else IFX(X_ALL) {
// SET_DFNONE(s4);
// }
// if(c>=0 && c<256) {
// IFX(X_ALL) {
// ORRS_IMM8(s1, s1, c, 0);
// } else {
// ORR_IMM8(s1, s1, c, 0);
// }
// } else {
// IFX(X_PEND) {} else {MOVW(s3, c);}
// IFX(X_ALL) {
// ORRS_REG_LSL_IMM5(s1, s1, s3, 0);
// } else {
// ORR_REG_LSL_IMM5(s1, s1, s3, 0);
// }
// }
// IFX(X_PEND) {
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
// }
// IFX(X_CF | X_AF | X_ZF) {
// BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF)|(1<<F_ZF), 0);
// }
// IFX(X_OF) {
// BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
// }
// IFX(X_ZF) {
// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
// }
// IFX(X_SF) {
// MOV_REG_LSR_IMM5(s3, s1, 15);
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// }
//}
void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int16_t c, int s3, int s4)
{
int mask = convert_bitmask_w((uint16_t)c);
if(!mask) {
MOV32w(s3, (uint16_t)c);
emit_or16(dyn, ninst, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, d_or16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
ORRw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
// emit XOR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s3, d_xor16);
SET_DF(s4, d_xor16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
SET_DFNONE(s4);
}
EORw_REG(s1, s1, s2);
IFX(X_PEND) {
@@ -500,66 +583,49 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit XOR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
//void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
//{
// IFX(X_PEND) {
// MOVW(s3, c);
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// SET_DF(s4, d_xor16);
// } else IFX(X_ALL) {
// SET_DFNONE(s4);
// }
// if(c>=0 && c<256) {
// IFX(X_ALL) {
// XORS_IMM8(s1, s1, c);
// } else {
// XOR_IMM8(s1, s1, c);
// }
// } else {
// IFX(X_PEND) {} else {MOVW(s3, c);}
// IFX(X_ALL) {
// XORS_REG_LSL_IMM5(s1, s1, s3, 0);
// } else {
// XOR_REG_LSL_IMM5(s1, s1, s3, 0);
// }
// }
// IFX(X_PEND) {
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
// }
// IFX(X_CF | X_AF | X_ZF) {
// BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF)|(1<<F_ZF), 0);
// }
// IFX(X_OF) {
// BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
// }
// IFX(X_ZF) {
// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
// }
// IFX(X_SF) {
// MOV_REG_LSR_IMM5(s3, s1, 15);
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// }
//}
void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int16_t c, int s3, int s4)
{
int mask = convert_bitmask_w((uint16_t)c);
if(!mask) {
MOV32w(s3, (uint16_t)c);
emit_xor16(dyn, ninst, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, d_xor16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
EORw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
// emit AND16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s3, d_and16);
SET_DF(s4, d_and16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
SET_DFNONE(s4);
}
IFX(X_ALL) {
IFX(X_ZF) {
ANDSw_REG(s1, s1, s2);
} else {
ANDw_REG(s1, s1, s2);
@@ -571,61 +637,66 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw_REG(xFlags, xFlags, s3);
}
IFX(X_ZF) {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 15);
BFIw(xFlags, s3, F_SF, 1);
if(arm64_flagm) {
COMP_ZFSF(s1, 16)
} else {
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRw(s3, s1, 15);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit AND16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
//void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
//{
// IFX(X_PEND) {
// MOVW(s3, c);
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// SET_DF(s4, d_and16);
// } else IFX(X_ALL) {
// SET_DFNONE(s4);
// }
// if(c>=0 && c<256) {
// IFX(X_ALL) {
// ANDS_IMM8(s1, s1, c);
// } else {
// AND_IMM8(s1, s1, c);
// }
// } else {
// IFX(X_PEND) {} else {MOVW(s3, c);}
// IFX(X_ALL) {
// ANDS_REG_LSL_IMM5(s1, s1, s3, 0);
// } else {
// AND_REG_LSL_IMM5(s1, s1, s3, 0);
// }
// }
// IFX(X_PEND) {
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
// }
// IFX(X_CF | X_AF | X_ZF) {
// BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF)|(1<<F_ZF), 0);
// }
// IFX(X_OF) {
// BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
// }
// IFX(X_ZF) {
// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
// }
// IFX(X_SF) {
// MOV_REG_LSR_IMM5(s3, s1, 15);
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// }
//}
void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int16_t c, int s3, int s4)
{
int mask = convert_bitmask_w((uint16_t)c);
if(!mask) {
MOV32w(s3, (uint16_t)c);
emit_and16(dyn, ninst, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, d_and16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
} else {
ANDw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
}
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
if(arm64_flagm) {
COMP_ZFSF(s1, 16)
} else {
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRw(s3, s1, 15);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
File diff suppressed because it is too large. Load diff
+276 -244
View File
@@ -19,9 +19,9 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
// emit SHL32 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2
// emit SHL32 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2. s2 must be non-0
void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
@@ -35,15 +35,6 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_OF) {
CMPSxw_U12(s2, 0);
Bcond(cNE, +8+((dyn->insts[ninst].x64.gen_flags&X_PEND)?4:0));
BFCw(xFlags, F_OF, 1);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
B_NEXT(cEQ);
}
IFX(X_CF | X_OF) {
MOV32w(s4, rex.w?64:32);
SUBxw_REG(s4, s4, s2);
@@ -54,28 +45,35 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
CMPSxw_U12(s2, 1); // if s2==1
IFX(X_SF) {} else {LSRxw(s4, s1, (rex.w)?63:31);}
EORxw_REG(s4, s4, xFlags); // CF is set if OF is asked
CSELw(s4, s4, wZR, cEQ);
BFIw(xFlags, s4, F_OF, 1);
LSRxw(s4, s1, (rex.w)?63:31);
EORxw_REG(s3, s4, xFlags); // CF is set if OF is asked
CSELw(s3, s3, wZR, cEQ);
BFIw(xFlags, s3, F_OF, 1);
}
int need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
if(need_tst) TSTxw_REG(s1, s1);
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
IFX(X_OF) {} else {LSRxw(s4, s1, (rex.w)?63:31);}
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
if(box64_dynarec_test)
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -92,15 +90,6 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(c==0) {
IFX(X_OF) {
BFCw(xFlags, F_OF, 1);
}
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
IFX(X_CF|X_OF) {
LSRxw(s3, s1, (rex.w?64:32)-c);
BFIxw(xFlags, s3, F_CF, 1);
@@ -110,14 +99,21 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
int need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
if(need_tst) TSTxw_REG(s1, s1);
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s4, s1, (rex.w)?63:31);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_OF) {
if(c==1) {
@@ -138,7 +134,7 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
MOV32w(s3, 1);
BFIw(xFlags, s3, F_PF, 1);
} else
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -171,21 +167,28 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
int need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
if(need_tst) TSTxw_REG(s1, s1);
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
}
}
if(box64_dynarec_test)
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -220,21 +223,79 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
int need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
if(need_tst) TSTxw_REG(s1, s1);
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_SF) {
// no sign if c>0
BFCw(xFlags, F_SF, 1);
IFNATIVE(NF_SF) {} else {
// no sign if c>0
BFCw(xFlags, F_SF, 1);
}
}
if(box64_dynarec_test)
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SAR32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
void emit_sar32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
int64_t j64;
MAYUSE(j64);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_sar64:d_sar32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
SUBxw_U12(s3, s2, 1);
ASRxw_REG(s3, s1, s3);
BFIw(xFlags, s3, 0, 1);
}
IFX(X_OF) {
BFCw(xFlags, F_OF, 1);
}
ASRxw_REG(s1, s1, s2);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
int need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
if(need_tst) TSTxw_REG(s1, s1);
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
}
}
if(box64_dynarec_test)
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -259,17 +320,24 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
int need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
if(need_tst) TSTxw_REG(s1, s1);
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
}
}
IFX(X_OF)
if(c==1) {
if(c==1 || box64_dynarec_test) {
BFCw(xFlags, F_OF, 1);
}
if(box64_dynarec_test)
@@ -277,7 +345,7 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -305,20 +373,20 @@ void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
COMP_ZFSF(s1, 8)
IFX(X_OF) {
CMPSw_U12(s2, 1); // if s2==1
IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 7);}
LSRw(s3, s1, 7);
EORw_REG(s4, s3, xFlags); // CF is set if OF is asked
CSELw(s4, s4, wZR, cEQ);
BFIw(xFlags, s4, F_OF, 1);
}
COMP_ZFSF(s1, 8)
if(box64_dynarec_test)
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -347,7 +415,7 @@ void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
COMP_ZFSF(s1, 8)
IFX(X_OF) {
if(c==1) {
IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 7);}
IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 7);} //use COMP_ZFSF operation
EORw_REG(s4, s3, xFlags); // CF is set if OF is asked
BFIw(xFlags, s4, F_OF, 1);
} else {
@@ -358,32 +426,38 @@ void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
} else {
IFXNATIVE(X_ZF|X_SF|X_CF, NF_EQ|NF_SF|NF_CF) {
SUBSw_REG(s1, s1, s1);
} else {
MOVw_REG(s1, xZR);
}
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF) {
LSLw(s3, s1, c-1);
BFXILw(xFlags, s3, 7, 1); // insert F_CF from s3[7:1]
// sub X, X will generate a carry flags
IFNATIVE(NF_CF) {GEN_INVERTED_CARRY();} else {BFCw(xFlags, F_CF, 1);}
}
MOVw_REG(s1, xZR);
IFX(X_OF) {
BFCw(xFlags, F_OF, 1);
}
IFX(X_SF) {
BFCw(xFlags, F_SF, 1);
IFNATIVE(NF_SF) {} else BFCw(xFlags, F_SF, 1);
}
if(box64_dynarec_test) IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF | X_ZF) {
MOV32w(s3, 1);
IFX(X_ZF) {
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_PF) {
BFIw(xFlags, s3, F_PF, 1);
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
ORRw_mask(xFlags, xFlags, 26, 0); //1<<F_ZF
}
}
IFX(X_PF) {
ORRw_mask(xFlags, xFlags, 30, 0); //1<<F_PF
}
}
}
@@ -422,7 +496,7 @@ void emit_shr8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -462,7 +536,7 @@ void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -487,8 +561,8 @@ void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
COMP_ZFSF(s1, 8)
IFX(X_OF) {
CMPSw_U12(s2, 1);
Bcond(cNE, 4+4);
SUBw_U12(s4, s2, 1);
CBNZw(s4, 4+4);
BFCw(xFlags, F_OF, 1);
}
if(box64_dynarec_test)
@@ -496,7 +570,7 @@ void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -513,8 +587,7 @@ void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
SET_DFNONE(s4);
}
if(c<8) IFX(X_CF) {
ASRw(s3, s1, c-1);
BFIw(xFlags, s3, 0, 1);
BFXILw(xFlags, s1, c-1, 1);
}
ASRw(s1, s1, c);
IFX(X_PEND) {
@@ -527,16 +600,21 @@ void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
BFCw(xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
} else {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_CF, 1);
BFIw(wFlags, s3, F_SF, 1);
EORw_mask(s3, s3, 0, 0); //1
BFIw(xFlags, s3, F_ZF, 1);
MOV32w(s3, 1);
BFIw(xFlags, s3, F_PF, 1);
IFX(X_CF|X_ZF|X_SF|X_PF) {
LSRw(s3, s1, 7);
IFX(X_CF){ BFIw(xFlags, s3, F_CF, 1); }
IFX(X_SF){ BFIw(wFlags, s3, F_SF, 1); }
IFX(X_ZF) {
EORw_mask(s3, s3, 0, 0); //1
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_PF) {
ORRw_mask(xFlags, xFlags, 30, 0); //1<<F_PF
}
}
}
if(box64_dynarec_test)
IFX(X_AF) {
@@ -564,20 +642,20 @@ void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
COMP_ZFSF(s1, 16)
IFX(X_OF) {
CMPSw_U12(s2, 1); // if s2==1
IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 15);}
LSRw(s3, s1, 15);
EORw_REG(s4, s3, xFlags); // CF is set if OF is asked
CSELw(s4, s4, wZR, cEQ);
BFIw(xFlags, s4, F_OF, 1);
}
COMP_ZFSF(s1, 16)
if(box64_dynarec_test)
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -606,7 +684,7 @@ void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
COMP_ZFSF(s1, 16)
IFX(X_OF) {
if(c==1) {
IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 15);}
IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 15);} // use COMP_ZFSF operation
EORw_REG(s4, s3, xFlags); // CF is set if OF is asked
BFIw(xFlags, s4, F_OF, 1);
} else {
@@ -619,32 +697,40 @@ void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
IFX(X_PF) {
if(c>7) {
// the 0xff area will be 0, so PF is known
MOV32w(s3, 1);
BFIw(xFlags, s3, F_PF, 1);
ORRw_mask(xFlags, xFlags, 30, 0); //1<<F_PF
} else
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
} else {
IFX(X_CF) {
LSLw(s3, s1, c-1);
BFXILw(xFlags, s3, 15, 1); // insert F_CF from s3[15:1]
IFXNATIVE(X_ZF|X_SF|X_CF, NF_EQ|NF_SF|NF_CF) {
SUBSw_REG(s1, s1, s1);
} else {
MOVw_REG(s1, xZR);
}
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
MOVw_REG(s1, xZR);
IFX(X_OF) {
BFCw(xFlags, F_OF, 1);
}
IFX(X_SF) {
BFCw(xFlags, F_SF, 1);
IFX(X_CF) {
// sub X, X will generate a carry flags
IFNATIVE(NF_CF) {GEN_INVERTED_CARRY();} else {BFCw(xFlags, F_CF, 1);}
}
IFX(X_PF | X_ZF) {
MOV32w(s3, 1);
IFX(X_ZF) {
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_PF) {
BFIw(xFlags, s3, F_PF, 1);
IFX(X_SF) {
IFNATIVE(NF_SF) {} else BFCw(xFlags, F_SF, 1);
}
if(box64_dynarec_test) IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
ORRw_mask(xFlags, xFlags, 26, 0); //1<<F_ZF
}
}
IFX(X_PF) {
ORRw_mask(xFlags, xFlags, 30, 0); //1<<F_PF
}
}
}
@@ -664,8 +750,8 @@ void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFIw(xFlags, s4, 0, 1);
}
IFX(X_OF) {
CMPSw_U12(s2, 1); // if s2==1
Bcond(cNE, 4+2*4);
SUBw_U12(s4, s2, 1); // if s2==1
CBNZw(s4, 4+2*4);
LSRw(s4, s1, 15);
BFIw(xFlags, s4, F_OF, 1);
}
@@ -679,7 +765,7 @@ void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -720,7 +806,7 @@ void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -743,18 +829,18 @@ void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
COMP_ZFSF(s1, 16)
IFX(X_OF) {
CMPSw_U12(s2, 1);
Bcond(cNE, 4+4);
SUBw_U12(s4, s2, 1);
CBNZw(s4, 4+4);
BFCw(xFlags, F_OF, 1);
}
COMP_ZFSF(s1, 16)
if(box64_dynarec_test)
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -788,7 +874,7 @@ void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
@@ -798,29 +884,15 @@ void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_rol64:d_rol32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
SET_DFNONE(s4);
RORxw(s1, s1, (rex.w?64:32)-c);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF) {
BFIw(xFlags, s1, F_CF, 1);
}
IFX(X_OF) {
if(c==1) {
ADDxw_REG_LSR(s3, s1, s1, rex.w?63:31);
EORxw_REG_LSR(s3, s1, s1, rex.w?63:31);
BFIw(xFlags, s3, F_OF, 1);
}
}
@@ -833,23 +905,9 @@ void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_ror64:d_ror32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
SET_DFNONE(s4);
RORxw(s1, s1, c);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF) {
BFXILxw(xFlags, s1, rex.w?63:31, 1);
}
@@ -869,21 +927,13 @@ void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRB_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_rol8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
SET_DFNONE(s4);
if(c&7) {
int rc = 8-(c&7);
ORRw_REG_LSL(s1, s1, s1, 8);
LSRw(s1, s1, rc);
}
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF) {
BFIw(xFlags, s1, F_CF, 1);
}
@@ -902,20 +952,12 @@ void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRB_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_ror8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
SET_DFNONE(s4);
if(c&7) {
ORRw_REG_LSL(s1, s1, s1, 8);
LSRw(s1, s1, c&7);
}
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF) {
BFXILw(xFlags, s1, 7, 1);
}
@@ -935,21 +977,13 @@ void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRH_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_rol16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
SET_DFNONE(s4);
if(c&15) {
int rc = 16-(c&15);
ORRw_REG_LSL(s1, s1, s1, 16);
LSRw(s1, s1, rc);
}
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF) {
BFIw(xFlags, s1, F_CF, 1);
}
@@ -968,20 +1002,12 @@ void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRH_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_ror16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
SET_DFNONE(s4);
if(c&15) {
ORRw_REG_LSL(s1, s1, s1, 16);
LSRw(s1, s1, c&15);
}
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF) {
BFXILw(xFlags, s1, 15, 1);
}
@@ -1014,9 +1040,6 @@ void emit_rcl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
}
ORRw_REG_LSL(s1, s1, s1, 9); // insert s1 again
LSRw_IMM(s1, s1, 9-c); // do the rcl
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_OF|X_CF) {
IFX(X_CF) {
BFIw(xFlags, s3, F_CF, 1);
@@ -1057,9 +1080,6 @@ void emit_rcr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
BFIw(xFlags, s3, F_OF, 1);
}
}
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
}
// emit RCL16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
@@ -1082,9 +1102,6 @@ void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
}
ORRx_REG_LSL(s1, s1, s1, 17); // insert s1 again
LSRx_IMM(s1, s1, 17-c); // do the rcl
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF) {
BFIw(xFlags, s3, F_CF, 1);
}
@@ -1123,9 +1140,6 @@ void emit_rcr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
BFIw(xFlags, s3, F_OF, 1);
}
}
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
}
// emit RCL32/RCL64 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
@@ -1133,6 +1147,8 @@ void emit_rcl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
if(!c) return;
SET_DFNONE(s4);
IFX(X_OF|X_CF) {
@@ -1146,9 +1162,6 @@ void emit_rcl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
BFIxw(s4, xFlags, c-1, 1);
ORRxw_REG_LSR(s1, s4, s1, (rex.w?65:33)-c);
}
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF) {
BFIw(xFlags, s3, F_CF, 1);
}
@@ -1164,6 +1177,8 @@ void emit_rcr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
if(!c) return;
SET_DFNONE(s4);
IFX(X_OF) {
@@ -1186,9 +1201,6 @@ void emit_rcr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
IFX(X_CF) {
BFIw(wFlags, s3, 0, 1);
}
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
}
// emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch
@@ -1213,7 +1225,7 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint
BFXILxw(xFlags, s1, c-1, 1); // set CF
}
IFX(X_OF) {
if(c==1) {
if((c==1) || box64_dynarec_test) {
LSRxw(s4, s1, rex.w?63:31);
BFIw(xFlags, s4, F_OF, 1); // store sign for later use
}
@@ -1222,14 +1234,21 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
int need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
if(need_tst) TSTxw_REG(s1, s1);
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
}
}
IFX(X_OF) {
if(c==1) {
@@ -1238,7 +1257,7 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1263,8 +1282,7 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint
return;
}
IFX(X_CF) {
LSRxw(s3, s1, (rex.w?64:32)-c);
BFIxw(xFlags, s3, F_CF, 1);
BFXILx(xFlags, s1, (rex.w?64:32)-c, 1);
}
IFX(X_OF) {
LSRxw(s3, s1, rex.w?63:31);
@@ -1293,7 +1311,7 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1325,23 +1343,30 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
int need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
if(need_tst) TSTxw_REG(s1, s1);
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
BFIw(xFlags, s4, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
}
}
IFX(X_OF) {
CMPSw_U12(s5, 1);
Bcond(cNE, 4+2*4);
SUBw_U12(s3, s5, 1);
CBNZw(s3, 4+2*4); //flagless jump
UBFXx(s3, s1, rex.w?63:31, 1);
EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1371,23 +1396,30 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
int need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
if(need_tst) TSTxw_REG(s1, s1);
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
}
}
IFX(X_OF) {
CMPSw_U12(s5, 1);
Bcond(cNE, 4+2*4);
SUBw_U12(s3, s5, 1);
CBNZw(s3, 4+2*4); //flagless jump
UBFXx(s3, s1, rex.w?63:31, 1);
EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1431,7 +1463,7 @@ void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1462,13 +1494,13 @@ void emit_shrd16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3,
}
COMP_ZFSF(s1, 16)
IFX(X_OF) {
CMPSw_U12(s5, 1);
Bcond(cNE, 4+2*4);
SUBw_U12(s3, s5, 1);
CBNZw(s3, 4+2*4);
UBFXw(s3, s1, 15, 1);
EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1519,7 +1551,7 @@ void emit_shld16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1553,12 +1585,12 @@ void emit_shld16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3,
}
COMP_ZFSF(s1, 16)
IFX(X_OF) {
CMPSw_U12(s5, 1);
Bcond(cNE, 4+2*4);
SUBw_U12(s3, s5, 1);
CBNZw(s3, 4+2*4);
UBFXw(s3, s1, 15, 1);
EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
+403 -106
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
// emit CMP32 instruction, from cmp s1, s2, using s3 and s4 as scratch
void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
@@ -47,24 +47,34 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_ZF) {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_CF) {
// inverted carry
CSETw(s4, cCC);
BFIw(xFlags, s4, F_CF, 1);
IFNATIVE(NF_CF) {
GEN_INVERTED_CARRY();
} else {
CSETw(s4, cCC);
BFIw(xFlags, s4, F_CF, 1);
}
}
IFX(X_OF) {
CSETw(s4, cVS);
BFIw(xFlags, s4, F_OF, 1);
IFNATIVE(NF_VF) {} else {
CSETw(s4, cVS);
BFIw(xFlags, s4, F_OF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s5, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s5, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s3, s4);
emit_pf(dyn, ninst, s5, s4);
}
}
@@ -83,20 +93,35 @@ void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int
SUBSxw_U12(s3, s1, 0); // res = s1 - 0
// and now the tricky ones (and mostly unused), PF and AF
// bc = (res & (~d | s)) | (~d & s) => is 0 here...
IFX(X_OF|X_AF|X_CF) {
MOV32w(s4, (1<<F_OF)|(1<<F_AF)|(1<<F_CF));
BICw(xFlags, xFlags, s4);
IFX(X_CF) {
IFNATIVE(NF_CF) {
GEN_INVERTED_CARRY();
} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_ZF) {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -111,34 +136,63 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
} else {
SET_DFNONE(s3);
}
SUBw_REG(s5, s1, s2); // res = s1 - s2
IFX(X_AF) {
ORNw_REG(s3, s2, s1); // s3 = ~op1 | op2
BICw(s4, s2, s1); // s4 = ~op1 & op2
}
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 16);
SUBSw_REG_LSL(s5, s5, s2, 16);
IFX(X_AF) {
ANDw_REG_LSR(s3, s3, s5, 16); // s3 = (~op1 | op2) & res
ORRw_REG(s3, s3, s4); // s3 = (~op1 & op2) | ((~op1 | op2) & res)
LSRw(s4, s3, 3);
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_CF) {
// inverted carry
IFNATIVE(NF_CF) {
GEN_INVERTED_CARRY();
} else {
CSETw(s4, cCC);
BFIw(xFlags, s4, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
CSETw(s4, cVS);
BFIw(xFlags, s4, F_OF, 1);
}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
CSETw(s4, cMI);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_PF|X_PEND) {
LSRw(s5, s5, 16);
}
} else {
SUBw_REG(s5, s1, s2); // res = s1 - s2
IFX(X_AF) {
ANDw_REG(s3, s3, s5); // s3 = (~op1 | op2) & res
ORRw_REG(s3, s3, s4); // s3 = (~op1 & op2) | ((~op1 | op2) & res)
LSRw(s4, s3, 3);
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
}
IFX_PENDOR0 {
STRH_U12(s5, xEmu, offsetof(x64emu_t, res));
}
COMP_ZFSF(s5, 16)
// bc = (res & (~d | s)) | (~d & s)
IFX(X_CF|X_AF|X_OF) {
MVNw_REG(s4, s1); // s4 = ~d
ORRw_REG(s4, s4, s2); // s4 = ~d | s
ANDw_REG(s4, s4, s5); // s4 = res & (~d | s)
BICw_REG(s3, s2, s1); // s3 = s & ~d
ORRw_REG(s3, s4, s3); // s3 = (res & (~d | s)) | (s & ~d)
IFX(X_CF) {
LSRw(s4, s3, 15);
BFIw(xFlags, s4, F_CF, 1); // CF : bc & 0x8000
}
IFX(X_AF) {
LSRw(s4, s3, 3);
BFIw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_OF) {
LSRw(s4, s3, 14);
EORw_REG_LSR(s4, s4, s4, 1);
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s3, s4);
emit_pf(dyn, ninst, s5, s4);
}
}
@@ -161,7 +215,7 @@ void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit CMP8 instruction, from cmp s1, s2, using s3 and s4 as scratch
@@ -171,37 +225,67 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
IFX_PENDOR0 {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_cmp8);
SET_DF(s3, d_cmp8);
} else {
SET_DFNONE(s4);
SET_DFNONE(s3);
}
IFX(X_AF) {
ORNw_REG(s3, s2, s1); // s3 = ~op1 | op2
BICw(s4, s2, s1); // s4 = ~op1 & op2
}
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 24);
SUBSw_REG_LSL(s5, s5, s2, 24);
IFX(X_AF) {
ANDw_REG_LSR(s3, s3, s5, 24); // s3 = (~op1 | op2) & res
ORRw_REG(s3, s3, s4); // s3 = (~op1 & op2) | ((~op1 | op2) & res)
LSRw(s4, s3, 3);
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_CF) {
// inverted carry
IFNATIVE(NF_CF) {
GEN_INVERTED_CARRY();
} else {
CSETw(s4, cCC);
BFIw(xFlags, s4, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
CSETw(s4, cVS);
BFIw(xFlags, s4, F_OF, 1);
}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
CSETw(s4, cMI);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_PF|X_PEND) {
LSRw(s5, s5, 24);
}
} else {
SUBw_REG(s5, s1, s2); // res = s1 - s2
IFX(X_AF) {
ANDw_REG(s3, s3, s5); // s3 = (~op1 | op2) & res
ORRw_REG(s3, s3, s4); // s3 = (~op1 & op2) | ((~op1 | op2) & res)
LSRw(s4, s3, 3);
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
}
SUBw_REG(s5, s1, s2); // res = s1 - s2
IFX_PENDOR0 {
STRB_U12(s5, xEmu, offsetof(x64emu_t, res));
}
COMP_ZFSF(s5, 8)
// bc = (res & (~d | s)) | (~d & s)
IFX(X_CF|X_AF|X_OF) {
ORNw_REG(s4, s2, s1); // s4 = ~d | s
ANDw_REG(s4, s4, s5); // s4 = res & (~d | s)
BICw_REG(s3, s2, s1); // s3 = s & ~d
ORRw_REG(s3, s4, s3); // s3 = (res & (~d | s)) | (s & ~d)
IFX(X_CF) {
LSRw(s4, s3, 7);
BFIw(xFlags, s4, F_CF, 1); // CF : bc & 0x80
}
IFX(X_AF) {
LSRw(s4, s3, 3);
BFIw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_OF) {
LSRw(s4, s3, 6);
EORw_REG_LSR(s4, s4, s4, 1);
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s3, s4);
emit_pf(dyn, ninst, s5, s4);
}
}
// emit CMP8 instruction, from cmp s1 , 0, using s3 and s4 as scratch
@@ -223,7 +307,7 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -236,25 +320,86 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
} else {
SET_DFNONE(s4);
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
ANDSxw_REG(s3, s1, s2); // res = s1 & s2
IFX_PENDOR0 {
STRxw_U12(s3, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s4, s3, rex.w?63:31);
BFIw(xFlags, s4, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s4, s3, rex.w?63:31);
BFIw(xFlags, s4, F_SF, 1);
}
}
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
emit_pf(dyn, ninst, s3, s4, s5);
emit_pf(dyn, ninst, s3, s5);
}
}
// emit TEST32 instruction, from test s1, s2, using s3, s4 and s5 as scratch
void emit_test32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
int mask = convert_bitmask_xw(c);
IFX_PENDOR0 {
SET_DF(s3, rex.w?d_tst64:d_tst32);
} else {
SET_DFNONE(s4);
}
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
if(mask) {
ANDSxw_mask(s3, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV64xw(s3, c);
ANDSxw_REG(s3, s1, s3); // res = s1 & s2
}
IFX_PENDOR0 {
STRxw_U12(s3, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
LSRxw(s4, s3, rex.w?63:31);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s3, s5);
}
}
@@ -267,25 +412,101 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4,
} else {
SET_DFNONE(s4);
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 16);
ANDSw_REG_LSL(s5, s5, s2, 16);
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {BFCw(xFlags, F_CF, 1);}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
CSETw(s4, cMI);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_PF|X_PEND) {
LSRw(s5, s5, 16);
}
} else {
ANDw_REG(s5, s1, s2); // res = s1 & s2
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
ANDSw_REG(s5, s1, s2); // res = s1 & s2
IFX_PENDOR0 {
STRH_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s4, s5, 15);
BFIw(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s3, s4);
emit_pf(dyn, ninst, s5, s4);
}
}
// emit TEST16 instruction, from test s1, s2, using s3, s4 and s5 as scratch
void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5)
{
MAYUSE(s1);
int mask = 0;
IFX_PENDOR0 {
SET_DF(s3, d_tst16);
} else {
SET_DFNONE(s4);
}
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 16);
mask = convert_bitmask_w(c<<16);
if(mask) {
ANDSw_mask(s5, s5, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV32w(s3, c);
ANDSw_REG_LSL(s5, s5, s3, 16);
}
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {BFCw(xFlags, F_CF, 1);}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
CSETw(s4, cMI);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_PF|X_PEND) {
LSRw(s5, s5, 16);
}
} else {
mask = convert_bitmask_w(c);
if(mask) {
ANDw_mask(s5, s1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV32w(s5, c);
ANDw_REG(s5, s1, s5); // res = s1 & s2
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX_PENDOR0 {
STRH_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s4);
}
}
@@ -298,24 +519,100 @@ void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
} else {
SET_DFNONE(s4);
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 24);
ANDSw_REG_LSL(s5, s5, s2, 24);
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {BFCw(xFlags, F_CF, 1);}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
CSETw(s4, cMI);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_PF|X_PEND) {
LSRw(s5, s5, 24);
}
} else {
ANDw_REG(s5, s1, s2); // res = s1 & s2
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
ANDSw_REG(s5, s1, s2); // res = s1 & s2
IFX_PENDOR0 {
STRB_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s4, s5, 7);
BFIw(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s3, s4);
emit_pf(dyn, ninst, s5, s4);
}
}
// emit TEST8 instruction, from test s1, s2, using s3, s4 and s5 as scratch
void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5)
{
MAYUSE(s1);
int mask = 0;
IFX_PENDOR0 {
SET_DF(s3, d_tst8);
} else {
SET_DFNONE(s4);
}
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 24);
mask = convert_bitmask_w(c<<24);
if(mask) {
ANDSw_mask(s5, s5, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV32w(s3, c);
ANDSw_REG_LSL(s5, s5, s3, 24);
}
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {BFCw(xFlags, F_CF, 1);}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
CSETw(s4, cMI);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_PF|X_PEND) {
LSRw(s5, s5, 24);
}
} else {
mask = convert_bitmask_w(c);
if(mask) {
ANDw_mask(s5, s1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV32w(s5, c);
ANDw_REG(s5, s1, s5); // res = s1 & s2
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX_PENDOR0 {
STRB_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s4);
}
}
+88 -53
View File
@@ -18,7 +18,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -52,6 +52,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETREX();
SKIPTEST(x1); // DYNAREC_TEST doesn't work, by nature, on atomic opration
switch(opcode) {
case 0x00:
@@ -61,12 +62,12 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETGB(x2);
if((nextop&0xC0)==0xC0) {
if(rex.rex) {
wback = xRAX + (nextop&7) + (rex.b<<3);
wback = TO_NAT((nextop & 0x07) + (rex.b << 3));
wb2 = 0;
} else {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xRAX+(wback&3);
wback = TO_NAT(wback & 3);
}
UBFXw(x1, wback, wb2*8, 8);
emit_add8(dyn, ninst, x1, x2, x4, x3);
@@ -95,8 +96,8 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xRAX+(nextop&7)+(rex.b<<3);
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_add32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
@@ -148,12 +149,12 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETGB(x2);
if((nextop&0xC0)==0xC0) {
if(rex.rex) {
wback = xRAX + (nextop&7) + (rex.b<<3);
wback = TO_NAT((nextop & 0x07) + (rex.b << 3));
wb2 = 0;
} else {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xRAX+(wback&3);
wback = TO_NAT(wback & 3);
}
UBFXw(x1, wback, wb2*8, 8);
emit_or8(dyn, ninst, x1, x2, x4, x3);
@@ -181,7 +182,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_or32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
@@ -212,7 +213,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
if(rex.w) {
ANDx_mask(x2, gd, 1, 0, 0b00101); //mask=0x000000000000003f
@@ -259,19 +260,19 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UBFXx(x6, xRAX, 0, 8);
if(MODREG) {
if(rex.rex) {
wback = xRAX+(nextop&7)+(rex.b<<3);
wback = TO_NAT((nextop & 7) + (rex.b << 3));
wb2 = 0;
} else {
wback = (nextop&7);
wb2 = (wback>>2)*8;
wback = xRAX+(wback&3);
wback = TO_NAT(wback & 3);
}
UBFXx(x2, wback, wb2, 8);
wb1 = 0;
ed = x2;
UFLAG_IF {emit_cmp8(dyn, ninst, x6, ed, x3, x4, x5);}
CMPSxw_REG(x6, x2);
B_MARK2(cNE);
SUBxw_REG(x6, x6, x2);
CBNZxw_MARK2(x6);
BFIx(wback, x2, wb2, 8);
MOVxw_REG(ed, gd);
MARK2;
@@ -316,12 +317,12 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
UFLAG_IF {emit_cmp32(dyn, ninst, rex, xRAX, ed, x3, x4, x5);}
MOVxw_REG(x1, ed); // save value
CMPSxw_REG(xRAX, x1);
B_MARK2(cNE);
SUBxw_REG(x3, xRAX, x1);
CBNZxw_MARK2(x3);
MOVxw_REG(ed, gd);
MARK2;
MOVxw_REG(xRAX, x1);
@@ -399,7 +400,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
if(rex.w) {
ANDx_mask(x2, gd, 1, 0, 0b00101); //mask=0x000000000000003f
@@ -446,7 +447,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SET_DFNONE(x1);
gd = x2;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
u8 = F8;
u8&=rex.w?0x3f:0x1f;
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
@@ -470,7 +471,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
u8 = F8;
u8&=(rex.w?0x3f:0x1f);
@@ -502,7 +503,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
u8 = F8;
u8&=(rex.w?0x3f:0x1f);
@@ -531,7 +532,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
u8 = F8;
u8&=(rex.w?0x3f:0x1f);
@@ -569,7 +570,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGB(x1);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
GETEB(x2, 0);
gd = x2; ed = x1; // swap gd/ed
emit_add8(dyn, ninst, x1, x2, x4, x5);
@@ -615,7 +616,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOVxw_REG(x1, ed);
MOVxw_REG(ed, gd);
MOVxw_REG(gd, x1);
@@ -687,7 +688,11 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
switch((nextop>>3)&7) {
case 1:
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
if (rex.w) {
INST_NAME("LOCK CMPXCHG16B Gq, Eq");
} else {
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
}
SETFLAGS(X_ZF, SF_SUBSET);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(!ALIGNED_ATOMICxw) {
@@ -714,7 +719,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UFLAG_IF {
CMPSxw_REG(x2, xRAX);
CCMPxw(x3, xRDX, 0, cEQ);
CSETw(x1, cEQ);
IFNATIVE(NF_EQ) {} else {CSETw(x1, cEQ);}
}
MOVx_REG(xRAX, x2);
MOVx_REG(xRDX, x3);
@@ -730,7 +735,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STLXPxw(x4, xRBX, xRCX, wback);
CBNZx_MARKLOCK(x4);
UFLAG_IF {
MOV32w(x1, 1);
IFNATIVE(NF_EQ) {} else {MOV32w(x1, 1);}
}
B_MARK3_nocond;
MARK;
@@ -739,7 +744,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(xRAX, x2);
MOVxw_REG(xRDX, x3);
UFLAG_IF {
MOV32w(x1, 0);
IFNATIVE(NF_EQ) {} else {MOV32w(x1, 0);}
}
if(!ALIGNED_ATOMICxw) {
B_MARK3_nocond;
@@ -756,7 +761,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
CBNZx_MARK2(x4);
STPxw_S7_offset(xRBX, xRCX, wback, 0);
UFLAG_IF {
MOV32w(x1, 1);
IFNATIVE(NF_EQ) {} else {MOV32w(x1, 1);}
}
B_MARK3_nocond;
MARKSEG;
@@ -765,13 +770,13 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(xRAX, x2);
MOVxw_REG(xRDX, x3);
UFLAG_IF {
MOV32w(x1, 0);
IFNATIVE(NF_EQ) {} else {MOV32w(x1, 0);}
}
}
MARK3;
SMDMB();
UFLAG_IF {
BFIw(xFlags, x1, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {BFIw(xFlags, x1, F_ZF, 1);}
}
break;
default:
@@ -791,12 +796,12 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETGB(x2);
if((nextop&0xC0)==0xC0) {
if(rex.rex) {
wback = xRAX + (nextop&7) + (rex.b<<3);
wback = TO_NAT((nextop & 0x07) + (rex.b << 3));
wb2 = 0;
} else {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xRAX+(wback&3);
wback = TO_NAT(wback & 3);
}
UBFXw(x1, wback, wb2*8, 8);
emit_adc8(dyn, ninst, x1, x2, x4, x5);
@@ -818,7 +823,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_adc32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
@@ -830,13 +835,44 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SMDMB();
}
break;
case 0x20:
INST_NAME("LOCK AND Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
if(MODREG) {
GETEB(x1, 0);
GETGB(x2);
emit_and8(dyn, ninst, x1, x2, x4, x5);
EBBACK;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
GETGB(x5);
if(arm64_atomics) {
MVNxw_REG(x1, gd);
UFLAG_IF {
LDCLRALB(x1, x1, wback);
emit_and8(dyn, ninst, x1, gd, x3, x4);
} else {
STCLRLB(x1, wback);
}
} else {
MARKLOCK;
LDAXRB(x1, wback);
emit_and8(dyn, ninst, x1, gd, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
}
}
break;
case 0x21:
INST_NAME("LOCK AND Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_and32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
@@ -865,7 +901,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_sub32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
@@ -916,7 +952,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_xor32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
@@ -1196,7 +1232,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV64xw(x5, i64);
emit_add32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
@@ -1249,7 +1285,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV64xw(x5, i64);
emit_or32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
@@ -1279,7 +1315,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV64xw(x5, i64);
emit_adc32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
@@ -1300,7 +1336,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV64xw(x5, i64);
emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
@@ -1320,7 +1356,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV64xw(x5, i64);
emit_and32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
@@ -1351,7 +1387,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV64xw(x5, i64);
emit_sub32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
@@ -1405,7 +1441,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV64xw(x5, i64);
emit_xor32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
@@ -1452,12 +1488,12 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
GETGB(x4);
if(rex.rex) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
eb1 = ed;
eb2 = 0;
} else {
ed = (nextop&7);
eb1 = xRAX+(ed&3);
eb1 = TO_NAT(ed & 3);
eb2 = ((ed&4)<<1);
}
UBFXw(x1, eb1, eb2, 8);
@@ -1543,8 +1579,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SMDMB();
GETEB(x1, 1);
u8 = F8;
MOV32w(x2, u8);
emit_test8(dyn, ninst, x1, x2, x3, x4, x5);
emit_test8c(dyn, ninst, x1, u8, x3, x4, x5);
break;
case 2:
INST_NAME("LOCK NOT Eb");
@@ -1573,7 +1608,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
{
case 0: // INC Eb
INST_NAME("LOCK INC Eb");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if(MODREG) {
GETEB(x1, 0);
emit_inc8(dyn, ninst, x1, x2, x4);
@@ -1600,7 +1635,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 1: //DEC Eb
INST_NAME("LOCK DEC Eb");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if(MODREG) {
GETEB(x1, 0);
emit_dec8(dyn, ninst, x1, x2, x4);
@@ -1635,9 +1670,9 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
{
case 0: // INC Ed
INST_NAME("LOCK INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_inc32(dyn, ninst, rex, ed, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
@@ -1683,9 +1718,9 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 1: //DEC Ed
INST_NAME("LOCK DEC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_dec32(dyn, ninst, rex, ed, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
+81 -32
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
@@ -31,6 +31,8 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
uint8_t wback, wb1, wb2;
uint8_t u8;
uint64_t u64, j64;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1;
int q0;
int d0, d1;
@@ -71,7 +73,6 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
d0 = sse_get_reg(dyn, ninst, x1, ed, 1);
VMOVeD(d0, 0, v0, 0);
} else {
WILLWRITE2();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v0, ed, fixedaddress);
SMWRITE2();
@@ -84,14 +85,13 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(MODREG) {
d0 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVeD(v0, 0, d0, 0);
VDUPQ_64(v0, d0, 0);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VLDQ1R_64(v0, ed);
}
VMOVeD(v0, 1, v0, 0);
break;
case 0x2A:
@@ -99,7 +99,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGX(v0, 1);
GETED(0);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
if(rex.w) {
SCVTFDx(d1, ed);
} else {
@@ -140,7 +140,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
MSR_fpsr(x5);
}
u8 = sse_setround(dyn, ninst, x1, x2, x3);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
FRINTID(d1, q0);
x87_restoreround(dyn, ninst, u8);
FCVTZSxwD(gd, d1);
@@ -207,10 +207,10 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("SQRTSD Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(d0, 0, 0);
if(!box64_dynarec_fastnan) {
v1 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn, ninst);
FCMLTD_0(v1, d0);
SHL_64(v1, v1, 63);
FSQRTD(d1, d0);
@@ -225,11 +225,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("ADDSD Gx, Ex");
nextop = F8;
GETGX(d1, 1);
v1 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn, ninst);
GETEXSD(d0, 0, 0);
if(!box64_dynarec_fastnan) {
v0 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(v0, d0, d1); // propagate NAN
FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -247,11 +247,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("MULSD Gx, Ex");
nextop = F8;
GETGX(d1, 1);
v1 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn, ninst);
GETEXSD(d0, 0, 0);
if(!box64_dynarec_fastnan) {
v0 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(v0, d0, d1); // propagate NAN
FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -270,7 +270,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGX(v0, 1);
GETEXSD(d0, 0, 0);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
FCVT_S_D(d1, d0);
VMOVeS(v0, 0, d1, 0);
break;
@@ -279,11 +279,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("SUBSD Gx, Ex");
nextop = F8;
GETGX(d1, 1);
v1 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn, ninst);
GETEXSD(d0, 0, 0);
if(!box64_dynarec_fastnan) {
v0 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(v0, d0, d1); // propagate NAN
FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -304,7 +304,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEXSD(v1, 0, 0);
// MINSD: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
FMINNMD(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeD(v0, 0, d0, 0); // to not erase uper part
#else
@@ -317,11 +317,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("DIVSD Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
if(!box64_dynarec_fastnan) {
d0 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(d0, v0, v1); // propagate NAN
FCMEQD(d0, d0, d0); // 0 if NAN, 1 if not NAN
@@ -342,7 +342,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEXSD(v1, 0, 0);
// MAXSD: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
FMAXNMD(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeD(v0, 0, d0, 0); // to not erase uper part
#else
@@ -361,7 +361,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
u8 = F8;
if(u8==0b00000000 || u8==0b01010101 || u8==0b10101010 || u8==0b11111111) {
if(v0==v1) {
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
VMOVQ(d0, v1);
}
VDUP_16(v0, v1, u8&3);
@@ -375,7 +375,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+1)<<(i*16+8);
}
MOV64x(x2, u64);
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
VMOVQDfrom(d0, 0, x2);
VTBL1_8(d0, v1, d0);
VMOVeD(v0, 0, d0, 0);
@@ -393,7 +393,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
v1 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn, ninst);
VLD128(v1, ed, fixedaddress);
}
VFADDPQS(v0, v0, v1);
@@ -406,14 +406,63 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
v1 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn, ninst);
VLD128(v1, ed, fixedaddress);
}
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
VUZP1Q_32(d0, v0, v1);
VUZP2Q_32(v0, v0, v1);
VFSUBQS(v0, d0, v0);
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
i32_ = F32S; \
if(rex.is32bits) \
j64 = (uint32_t)(addr+i32_); \
else \
j64 = addr+i32_; \
BARRIER(BARRIER_MAYBE); \
JUMP(j64, 1); \
GETFLAGS; \
if(dyn->insts[ninst].x64.jmp_insts==-1 || \
CHECK_CACHE()) { \
/* out of the block */ \
i32 = dyn->insts[ninst].epilog-(dyn->native_size); \
Bcond(NO, i32); \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, j64, 0, ninst, rex.is32bits); \
} else { \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
SKIP_SEVL(i32); \
B(i32); \
} \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
SKIP_SEVL(i32); \
Bcond(YES, i32); \
}
GOCOND(0x80, "J", "Id");
#undef GO
case 0xAE:
nextop = F8;
switch((nextop>>3)&7) {
case 6:
INST_NAME("(unsupported) UWAIT Ed");
FAKEED;
UDF(0);
break;
default:
DEFAULT;
}
break;
case 0xC2:
INST_NAME("CMPSD Gx, Ex, Ib");
nextop = F8;
@@ -439,7 +488,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 0);
q0 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn, ninst);
static float addsubps[4] = {-1.f, 1.f, -1.f, 1.f};
MAYUSE(addsubps);
TABLE64(x2, (uintptr_t)&addsubps);
@@ -472,7 +521,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
ORRw_mask(x4, xZR, 1, 0); //0x80000000
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
for(int i=0; i<2; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
+116 -38
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
@@ -84,7 +84,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
q1 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn, ninst);
VLD128(q1, ed, fixedaddress);
}
GETGX_empty(q0);
@@ -99,7 +99,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
q1 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn, ninst);
VLD128(q1, ed, fixedaddress);
}
GETGX_empty(q0);
@@ -117,7 +117,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGX(v0, 1);
GETED(0);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
if(rex.w) {
SCVTFSx(d1, ed);
} else {
@@ -158,7 +158,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
MSR_fpsr(x5);
}
u8 = sse_setround(dyn, ninst, x1, x2, x3);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
FRINTIS(d1, q0);
x87_restoreround(dyn, ninst, u8);
FCVTZSxwS(gd, d1);
@@ -172,11 +172,41 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
}
break;
case 0x38: /* MAP */
opcode = F8;
switch(opcode) {
case 0xF6:
INST_NAME("ADOX Gd, Ed");
nextop = F8;
READFLAGS(X_OF);
SETFLAGS(X_OF, SF_SUBSET);
GETED(0);
GETGD;
MRS_nzcv(x3);
LSRw(x4, xFlags, F_OF);
BFIx(x3, x4, 29, 1); // set C
MSR_nzcv(x3); // load CC into ARM CF
IFX(X_OF) {
ADCSxw_REG(gd, gd, ed);
CSETw(x3, cCS);
BFIw(xFlags, x3, F_OF, 1);
} else {
ADCxw_REG(gd, gd, ed);
}
break;
default:
DEFAULT;
}
break;
case 0x51:
INST_NAME("SQRTSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(d0, 0, 0);
FSQRTS(d1, d0);
VMOVeS(v0, 0, d1, 0);
@@ -186,8 +216,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGX(v0, 1);
GETEXSS(v1, 0, 0);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
d1 = fpu_get_scratch(dyn, ninst);
// so here: F32: Imm8 = abcd efgh that gives => aBbbbbbc defgh000 00000000 00000000
// and want 1.0f = 0x3f800000
// so 00111111 10000000 00000000 00000000
@@ -203,7 +233,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGX(v0, 1);
GETEXSS(v1, 0, 0);
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
FMOVS_8(d0, 0b01110000); //1.0f
FDIVS(d0, d0, v1);
VMOVeS(v0, 0, d0, 0);
@@ -213,7 +243,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("ADDSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(d0, 0, 0);
FADDS(d1, v0, d0); // the high part of the vector is erased...
VMOVeS(v0, 0, d1, 0);
@@ -221,18 +251,31 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x59:
INST_NAME("MULSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
GETGX(d1, 1);
v1 = fpu_get_scratch(dyn, ninst);
GETEXSS(d0, 0, 0);
FMULS(d1, v0, d0);
VMOVeS(v0, 0, d1, 0);
if(!box64_dynarec_fastnan) {
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXS(v0, d0, d1); // propagate NAN
FCMEQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
FMULS(v1, d1, d0);
FCMEQS(q0, v1, v1); // 0 => out is NAN
VBIC(q0, v0, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(v1, v1, q0); // NAN -> -NAN
} else {
FMULS(v1, d1, d0);
}
VMOVeS(d1, 0, v1, 0);
break;
case 0x5A:
INST_NAME("CVTSS2SD Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETEXSS(v1, 0, 0);
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
FCVT_D_S(d0, v1);
VMOVeD(v0, 0, d0, 0);
break;
@@ -248,7 +291,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
ORRw_mask(x4, xZR, 1, 0); //0x80000000
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
for(int i=0; i<4; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
@@ -261,12 +304,11 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
}
break;
case 0x5C:
INST_NAME("SUBSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(d0, 0, 0);
FSUBS(d1, v0, d0);
VMOVeS(v0, 0, d1, 0);
@@ -278,12 +320,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEXSS(v1, 0, 0);
// MINSS: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
FMINNMS(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeS(v0, 0, d0, 0); // to not erase uper part
#else
FCMPS(v0, v1);
B_NEXT(cLS); //Less than or equal
B_NEXT(cCC); //Less than
VMOVeS(v0, 0, v1, 0); // to not erase uper part
#endif
break;
@@ -291,7 +333,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("DIVSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(d0, 0, 0);
FDIVS(d1, v0, d0);
VMOVeS(v0, 0, d1, 0);
@@ -303,12 +345,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEXSS(v1, 0, 0);
// MAXSS: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
FMAXNMS(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeS(v0, 0, d0, 0); // to not erase uper part
#else
FCMPS(v0, v1);
B_NEXT(cGE); //Greater than or equal
B_NEXT(cGT); //Greater than
VMOVeS(v0, 0, v1, 0); // to not erase uper part
#endif
break;
@@ -333,7 +375,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEX(v1, 0, 1) ;
GETGX(v0, 1);
u8 = F8;
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
if (u8 == 0b00000000 || u8 == 0b01010101 || u8 == 0b10101010 || u8 == 0b11111111) {
VDUPQ_16(d0, v1, (u8 & 3) + 4);
} else {
@@ -381,12 +423,40 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0xAE:
nextop = F8;
switch((nextop>>3)&7) {
case 2:
INST_NAME("(unsupported) WRFSBASE Ed");
FAKEED;
UDF(0);
break;
case 3:
INST_NAME("(unsupported) WRGSBASE Ed");
FAKEED;
UDF(0);
break;
case 5:
INST_NAME("(unsupported) INCSSPD/INCSSPQ Ed");
FAKEED;
UDF(0);
break;
case 6:
INST_NAME("(unsupported) UMONITOR Ed");
FAKEED;
UDF(0);
break;
default:
DEFAULT;
}
break;
case 0xB8:
INST_NAME("POPCNT Gd, Ed");
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE(x1);
nextop = F8;
v1 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn, ninst);
GETGD;
if(MODREG) {
GETED(0);
@@ -424,14 +494,18 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETED(0);
GETGD;
TSTxw_REG(ed, ed);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_CF, 1); // CF = is source 0?
IFX(X_CF) {
TSTxw_REG(ed, ed);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_CF, 1); // CF = is source 0?
}
RBITxw(x3, ed); // reverse
CLZxw(gd, x3); // x2 gets leading 0 == TZCNT
TSTxw_REG(gd, gd);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
IFX(X_ZF) {
TSTxw_REG(gd, gd);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
}
break;
case 0xBD:
INST_NAME("LZCNT Gd, Ed");
@@ -440,13 +514,17 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETED(0);
GETGD;
TSTxw_REG(ed, ed);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_CF, 1); // CF = is source 0?
IFX(X_CF) {
TSTxw_REG(ed, ed);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_CF, 1); // CF = is source 0?
}
CLZxw(gd, ed); // x2 gets leading 0 == LZCNT
TSTxw_REG(gd, gd);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
IFX(X_ZF) {
TSTxw_REG(gd, gd);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
}
break;
case 0xC2:
@@ -489,7 +567,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETEXSD(v1, 0, 0);
GETGX_empty(v0);
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
SXTL_32(v0, v1);
SCVTQFD(v0, v0); // there is only I64 -> Double vector conversion, not from i32
break;
+387 -29
View File
@@ -26,26 +26,55 @@
#include "custommem.h"
#include "bridge.h"
#define XMM0 0
#define XMM8 16
#define X870 8
#define EMM0 8
// Get a FPU scratch reg
int fpu_get_scratch(dynarec_arm_t* dyn)
int fpu_get_scratch(dynarec_arm_t* dyn, int ninst)
{
return SCRATCH0 + dyn->n.fpu_scratch++; // return an Sx
int ret = SCRATCH0 + dyn->n.fpu_scratch++;
if(dyn->n.ymm_used) printf_log(LOG_INFO, "Warning, getting a scratch register after getting some YMM at inst=%d\n", ninst);
if(dyn->n.neoncache[ret].t==NEON_CACHE_YMMR || dyn->n.neoncache[ret].t==NEON_CACHE_YMMW) {
// should only happens in step 0...
dyn->insts[ninst].purge_ymm |= (1<<dyn->n.neoncache[ret].n); // mark as purged
dyn->n.neoncache[ret].v = 0; // reset it
}
return ret;
}
// Get 2 consicutive FPU scratch reg
int fpu_get_double_scratch(dynarec_arm_t* dyn, int ninst)
{
int ret = SCRATCH0 + dyn->n.fpu_scratch;
if(dyn->n.ymm_used) printf_log(LOG_INFO, "Warning, getting a double scratch register after getting some YMM at inst=%d\n", ninst);
if(dyn->n.neoncache[ret].t==NEON_CACHE_YMMR || dyn->n.neoncache[ret].t==NEON_CACHE_YMMW) {
// should only happens in step 0...
dyn->insts[ninst].purge_ymm |= (1<<dyn->n.neoncache[ret].n); // mark as purged
dyn->n.neoncache[ret].v = 0; // reset it
}
if(dyn->n.neoncache[ret+1].t==NEON_CACHE_YMMR || dyn->n.neoncache[ret+1].t==NEON_CACHE_YMMW) {
// should only happens in step 0...
dyn->insts[ninst].purge_ymm |= (1<<dyn->n.neoncache[ret+1].n); // mark as purged
dyn->n.neoncache[ret+1].v = 0; // reset it
}
dyn->n.fpu_scratch+=2;
return ret;
}
// Reset scratch regs counter
void fpu_reset_scratch(dynarec_arm_t* dyn)
{
dyn->n.fpu_scratch = 0;
dyn->n.ymm_used = 0;
dyn->n.ymm_regs = 0;
dyn->n.ymm_write = 0;
dyn->n.ymm_removed = 0;
}
// Get a x87 double reg
int fpu_get_reg_x87(dynarec_arm_t* dyn, int t, int n)
int fpu_get_reg_x87(dynarec_arm_t* dyn, int ninst, int t, int n)
{
int i=X870;
while (dyn->n.fpuused[i]) ++i;
if(dyn->n.neoncache[i].t==NEON_CACHE_YMMR || dyn->n.neoncache[i].t==NEON_CACHE_YMMW) {
// should only happens in step 0...
dyn->insts[ninst].purge_ymm |= (1<<dyn->n.neoncache[i].n); // mark as purged
dyn->n.neoncache[i].v = 0; // reset it
}
dyn->n.fpuused[i] = 1;
dyn->n.neoncache[i].n = n;
dyn->n.neoncache[i].t = t;
@@ -57,17 +86,34 @@ void fpu_free_reg(dynarec_arm_t* dyn, int reg)
{
// TODO: check upper limit?
dyn->n.fpuused[reg] = 0;
if(dyn->n.neoncache[reg].t==NEON_CACHE_YMMR || dyn->n.neoncache[reg].t==NEON_CACHE_YMMW) {
dyn->n.ymm_removed |= 1<<dyn->n.neoncache[reg].n;
if(dyn->n.neoncache[reg].t==NEON_CACHE_YMMW)
dyn->n.ymm_write |= 1<<dyn->n.neoncache[reg].n;
if(reg>SCRATCH0)
dyn->n.ymm_regs |= (8LL+reg-SCRATCH0)<<(dyn->n.neoncache[reg].n*4);
else
dyn->n.ymm_regs |= ((uint64_t)(reg-EMM0))<<(dyn->n.neoncache[reg].n*4);
}
if(dyn->n.neoncache[reg].t!=NEON_CACHE_ST_F && dyn->n.neoncache[reg].t!=NEON_CACHE_ST_D && dyn->n.neoncache[reg].t!=NEON_CACHE_ST_I64)
dyn->n.neoncache[reg].v = 0;
if(dyn->n.fpu_scratch && reg==SCRATCH0+dyn->n.fpu_scratch-1)
--dyn->n.fpu_scratch;
}
// Get an MMX double reg
int fpu_get_reg_emm(dynarec_arm_t* dyn, int emm)
int fpu_get_reg_emm(dynarec_arm_t* dyn, int ninst, int emm)
{
dyn->n.fpuused[EMM0 + emm] = 1;
dyn->n.neoncache[EMM0 + emm].t = NEON_CACHE_MM;
dyn->n.neoncache[EMM0 + emm].n = emm;
dyn->n.news |= (1<<(EMM0 + emm));
return EMM0 + emm;
int ret = EMM0 + emm;
if(dyn->n.neoncache[ret].t==NEON_CACHE_YMMR || dyn->n.neoncache[ret].t==NEON_CACHE_YMMW) {
// should only happens in step 0...
dyn->insts[ninst].purge_ymm |= (1<<dyn->n.neoncache[ret].n); // mark as purged
dyn->n.neoncache[ret].v = 0; // reset it
}
dyn->n.fpuused[ret] = 1;
dyn->n.neoncache[ret].t = NEON_CACHE_MM;
dyn->n.neoncache[ret].n = emm;
dyn->n.news |= (1<<(ret));
return ret;
}
// Get an XMM quad reg
int fpu_get_reg_xmm(dynarec_arm_t* dyn, int t, int xmm)
@@ -84,14 +130,49 @@ int fpu_get_reg_xmm(dynarec_arm_t* dyn, int t, int xmm)
dyn->n.news |= (1<<i);
return i;
}
int internal_mark_ymm(dynarec_arm_t* dyn, int t, int ymm, int reg)
{
if((dyn->n.neoncache[reg].t==NEON_CACHE_YMMR) || (dyn->n.neoncache[reg].t==NEON_CACHE_YMMW)) {
if(dyn->n.neoncache[reg].n == ymm) {
// already there!
if(t==NEON_CACHE_YMMW)
dyn->n.neoncache[reg].t=t;
return reg;
}
} else if(!dyn->n.neoncache[reg].v) {
// found a slot!
dyn->n.neoncache[reg].t=t;
dyn->n.neoncache[reg].n=ymm;
dyn->n.news |= (1<<reg);
return reg;
}
return -1;
}
int is_ymm_to_keep(dynarec_arm_t* dyn, int reg, int k1, int k2, int k3)
{
if((k1!=-1) && (dyn->n.neoncache[reg].n==k1))
return 1;
if((k2!=-1) && (dyn->n.neoncache[reg].n==k2))
return 1;
if((k3!=-1) && (dyn->n.neoncache[reg].n==k3))
return 1;
if((dyn->n.neoncache[reg].t==NEON_CACHE_YMMR || dyn->n.neoncache[reg].t==NEON_CACHE_YMMW) && (dyn->n.ymm_used&(1<<dyn->n.neoncache[reg].n)))
return 1;
return 0;
}
// Reset fpu regs counter
static void fpu_reset_reg_neoncache(neoncache_t* n)
{
n->fpu_reg = 0;
for (int i=0; i<24; ++i) {
for (int i=0; i<32; ++i) {
n->fpuused[i]=0;
n->neoncache[i].v = 0;
}
n->ymm_regs = 0;
n->ymm_removed = 0;
n->ymm_used = 0;
n->ymm_write = 0;
}
void fpu_reset_reg(dynarec_arm_t* dyn)
@@ -343,10 +424,11 @@ int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
return ((dyn->insts[ninst].x64.barrier&BARRIER_FLOAT))?0:(isCacheEmpty(dyn, ninst)?0:1);
int ret = 0;
if(!i2) { // just purge
if(dyn->insts[ninst].n.stack_next) {
if(dyn->insts[ninst].n.stack_next)
return 1;
}
for(int i=0; i<24 && !ret; ++i)
if(dyn->insts[ninst].ymm0_out)
return 1;
for(int i=0; i<32 && !ret; ++i)
if(dyn->insts[ninst].n.neoncache[i].v) { // there is something at ninst for i
if(!(
(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
@@ -361,10 +443,12 @@ int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
if(dyn->insts[ninst].n.stack_next != dyn->insts[i2].n.stack-dyn->insts[i2].n.stack_push) {
return 1;
}
if(dyn->insts[ninst].ymm0_out && (dyn->insts[ninst].ymm0_out&~dyn->insts[i2].ymm0_in))
return 1;
neoncache_t cache_i2 = dyn->insts[i2].n;
neoncacheUnwind(&cache_i2);
for(int i=0; i<24; ++i) {
for(int i=0; i<32; ++i) {
if(dyn->insts[ninst].n.neoncache[i].v) { // there is something at ninst for i
if(!cache_i2.neoncache[i].v) { // but there is nothing at i2 for i
ret = 1;
@@ -374,6 +458,8 @@ int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
}
else if(dyn->insts[ninst].n.neoncache[i].t == NEON_CACHE_XMMR && cache_i2.neoncache[i].t == NEON_CACHE_XMMW)
{/* nothing */ }
else if(dyn->insts[ninst].n.neoncache[i].t == NEON_CACHE_YMMR && cache_i2.neoncache[i].t == NEON_CACHE_YMMW)
{/* nothing */ }
else
ret = 1;
}
@@ -408,7 +494,7 @@ void neoncacheUnwind(neoncache_t* cache)
}
if(cache->news) {
// remove the newly created neoncache
for(int i=0; i<24; ++i)
for(int i=0; i<32; ++i)
if(cache->news&(1<<i))
cache->neoncache[i].v = 0;
cache->news = 0;
@@ -446,7 +532,6 @@ void neoncacheUnwind(neoncache_t* cache)
// And now, rebuild the x87cache info with neoncache
cache->mmxcount = 0;
cache->fpu_scratch = 0;
cache->fpu_extra_qscratch = 0;
cache->fpu_reg = 0;
for(int i=0; i<8; ++i) {
cache->x87cache[i] = -1;
@@ -456,7 +541,7 @@ void neoncacheUnwind(neoncache_t* cache)
cache->ssecache[i*2+1].v = -1;
}
int x87reg = 0;
for(int i=0; i<24; ++i) {
for(int i=0; i<32; ++i) {
if(cache->neoncache[i].v) {
cache->fpuused[i] = 1;
switch (cache->neoncache[i].t) {
@@ -471,6 +556,10 @@ void neoncacheUnwind(neoncache_t* cache)
cache->ssecache[cache->neoncache[i].n].write = (cache->neoncache[i].t==NEON_CACHE_XMMW)?1:0;
++cache->fpu_reg;
break;
case NEON_CACHE_YMMR:
case NEON_CACHE_YMMW:
cache->fpuused[i] = 0; // YMM does not mark the fpu reg as used
break;
case NEON_CACHE_ST_F:
case NEON_CACHE_ST_D:
case NEON_CACHE_ST_I64:
@@ -488,11 +577,29 @@ void neoncacheUnwind(neoncache_t* cache)
cache->fpuused[i] = 0;
}
}
// add back removed YMM
if(cache->ymm_removed) {
for(int i=0; i<16; ++i)
if(cache->ymm_removed&(1<<i)) {
int reg = cache->ymm_regs>>(i*4)&15;
if(reg>7)
reg = reg - 8 + SCRATCH0;
else
reg = reg + EMM0;
if(cache->neoncache[reg].v)
printf_log(LOG_INFO, "Warning, recreating YMM%d on non empty slot %s", i, getCacheName(cache->neoncache[reg].t, cache->neoncache[reg].n));
cache->neoncache[reg].t = (cache->ymm_write&(1<<i))?NEON_CACHE_YMMW:NEON_CACHE_YMMR;
cache->neoncache[reg].n = i;
}
cache->ymm_regs = 0;
cache->ymm_write = cache->ymm_removed = 0;
}
cache->ymm_used = 0;
}
#define F8 *(uint8_t*)(addr++)
#define F32S64 (uint64_t)(int64_t)*(int32_t*)(addr+=4, addr-4)
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
// Get if ED will have the correct parity. Not emitting anything. Parity is 2 for DWORD or 3 for QWORD
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity, int delta)
{
(void)dyn; (void)ninst;
@@ -543,6 +650,8 @@ const char* getCacheName(int t, int n)
case NEON_CACHE_MM: sprintf(buff, "MM%d", n); break;
case NEON_CACHE_XMMW: sprintf(buff, "XMM%d", n); break;
case NEON_CACHE_XMMR: sprintf(buff, "xmm%d", n); break;
case NEON_CACHE_YMMW: sprintf(buff, "YMM%d", n); break;
case NEON_CACHE_YMMR: sprintf(buff, "ymm%d", n); break;
case NEON_CACHE_SCR: sprintf(buff, "Scratch"); break;
case NEON_CACHE_NONE: buff[0]='\0'; break;
}
@@ -553,7 +662,7 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
{
if(box64_dynarec_dump) {
printf_x64_instruction(rex.is32bits?my_context->dec32:my_context->dec, &dyn->insts[ninst].x64, name);
dynarec_log(LOG_NONE, "%s%p: %d emitted opcodes, inst=%d, barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d)",
dynarec_log(LOG_NONE, "%s%p: %d emitted opcodes, inst=%d, barrier=%d state=%d/%d/%d(%d:%d->%d:%d), %s=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d)",
(box64_dynarec_dump>1)?"\e[32m":"",
(void*)(dyn->native_start+dyn->insts[ninst].address),
dyn->insts[ninst].size/4,
@@ -562,6 +671,10 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
dyn->insts[ninst].x64.state_flags,
dyn->f.pending,
dyn->f.dfnone,
dyn->insts[ninst].f_entry.pending,
dyn->insts[ninst].f_entry.dfnone,
dyn->insts[ninst].f_exit.pending,
dyn->insts[ninst].f_exit.dfnone,
dyn->insts[ninst].x64.may_set?"may":"set",
dyn->insts[ninst].x64.set_flags,
dyn->insts[ninst].x64.gen_flags,
@@ -569,18 +682,38 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
dyn->insts[ninst].x64.need_before,
dyn->insts[ninst].x64.need_after,
dyn->smwrite, dyn->insts[ninst].will_write, dyn->insts[ninst].last_write);
if(dyn->insts[ninst].nat_flags_op) {
if(dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH && dyn->insts[ninst].before_nat_flags)
printf_log(LOG_NONE, " NF:%d/read:%x", dyn->insts[ninst].nat_flags_op, dyn->insts[ninst].before_nat_flags);
else
printf_log(LOG_NONE, " NF:%d", dyn->insts[ninst].nat_flags_op);
}
if(dyn->insts[ninst].use_nat_flags || dyn->insts[ninst].set_nat_flags || dyn->insts[ninst].need_nat_flags)
printf_log(LOG_NONE, " nf:%hhx/%hhx/%hhx", dyn->insts[ninst].set_nat_flags, dyn->insts[ninst].use_nat_flags, dyn->insts[ninst].need_nat_flags);
if(dyn->insts[ninst].invert_carry)
printf_log(LOG_NONE, " CI");
if(dyn->insts[ninst].gen_inverted_carry)
printf_log(LOG_NONE, " gic");
if(dyn->insts[ninst].before_nat_flags&NF_CF)
printf_log(LOG_NONE, " %ccb", dyn->insts[ninst].normal_carry_before?'n':'i');
if(dyn->insts[ninst].need_nat_flags&NF_CF)
printf_log(LOG_NONE, " %cc", dyn->insts[ninst].normal_carry?'n':'i');
if(dyn->insts[ninst].pred_sz) {
dynarec_log(LOG_NONE, ", pred=");
for(int ii=0; ii<dyn->insts[ninst].pred_sz; ++ii)
dynarec_log(LOG_NONE, "%s%d", ii?"/":"", dyn->insts[ninst].pred[ii]);
}
if(!dyn->insts[ninst].x64.alive)
dynarec_log(LOG_NONE, " not executed");
if(dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts>=0)
dynarec_log(LOG_NONE, ", jmp=%d", dyn->insts[ninst].x64.jmp_insts);
if(dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts==-1)
dynarec_log(LOG_NONE, ", jmp=out");
if(dyn->insts[ninst].x64.has_callret)
dynarec_log(LOG_NONE, ", callret");
if(dyn->last_ip)
dynarec_log(LOG_NONE, ", last_ip=%p", (void*)dyn->last_ip);
for(int ii=0; ii<24; ++ii) {
for(int ii=0; ii<32; ++ii) {
switch(dyn->insts[ninst].n.neoncache[ii].t) {
case NEON_CACHE_ST_D: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_ST_F: dynarec_log(LOG_NONE, " S%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
@@ -588,11 +721,27 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
case NEON_CACHE_MM: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_XMMW: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_XMMR: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_YMMW: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_YMMR: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
//case NEON_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_NONE:
default: break;
}
}
if(memcmp(dyn->insts[ninst].n.neoncache, dyn->n.neoncache, sizeof(dyn->n.neoncache))) {
dynarec_log(LOG_NONE, " %s(Change:", (box64_dynarec_dump>1)?"\e[1;91m":"");
for(int ii=0; ii<32; ++ii) if(dyn->insts[ninst].n.neoncache[ii].v!=dyn->n.neoncache[ii].v) {
dynarec_log(LOG_NONE, " V%d:%s", ii, getCacheName(dyn->n.neoncache[ii].t, dyn->n.neoncache[ii].n));
dynarec_log(LOG_NONE, "->%s", getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n));
}
dynarec_log(LOG_NONE, ")%s", (box64_dynarec_dump>1)?"\e[0;32m":"");
}
if(dyn->insts[ninst].n.ymm_used)
dynarec_log(LOG_NONE, " ymmUsed=%04x", dyn->insts[ninst].n.ymm_used);
if(dyn->ymm_zero || dyn->insts[ninst].ymm0_add || dyn->insts[ninst].ymm0_sub || dyn->insts[ninst].ymm0_out)
dynarec_log(LOG_NONE, " ymm0=(%04x/%04x+%04x-%04x=%04x)", dyn->ymm_zero, dyn->insts[ninst].ymm0_in, dyn->insts[ninst].ymm0_add ,dyn->insts[ninst].ymm0_sub, dyn->insts[ninst].ymm0_out);
if(dyn->insts[ninst].purge_ymm)
dynarec_log(LOG_NONE, " purgeYmm=%04x", dyn->insts[ninst].purge_ymm);
if(dyn->n.stack || dyn->insts[ninst].n.stack_next || dyn->insts[ninst].n.x87stack)
dynarec_log(LOG_NONE, " X87:%d/%d(+%d/-%d)%d", dyn->n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, dyn->insts[ninst].n.stack_pop, dyn->insts[ninst].n.x87stack);
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2)
@@ -640,25 +789,234 @@ static void sse_reset(neoncache_t* n)
{
for (int i=0; i<16; ++i)
n->ssecache[i].v = -1;
for (int i=0; i<32; ++i)
if(n->neoncache[i].t==NEON_CACHE_YMMR || n->neoncache[i].t==NEON_CACHE_YMMW)
n->neoncache[i].v = 0;
}
void fpu_reset(dynarec_arm_t* dyn)
void fpu_reset(dynarec_native_t* dyn)
{
x87_reset(&dyn->n);
mmx_reset(&dyn->n);
sse_reset(&dyn->n);
fpu_reset_reg(dyn);
dyn->ymm_zero = 0;
}
void fpu_reset_ninst(dynarec_arm_t* dyn, int ninst)
void fpu_reset_ninst(dynarec_native_t* dyn, int ninst)
{
x87_reset(&dyn->insts[ninst].n);
mmx_reset(&dyn->insts[ninst].n);
sse_reset(&dyn->insts[ninst].n);
fpu_reset_reg_neoncache(&dyn->insts[ninst].n);
}
int fpu_is_st_freed(dynarec_native_t* dyn, int ninst, int st)
{
return (dyn->n.tags&(0b11<<(st*2)))?1:0;
}
}
uint8_t mark_natflag(dynarec_arm_t* dyn, int ninst, uint8_t flag, int before)
{
if(dyn->insts[ninst].x64.set_flags && !before) {
dyn->insts[ninst].set_nat_flags |= flag;
if(dyn->insts[ninst].x64.use_flags) {
dyn->insts[ninst].use_nat_flags |= flag;
}
} else {
if(before)
dyn->insts[ninst].use_nat_flags_before |= flag;
else
dyn->insts[ninst].use_nat_flags |= flag;
}
return flag;
}
uint8_t flag2native(uint8_t flags)
{
uint8_t ret = 0;
#ifdef ARM64
if(flags&X_ZF) ret|=NF_EQ;
if(flags&X_SF) ret|=NF_SF;
if(flags&X_OF) ret|=NF_VF;
if(flags&X_CF) ret|=NF_CF;
#else
// no native flags on rv64 or la64
#endif
return ret;
}
int flagIsNative(uint8_t flags)
{
if(flags&(X_AF|X_PF)) return 0;
return 1;
}
static uint8_t getNativeFlagsUsed(dynarec_arm_t* dyn, int start, uint8_t flags)
{
// propagate and check wich flags are actually used
uint8_t used_flags = 0;
int nat_flags_used = 0;
int ninst = start;
while(ninst<dyn->size) {
//printf_log(LOG_INFO, "getNativeFlagsUsed ninst:%d/%d, flags=%x, used_flags=%x(%d), nat_flags_op_before:%x, nat_flags_op:%x, need_after:%x\n", ninst, start, flags, used_flags, nat_flags_used, dyn->insts[ninst].nat_flags_op_before, dyn->insts[ninst].nat_flags_op, flag2native(dyn->insts[ninst].x64.need_after));
// check if this is an opcode that generate flags but consume flags before
if(dyn->insts[ninst].nat_flags_op_before)
return 0;
// check if nat flags are used "before"
if(dyn->insts[ninst].use_nat_flags_before)
nat_flags_used = 1;
if(dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH && dyn->insts[ninst].use_nat_flags_before)
used_flags|=dyn->insts[ninst].use_nat_flags_before&flags;
// if the opcode generate flags, return
if(dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH && (start!=ninst)) {
if(used_flags&~dyn->insts[ninst].set_nat_flags) {
// check partial changes that would destroy flag state
if(dyn->insts[ninst].use_nat_flags_before&flags)
return nat_flags_used?used_flags:0;
// but also check if there is before needed
return 0;
}
return nat_flags_used?used_flags:0;
}
// check if there is a callret barrier
if(dyn->insts[ninst].x64.has_callret)
return 0;
// check if nat flags are used
if(dyn->insts[ninst].use_nat_flags)
nat_flags_used = 1;
// check if flags are used, but not the natives ones
if(ninst!=start && dyn->insts[ninst].x64.use_flags) {
if((flag2native(dyn->insts[ninst].x64.use_flags)&~(dyn->insts[ninst].use_nat_flags))&used_flags)
return 0;
// also check if the gen flags are compatible
if((dyn->insts[ninst].use_nat_flags)&~flags)
return 0;
}
// check if flags are generated without native option
if((start!=ninst) && dyn->insts[ninst].x64.gen_flags && (flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after)&used_flags)) {
if(used_flags&~flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after))
return 0; // partial covert, not supported for now (TODO: this might be fixable)
else
return nat_flags_used?used_flags:0; // full covert... End of propagation
}
// check if flags are still needed
if(!(flag2native(dyn->insts[ninst].x64.need_after)&flags))
return nat_flags_used?used_flags:0;
// check if flags are destroyed, cancel the use then
if(dyn->insts[ninst].nat_flags_op && (start!=ninst))
return 0;
// update used flags
used_flags |= (flag2native(dyn->insts[ninst].x64.need_after)&flags);
// go next
if(!dyn->insts[ninst].x64.has_next) {
// check if it's a jump to an opcode with only 1 preds, then just follow the jump
int jmp = dyn->insts[ninst].x64.jmp_insts;
if(dyn->insts[ninst].x64.jmp && (jmp!=-1) && (getNominalPred(dyn, jmp)==ninst))
ninst = jmp;
else
return nat_flags_used?used_flags:0;
} else
++ninst;
}
return nat_flags_used?used_flags:0;
}
static void propagateNativeFlags(dynarec_arm_t* dyn, int start)
{
int ninst = start;
// those are the flags generated by the opcode and used later on
uint8_t flags = dyn->insts[ninst].set_nat_flags&flag2native(dyn->insts[ninst].x64.need_after);
//check if they are actualy used before starting
//printf_log(LOG_INFO, "propagateNativeFlags called for start=%d, flags=%x, will need:%x\n", start, flags, flag2native(dyn->insts[ninst].x64.need_after));
if(!flags) return;
// also check if some native flags are used but not genereated here
if(flag2native(dyn->insts[ninst].x64.need_after)&~flags) return;
uint8_t used_flags = getNativeFlagsUsed(dyn, start, flags);
//printf_log(LOG_INFO, " will use:%x, carry:%d, generate inverted carry:%d\n", used_flags, used_flags&NF_CF, dyn->insts[ninst].gen_inverted_carry);
if(!used_flags) return; // the flags wont be used, so just cancel
int nc = dyn->insts[ninst].gen_inverted_carry?0:1;
int carry = used_flags&NF_CF;
// propagate
while(ninst<dyn->size) {
// check if this is an opcode that generate flags but consume flags before
if((start!=ninst) && dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH) {
if(dyn->insts[ninst].use_nat_flags_before) {
dyn->insts[ninst].before_nat_flags |= used_flags;
if(carry) dyn->insts[ninst].normal_carry_before = nc;
}
// if the opcode generate flags, return
return;
}
// check if flags are generated without native option
if((start!=ninst) && dyn->insts[ninst].x64.gen_flags && (flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after)&used_flags))
return;
// mark the opcode
uint8_t use_flags = flag2native(dyn->insts[ninst].x64.need_before|dyn->insts[ninst].x64.need_after);
if(dyn->insts[ninst].x64.use_flags) use_flags |= flag2native(dyn->insts[ninst].x64.use_flags); // should not change anything
//printf_log(LOG_INFO, " marking ninst=%d with %x | %x&%x => %x\n", ninst, dyn->insts[ninst].need_nat_flags, used_flags, use_flags, dyn->insts[ninst].need_nat_flags | (used_flags&use_flags));
dyn->insts[ninst].need_nat_flags |= used_flags&use_flags;
if(carry) dyn->insts[ninst].normal_carry = nc;
if(carry && dyn->insts[ninst].invert_carry) nc = 0;
// check if flags are still needed
if(!(flag2native(dyn->insts[ninst].x64.need_after)&used_flags))
return;
// go next
if(!dyn->insts[ninst].x64.has_next) {
// check if it's a jump to an opcode with only 1 preds, then just follow the jump
int jmp = dyn->insts[ninst].x64.jmp_insts;
if(dyn->insts[ninst].x64.jmp && (jmp!=-1) && (getNominalPred(dyn, jmp)==ninst))
ninst = jmp;
else
return;
} else
++ninst;
}
}
void updateNativeFlags(dynarec_native_t* dyn)
{
if(!box64_dynarec_nativeflags)
return;
// backward check if native flags are used
for(int ninst=0; ninst<dyn->size; ++ninst)
if(flag2native(dyn->insts[ninst].x64.gen_flags) && (dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH)) {
propagateNativeFlags(dyn, ninst);
}
}
void rasNativeState(dynarec_arm_t* dyn, int ninst)
{
dyn->insts[ninst].nat_flags_op = dyn->insts[ninst].set_nat_flags = dyn->insts[ninst].use_nat_flags = dyn->insts[ninst].need_nat_flags = 0;
}
int nativeFlagsNeedsTransform(dynarec_arm_t* dyn, int ninst)
{
int jmp = dyn->insts[ninst].x64.jmp_insts;
if(jmp<0)
return 0;
if(!dyn->insts[ninst].x64.need_after || !dyn->insts[jmp].x64.need_before)
return 0;
if(dyn->insts[ninst].set_nat_flags)
return 0;
uint8_t flags_before = dyn->insts[ninst].need_nat_flags;
uint8_t nc_before = dyn->insts[ninst].normal_carry;
if(dyn->insts[ninst].invert_carry)
nc_before = 0;
uint8_t flags_after = dyn->insts[jmp].need_nat_flags;
uint8_t nc_after = dyn->insts[jmp].normal_carry;
if(dyn->insts[jmp].nat_flags_op==NAT_FLAG_OP_TOUCH) {
flags_after = dyn->insts[jmp].before_nat_flags;
nc_after = dyn->insts[jmp].normal_carry_before;
}
uint8_t flags_x86 = flag2native(dyn->insts[jmp].x64.need_before);
flags_x86 &= ~flags_after;
if((flags_before&NF_CF) && (flags_after&NF_CF) && (nc_before!=nc_after))
return 1;
// all flags_after should be present and none remaining flags_x86
if(((flags_before&flags_after)!=flags_after) || (flags_before&flags_x86))
return 1;
return 0;
}
+25 -4
View File
@@ -4,21 +4,32 @@
#include "../dynarec_native_functions.h"
#define SCRATCH0 24
#define XMM0 0
#define XMM8 16
#define X870 8
#define EMM0 8
// Get an FPU scratch reg
int fpu_get_scratch(dynarec_arm_t* dyn);
int fpu_get_scratch(dynarec_arm_t* dyn, int ninst);
// Get 2 consecutive FPU scratch reg
int fpu_get_double_scratch(dynarec_arm_t* dyn, int ninst);
// Reset scratch regs counter
void fpu_reset_scratch(dynarec_arm_t* dyn);
// Get an x87 double reg
int fpu_get_reg_x87(dynarec_arm_t* dyn, int t, int n);
int fpu_get_reg_x87(dynarec_arm_t* dyn, int ninst, int t, int n);
// Get an MMX double reg
int fpu_get_reg_emm(dynarec_arm_t* dyn, int emm);
int fpu_get_reg_emm(dynarec_arm_t* dyn, int ninst, int emm);
// Get an XMM quad reg
int fpu_get_reg_xmm(dynarec_arm_t* dyn, int t, int xmm);
// Free a FPU/MMX/XMM reg
void fpu_free_reg(dynarec_arm_t* dyn, int reg);
// Reset fpu regs counter
void fpu_reset_reg(dynarec_arm_t* dyn);
// internal YMM handling
int internal_mark_ymm(dynarec_arm_t* dyn, int t, int ymm, int reg);
// is ymm neoncache[reg] one of k1, k2, k3?
int is_ymm_to_keep(dynarec_arm_t* dyn, int reg, int k1, int k2, int k3);
// ---- Neon cache functions
// Get type for STx
@@ -40,6 +51,16 @@ int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b); // with
// Do not allow i64 type
int neoncache_no_i64(dynarec_arm_t* dyn, int ninst, int st, int a);
// transform x86 flags to native flags
uint8_t flag2native(uint8_t flags);
// mark a instruction as using/generating flags. return flag
uint8_t mark_natflag(dynarec_arm_t* dyn, int ninst, uint8_t flag, int before);
// propage the use of nativeflags or not (done between step 0 and step 1)
void updateNativeFlags(dynarec_arm_t* dyn);
// raz arm speicifc state when an opcode is unused
void rasNativeState(dynarec_arm_t* dyn, int ninst);
// check if natives flags needs some tranform to/from x86 flags
int nativeFlagsNeedsTransform(dynarec_arm_t* dyn, int ninst);
// FPU Cache transformation (for loops) // Specific, need to be written by backend
int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst);
@@ -47,7 +68,7 @@ int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst);
// Undo the changes of a neoncache to get the status before the instruction
void neoncacheUnwind(neoncache_t* cache);
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
// Get if ED will have the correct parity. Not emitting anything. Parity is 2 for DWORD or 3 for QWORD
int getedparity(dynarec_native_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity, int delta);
const char* getCacheName(int t, int n);
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+6 -2
View File
@@ -2,10 +2,14 @@
#include "arm64_emitter.h"
#define EMIT(A) *block = (A); ++block
#define EMIT(A) \
do { \
*block = (A); \
++block; \
} while (0)
void CreateJmpNext(void* addr, void* next)
{
uint32_t* block = (uint32_t*)addr;
LDRx_literal(x2, (intptr_t)next - (intptr_t)addr);
BR(x2);
}
}
+19 -3
View File
@@ -5,7 +5,7 @@
dyn->insts[ninst].x64.addr = addr; \
if(ninst) dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr
#define MESSAGE(A, ...)
#define MESSAGE(A, ...) do {} while (0)
#define MAYSETFLAGS() dyn->insts[ninst].x64.may_set = 1
#define READFLAGS(A) \
dyn->insts[ninst].x64.use_flags = A; dyn->f.dfnone = 1;\
@@ -18,7 +18,6 @@
#define EMIT(A) dyn->native_size+=4
#define JUMP(A, C) add_jump(dyn, ninst); add_next(dyn, (uintptr_t)A); SMEND(); dyn->insts[ninst].x64.jmp = A; dyn->insts[ninst].x64.jmp_cond = C; dyn->insts[ninst].x64.jmp_insts = 0
#define BARRIER(A) if(A!=BARRIER_MAYBE) {fpu_purgecache(dyn, ninst, 0, x1, x2, x3); dyn->insts[ninst].x64.barrier = A;} else dyn->insts[ninst].barrier_maybe = 1
#define BARRIER_NEXT(A) dyn->insts[ninst].x64.barrier_next = A
#define SET_HASCALLRET() dyn->insts[ninst].x64.has_callret = 1
#define NEW_INST \
++dyn->size; \
@@ -31,12 +30,14 @@
#define INST_EPILOG \
dyn->insts[ninst].f_exit = dyn->f; \
dyn->insts[ninst].n = dyn->n; \
if(dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH && !dyn->insts[ninst].set_nat_flags) \
dyn->insts[ninst].nat_flags_op=NAT_FLAG_OP_UNUSABLE; \
dyn->insts[ninst].x64.has_next = (ok>0)?1:0;
#define INST_NAME(name)
#define DEFAULT \
--dyn->size; \
*ok = -1; \
if(box64_dynarec_log>=LOG_INFO || box64_dynarec_dump || box64_dynarec_missing) {\
if(box64_dynarec_log>=LOG_INFO || box64_dynarec_dump || box64_dynarec_missing==1) {\
dynarec_log(LOG_NONE, "%p: Dynarec stopped because of %sOpcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
(void*)ip, rex.is32bits?"x86 ":"x64 ",\
PKip(0), \
@@ -48,3 +49,18 @@
printFunctionAddr(ip, " => "); \
dynarec_log(LOG_NONE, "\n"); \
}
#define FEMIT(A) dyn->insts[ninst].nat_flags_op = dyn->insts[ninst].x64.set_flags?NAT_FLAG_OP_TOUCH:NAT_FLAG_OP_UNUSABLE
#define IFNATIVE(A) if(mark_natflag(dyn, ninst, A, 0))
#define IFNATIVEN(A) if(mark_natflag(dyn, ninst, A, 0))
#define IFX(A) if((dyn->insts[ninst].x64.set_flags&(A)))
#define IFX2(A, B) if((dyn->insts[ninst].x64.set_flags&(A)) B)
#define IFX_PENDOR0 if((dyn->insts[ninst].x64.set_flags&(X_PEND) || !dyn->insts[ninst].x64.set_flags))
#define IFXX(A) if((dyn->insts[ninst].x64.set_flags==(A)))
#define IFX2X(A, B) if((dyn->insts[ninst].x64.set_flags==(A) || dyn->insts[ninst].x64.set_flags==(B) || dyn->insts[ninst].x64.set_flags==((A)|(B))))
#define IFXN(A, B) if((dyn->insts[ninst].x64.set_flags&(A) && !(dyn->insts[ninst].x64.set_flags&(B))))
#define IFXNATIVE(X, N) if((dyn->insts[ninst].x64.set_flags&(X)) && mark_natflag(dyn, ninst, N, 0))
#define GEN_INVERTED_CARRY() dyn->insts[ninst].gen_inverted_carry = 1
#define IFNATIVE_BEFORE(A) if(mark_natflag(dyn, ninst, A, 1))
#define INVERT_CARRY(A) dyn->insts[ninst].invert_carry = 1
#define INVERT_CARRY_BEFORE(A) dyn->insts[ninst].invert_carry_before = 1
+12 -2
View File
@@ -1,7 +1,17 @@
#define INIT
#define FINI
#define MESSAGE(A, ...)
#define EMIT(A)
#define MESSAGE(A, ...) do {} while (0)
#define EMIT(A) do {} while (0)
#define MAYSETFLAGS() dyn->insts[ninst].x64.may_set = 1
#define SET_NODF() \
if(!dyn->insts[ninst].x64.gen_flags && !dyn->insts[ninst].x64.use_flags) \
propagate_nodf(dyn, ninst); \
dyn->f.dfnone = 0
#define SETFLAGS(A,B) \
dyn->insts[ninst].x64.set_flags = A; \
dyn->insts[ninst].x64.state_flags = (B)&~SF_DF; \
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?(((B)==SF_SET_NODF)?0:1):0;
#define NEW_INST \
dyn->insts[ninst].f_entry = dyn->f; \
dyn->n.combined1 = dyn->n.combined2 = 0;\
+3 -2
View File
@@ -5,14 +5,15 @@
dyn->insts_size += 1+((dyn->insts[ninst].x64.size>(dyn->insts[ninst].size/4))?dyn->insts[ninst].x64.size:(dyn->insts[ninst].size/4))/15; \
}
#define MESSAGE(A, ...)
#define MESSAGE(A, ...) do {} while (0)
#define EMIT(A) do{dyn->insts[ninst].size+=4; dyn->native_size+=4;}while(0)
#define NEW_INST \
if(ninst) { \
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
dyn->insts_size += 1+((dyn->insts[ninst-1].x64.size>(dyn->insts[ninst-1].size/4))?dyn->insts[ninst-1].x64.size:(dyn->insts[ninst-1].size/4))/15; \
dyn->insts[ninst].ymm0_pass2 = dyn->ymm_zero; \
}
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->native_size;
#define INST_NAME(name)
#define TABLE64(A, V) {Table64(dyn, (V), 2); EMIT(0);}
#define FTABLE64(A, V) {mmx87_regs_t v = {.d = V}; Table64(dyn, v.q, 2); EMIT(0);}
#define FTABLE64(A, V) {mmx87_regs_t v = {.d = V}; Table64(dyn, v.q, 2); EMIT(0);}
+5 -2
View File
@@ -14,8 +14,11 @@
#define MESSAGE(A, ...) if(box64_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
#define NEW_INST \
if(ninst) \
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst-1].x64.size, dyn->insts[ninst-1].size/4);
if(ninst) { \
if(dyn->insts[ninst].address!=(uintptr_t)dyn->block-(uintptr_t)dyn->native_start) dyn->abort = 1; \
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst-1].x64.size, dyn->insts[ninst-1].size/4); \
dyn->insts[ninst].ymm0_pass3 = dyn->ymm_zero; \
}
#define INST_EPILOG
#define INST_NAME(name) inst_name_pass3(dyn, ninst, name, rex)
#define TABLE64(A, V) {int val64offset = Table64(dyn, (V), 3); MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset);}
+53 -10
View File
@@ -9,6 +9,20 @@ typedef struct instsize_s instsize_t;
#define BARRIER_MAYBE 8
#define NF_EQ (1<<0)
#define NF_SF (1<<1)
#define NF_VF (1<<2)
#define NF_CF (1<<3)
// Nothing happens to the native flags
#define NAT_FLAG_OP_NONE 0
// Native flags are touched on this opcode
#define NAT_FLAG_OP_TOUCH 1
// Native flags are destroyed and unusable
#define NAT_FLAG_OP_UNUSABLE 2
// Native flags usaged are canceled here
#define NAT_FLAG_OP_CANCELED 3
#define NEON_CACHE_NONE 0
#define NEON_CACHE_ST_D 1
#define NEON_CACHE_ST_F 2
@@ -16,7 +30,9 @@ typedef struct instsize_s instsize_t;
#define NEON_CACHE_MM 4
#define NEON_CACHE_XMMW 5
#define NEON_CACHE_XMMR 6
#define NEON_CACHE_SCR 7
#define NEON_CACHE_YMMW 7
#define NEON_CACHE_YMMR 8
#define NEON_CACHE_SCR 9
typedef union neon_cache_s {
int8_t v;
struct {
@@ -33,7 +49,7 @@ typedef union sse_cache_s {
} sse_cache_t;
typedef struct neoncache_s {
// Neon cache
neon_cache_t neoncache[24];
neon_cache_t neoncache[32];
int8_t stack;
int8_t stack_next;
int8_t stack_pop;
@@ -51,17 +67,21 @@ typedef struct neoncache_s {
int16_t tags; // similar to fpu_tags
int8_t mmxcache[8]; // cache status for the 8 MMX registers
sse_cache_t ssecache[16]; // cache status for the 16 SSE(2) registers
int8_t fpuused[24]; // all 0..24 double reg from fpu, used by x87, sse and mmx
int8_t fpuused[32]; // all neon regs, used by x87, mmx, sse and avx
int8_t x87stack; // cache stack counter
int8_t mmxcount; // number of mmx register used (not both mmx and x87 at the same time)
int8_t fpu_scratch; // scratch counter
int8_t fpu_extra_qscratch; // some opcode need an extra quad scratch register
int8_t fpu_reg; // x87/sse/mmx reg counter
uint16_t ymm_used; // mask of the ymm regs used in this opcode
uint64_t ymm_regs; // 4bits (0-15) position of 16 ymmXX regs removed
uint16_t ymm_write; // 1bits of ymmXX removed write
uint16_t ymm_removed; // 1bits if ymmXX was removed
} neoncache_t;
typedef struct flagcache_s {
int pending; // is there a pending flags here, or to check?
int dfnone; // if deferred flags is already set to df_none
uint8_t dfnone; // if deferred flags is already set to df_none
uint8_t dfnone_here;// defered flags is cleared in this opcode
} flagcache_t;
typedef struct instruction_arm64_s {
@@ -78,10 +98,30 @@ typedef struct instruction_arm64_s {
uintptr_t marklock;
int pass2choice;// value for choices that are fixed on pass2 for pass3
uintptr_t natcall;
int retn;
uint16_t retn;
uint16_t purge_ymm; // need to purge some ymm
uint16_t ymm0_in; // bitmap of ymm to zero at purge
uint16_t ymm0_add; // the ymm0 added by the opcode
uint16_t ymm0_sub; // the ymm0 removed by the opcode
uint16_t ymm0_out; // the ymm0 at th end of the opcode
uint16_t ymm0_pass2, ymm0_pass3;
uint8_t barrier_maybe;
uint8_t will_write;
uint8_t last_write;
uint8_t will_write:2; // [strongmem] will write to memory
uint8_t last_write:1; // [strongmem] the last write in a SEQ
uint8_t lock:1; // [strongmem] lock semantic
uint8_t wfe:1; // opcode uses sevl + wfe
uint8_t set_nat_flags; // 0 or combinaison of native flags define
uint8_t use_nat_flags; // 0 or combinaison of native flags define
uint8_t use_nat_flags_before; // 0 or combinaison of native flags define
uint8_t nat_flags_op:4;// what happens to native flags here
uint8_t nat_flags_op_before:4;// what happens to native flags here
uint8_t before_nat_flags; // 0 or combinaison of native flags define
uint8_t need_nat_flags;
unsigned gen_inverted_carry:1;
unsigned normal_carry:1;
unsigned normal_carry_before:1;
unsigned invert_carry:1; // this opcode force an inverted carry
unsigned df_notneeded:1;
flagcache_t f_exit; // flags status at end of instruction
neoncache_t n; // neoncache at end of instruction (but before poping)
flagcache_t f_entry; // flags status before the instruction begin
@@ -118,8 +158,8 @@ typedef struct dynarec_arm_s {
uintptr_t forward_to; // address of the next jump to (to check if everything is ok)
int32_t forward_size; // size at the forward point
int forward_ninst; // ninst at the forward point
uint16_t ymm_zero; // bitmap of ymm to zero at purge
uint8_t smwrite; // for strongmem model emulation
uint8_t smread;
uint8_t doublepush;
uint8_t doublepop;
uint8_t always_test;
@@ -130,6 +170,7 @@ void add_next(dynarec_arm_t *dyn, uintptr_t addr);
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
void add_jump(dynarec_arm_t *dyn, int ninst);
int get_first_jump(dynarec_arm_t *dyn, int next);
int get_first_jump_addr(dynarec_arm_t *dyn, uintptr_t next);
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n);
int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
@@ -140,9 +181,11 @@ void CreateJmpNext(void* addr, void* next);
#define GO_TRACE(A, B, s0) \
GETIP(addr); \
MOVx_REG(x1, xRIP); \
MRS_nzcv(s0); \
STORE_XEMU_CALL(xRIP); \
MOV32w(x2, B); \
CALL(A, -1); \
CALL_(A, -1, s0); \
MSR_nzcv(s0); \
LOAD_XEMU_CALL(xRIP)
#endif //__DYNAREC_ARM_PRIVATE_H_
+18 -7
View File
@@ -19,6 +19,7 @@
#include "dynarec_private.h"
#include "elfloader.h"
#include "bridge.h"
#include "signals.h"
#include "dynarec_native.h"
#include "native_lock.h"
@@ -31,9 +32,9 @@ uint32_t X31_hash_code(void* addr, int len)
{
if(!len) return 0;
uint8_t* p = (uint8_t*)addr;
int32_t h = *p;
for (--len, ++p; len; --len, ++p) h = (h << 5) - h + (int32_t)*p;
return (uint32_t)h;
int32_t h = *p;
for (--len, ++p; len; --len, ++p) h = (h << 5) - h + (int32_t)*p;
return (uint32_t)h;
}
dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock)
@@ -48,7 +49,7 @@ dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock)
mutex_lock(&my_context->mutex_dyndump);
db->done = 0;
db->gone = 1;
int db_size = db->x64_size;
uintptr_t db_size = db->x64_size;
if(db_size && my_context) {
uint32_t n = rb_get(my_context->db_sizes, db_size);
if(n>1)
@@ -94,7 +95,7 @@ void FreeDynablock(dynablock_t* db, int need_lock)
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->actual_block, db->size);
db->done = 0;
db->gone = 1;
int db_size = db->x64_size;
uintptr_t db_size = db->x64_size;
if(db_size && my_context) {
uint32_t n = rb_get(my_context->db_sizes, db_size);
if(n>1)
@@ -198,9 +199,13 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
{
if(hasAlternate((void*)addr))
return NULL;
const uint32_t req_prot = (box64_pagesize==4096)?(PROT_EXEC|PROT_READ):PROT_READ;
dynablock_t* block = getDB(addr);
if(block || !create)
if(block || !create) {
if(block && getNeedTest(addr) && (getProtection(addr)&req_prot)!=req_prot)
block = NULL;
return block;
}
if(need_lock) {
if(box64_dynarec_wait) {
@@ -211,11 +216,17 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
}
block = getDB(addr); // just in case
if(block) {
if(block && getNeedTest(addr) && (getProtection_fast(addr)&req_prot)!=req_prot)
block = NULL;
mutex_unlock(&my_context->mutex_dyndump);
return block;
}
}
if((getProtection_fast(addr)&req_prot)!=req_prot) {// cannot be run, get out of the Dynarec
if(need_lock)
mutex_unlock(&my_context->mutex_dyndump);
return NULL;
}
block = AddNewDynablock(addr);
// fill the block
+3 -2
View File
@@ -10,14 +10,15 @@ typedef struct dynablock_s {
void* block; // block-sizeof(void*) == self
void* actual_block; // the actual start of the block (so block-sizeof(void*))
struct dynablock_s* previous; // a previous block that might need to be freed
int size;
void* x64_addr;
uintptr_t x64_size;
int size;
uint32_t hash;
uint8_t done;
uint8_t gone;
uint8_t always_test;
uint8_t dirty; // if need to be tested as soon as it's created
uint8_t always_test:1;
uint8_t is32bits:1;
int isize;
instsize_t* instsize;
void* jmpnext; // a branch jmpnext code when block is marked
+46 -16
View File
@@ -34,10 +34,18 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
#ifdef HAVE_TRACE
if(!addr) {
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x64addr=%p/%s)\n", x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, db?getAddrFunctionName(getX64Address(db, (uintptr_t)x2-4)):"(nil)");
printf_log(LOG_INFO, "Warning, jumping to NULL address from %p (db=%p, x64addr=%p/%s)\n", x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, db?getAddrFunctionName(getX64Address(db, (uintptr_t)x2-4)):"(nil)");
} else if(addr<0x10000) {
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
printf_log(LOG_NONE, "Warning, jumping to low address %p from %p (db=%p, x64addr=%p/%s)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, db?getAddrFunctionName(getX64Address(db, (uintptr_t)x2-4)):"(nil)");
printf_log(LOG_INFO, "Warning, jumping to low address %p from %p (db=%p, x64addr=%p/%s)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, db?getAddrFunctionName(getX64Address(db, (uintptr_t)x2-4)):"(nil)");
#ifdef BOX32
} else if(emu->segs[_CS]==0x23 && addr>0x100000000LL) {
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
printf_log(LOG_INFO, "Warning, jumping to high address %p from %p (db=%p, x64addr=%p/%s)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, db?getAddrFunctionName(getX64Address(db, (uintptr_t)x2-4)):"(nil)");
} else if(!memExist(addr)) {
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
printf_log(LOG_INFO, "Warning, jumping to an unmapped address %p from %p (db=%p, x64addr=%p/%s)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, db?getAddrFunctionName(getX64Address(db, (uintptr_t)x2-4)):"(nil)");
#endif
}
#endif
void * jblock;
@@ -95,19 +103,22 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
uint64_t old_rsi = R_RSI;
uint64_t old_rbp = R_RBP;
uint64_t old_rip = R_RIP;
x64flags_t old_eflags = emu->eflags;
// save defered flags
deferred_flags_t old_df = emu->df;
multiuint_t old_op1 = emu->op1;
multiuint_t old_op2 = emu->op2;
multiuint_t old_res = emu->res;
multiuint_t old_op1_sav= emu->op1_sav;
multiuint_t old_res_sav= emu->res_sav;
deferred_flags_t old_df_sav= emu->df_sav;
// uc_link
x64_ucontext_t* old_uc_link = emu->uc_link;
void* old_uc_link = emu->uc_link;
emu->uc_link = NULL;
PushExit(emu);
#ifdef BOX32
if(box64_is32bits)
PushExit_32(emu);
else
#endif
PushExit(emu);
R_RIP = addr;
emu->df = d_none;
DynaRun(emu);
@@ -123,10 +134,8 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
emu->op1 = old_op1;
emu->op2 = old_op2;
emu->res = old_res;
emu->op1_sav = old_op1_sav;
emu->res_sav = old_res_sav;
emu->df_sav = old_df_sav;
// and the old registers
emu->eflags = old_eflags;
R_RBX = old_rbx;
R_RDI = old_rdi;
R_RSI = old_rsi;
@@ -137,6 +146,10 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
}
int my_setcontext(x64emu_t* emu, void* ucp);
#ifdef BOX32
int my32_setcontext(x64emu_t* emu, void* ucp);
#endif
extern int running32bits;
void DynaRun(x64emu_t* emu)
{
// prepare setjump for signal handling
@@ -147,7 +160,7 @@ void DynaRun(x64emu_t* emu)
uintptr_t old_savesp = emu->xSPSave;
#endif
emu->flags.jmpbuf_ready = 0;
int is32bits = (emu->segs[_CS]==0x23);
while(!(emu->quit)) {
if(!emu->jmpbuf || (emu->flags.need_jmpbuf && emu->jmpbuf!=jmpbuf)) {
emu->jmpbuf = jmpbuf;
@@ -180,7 +193,22 @@ void DynaRun(x64emu_t* emu)
Run(emu, 0);
#ifdef DYNAREC
else {
int is32bits = (emu->segs[_CS]==0x23);
int newis32bits = (emu->segs[_CS]==0x23);
if(newis32bits!=is32bits) {
is32bits = newis32bits;
if(is32bits) {
// Zero upper part of the 32bits regs
R_RAX = R_EAX;
R_RBX = R_EBX;
R_RCX = R_ECX;
R_RDX = R_EDX;
R_RSP = R_ESP;
R_RBP = R_EBP;
R_RSI = R_ESI;
R_RDI = R_EDI;
running32bits = 1;
}
}
dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1, is32bits);
if(!block || !block->block || !block->done || ACCESS_FLAG(F_TF)) {
skip = 0;
@@ -194,9 +222,6 @@ void DynaRun(x64emu_t* emu)
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts (hash=0x%x) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, block->hash, emu);
// block is here, let's run it!
native_prolog(emu, block->block);
extern int running32bits;
if(emu->segs[_CS]==0x23)
running32bits = 1;
}
if(emu->fork) {
int forktype = emu->fork;
@@ -206,7 +231,12 @@ void DynaRun(x64emu_t* emu)
}
if(emu->quit && emu->uc_link) {
emu->quit = 0;
my_setcontext(emu, emu->uc_link);
#ifdef BOX32
if(box64_is32bits)
my32_setcontext(emu, emu->uc_link);
else
#endif
my_setcontext(emu, emu->uc_link);
}
}
#endif
+22 -6
View File
@@ -9,14 +9,20 @@
#define ADDITIONNAL_DEFINITION() \
int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst);
#define OTHER_CACHE() \
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=2;
#define OTHER_CACHE() \
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=2; \
if (nativeFlagsNeedsTransform(dyn, ninst)) ret|=4;
#include "arm64/arm64_printer.h"
#include "arm64/dynarec_arm64_private.h"
#include "arm64/dynarec_arm64_functions.h"
// Limit here is defined by LD litteral, that is 19bits
#define MAXBLOCK_SIZE ((1<<19)-200)
#define RAZ_SPECIFIC(A, N) rasNativeState(A, N)
#define UPDATE_SPECIFICS(A) updateNativeFlags(A)
#define PREUPDATE_SPECIFICS(A)
#elif defined(LA64)
#define instruction_native_t instruction_la64_t
@@ -33,22 +39,32 @@
#include "la64/dynarec_la64_functions.h"
// Limit here is unconditionnal jump, that is signed 28bits
#define MAXBLOCK_SIZE ((1 << 27) - 200)
#define RAZ_SPECIFIC(A, N)
#define UPDATE_SPECIFICS(A)
#define PREUPDATE_SPECIFICS(A)
#elif defined(RV64)
#define instruction_native_t instruction_rv64_t
#define dynarec_native_t dynarec_rv64_t
#define ADDITIONNAL_DEFINITION() \
int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst);
#define ADDITIONNAL_DEFINITION() \
int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst); \
int sewNeedsTransform(dynarec_rv64_t* dyn, int ninst);
#define OTHER_CACHE() \
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=2;
#define OTHER_CACHE() \
if (fpuCacheNeedsTransform(dyn, ninst)) ret |= 2; \
if (sewNeedsTransform(dyn, ninst)) ret |= 4;
#include "rv64/rv64_printer.h"
#include "rv64/dynarec_rv64_private.h"
#include "rv64/dynarec_rv64_functions.h"
// Limit here is unconditionnal jump, that is signed 21bits
#define MAXBLOCK_SIZE ((1<<20)-200)
#define RAZ_SPECIFIC(A, N)
#define UPDATE_SPECIFICS(A)
#define PREUPDATE_SPECIFICS(A) updateNativeFlags(A)
#else
#error Unsupported platform
#endif
+184 -1
View File
@@ -1,6 +1,189 @@
#ifndef __DYNAREC_HELPER__H_
#define __DYNAREC_HELPER__H_
/* Box64 Strong Memory Model Emulation
*
* Definition of a SEQ:
* A SEQ is a sequence of opcodes that writes to guest memory, terminated by JMP, RET, CALL, etc.
*
* Memory barriers are added in the following cases to emulate the strong memory model:
* 1. End of a SEQ:
* - Scalar operations (a1)
* - SIMD operations (a2)
* 2. Start of a SEQ:
* - Scalar operations (b1)
* - SIMD operations (b2)
* 3. Right before the last guest memory store in a SEQ:
* - Scalar operations (c1)
* - SIMD operations (c2)
* 4. After every third guest memory store in a SEQ (d)
*
* STRONGMEM levels (coarse-grained):
* 1: Includes a1, b1, c1
* 2: Includes LEVEL1, plus a2, b2, c2
* 3: Includes LEVEL2, plus d
*
* WEAKBARRIER levels (fine-grained):
* 1: Use dmb.ishld and dmb.ishst over dmb.ish for more performance
* 2. All 1. Plus disabled the last write barriers (c1, c2)
*/
#define STRONGMEM_SIMD_WRITE 2 // The level of SIMD memory writes will be tracked
#define STRONGMEM_LAST_WRITE 1 // The level of a barrier before the last guest memory store will be put
#define STRONGMEM_SEQ_WRITE 3 // The level of a barrier at every third memory store will be put
#if STEP == 1
#define SMWRITE() \
do { \
/* Mark that current sequence writes to guest memory. */ \
/* This will be used in SMEND for last_write. */ \
dyn->smwrite = 1; \
/* Mark that current opcode writes to guest memory. */ \
dyn->insts[ninst].will_write = 1; \
} while (0)
#define SMWRITELOCK(lock) \
do { \
dyn->insts[ninst].lock = lock; \
SMWRITE(); \
} while (0)
#define SMWRITE2() \
do { \
if (box64_dynarec_strongmem >= STRONGMEM_SIMD_WRITE) { \
dyn->smwrite = 1; \
dyn->insts[ninst].will_write = 2; \
} \
} while (0)
#define SMREAD()
#define SMREADLOCK(lock)
#define WILLWRITE()
#define WILLWRITELOCK(lock)
#define SMSTART() \
do { \
/* Clear current state at the start of a potential SEQ. */ \
dyn->smwrite = 0; \
} while (0)
#define SMEND() \
do { \
/* If there is any guest memory write, which is a SEQ, then compute the last_write. */ \
if (dyn->smwrite && (box64_dynarec_strongmem >= STRONGMEM_LAST_WRITE)) { \
int i = ninst; \
while (i >= 0 && !dyn->insts[i].will_write) \
--i; \
if (i >= 0) { dyn->insts[i].last_write = 1; } \
} \
dyn->smwrite = 0; \
} while (0)
#define SMDMB()
#else
// An opcode writes guest memory, this need to be put after the STORE instruction manually.
#define SMWRITE() \
do { \
/* Put a barrier at every third memory write. */ \
if (box64_dynarec_strongmem >= STRONGMEM_SEQ_WRITE) { \
if (++dyn->smwrite >= 3 /* Every third memory write */) { \
DMB_ISH(); \
dyn->smwrite = 1; \
} \
} else { \
/* Mark that current sequence writes to guest memory. */ \
dyn->smwrite = 1; \
} \
} while (0)
// Similar to SMWRITE, but checks lock.
#define SMWRITELOCK(lock) \
do { \
if (lock) { \
DMB_ISH(); \
} else { \
SMWRITE(); \
} \
} while (0)
// Similar to SMWRITE, but for SIMD instructions.
#define SMWRITE2() \
do { \
if (box64_dynarec_strongmem >= STRONGMEM_SIMD_WRITE) \
SMWRITE(); \
} while (0)
// An opcode reads guest memory, this need to be put before the LOAD instruction manually.
#define SMREAD()
// Similar to SMREAD, but checks lock.
#define SMREADLOCK(lock) \
do { \
if (lock) { \
DMB_ISH(); \
} else { \
SMREAD(); \
} \
} while (0)
// An opcode will write memory, this will be put before the STORE instruction automatically.
#define WILLWRITE() \
do { \
if (box64_dynarec_strongmem >= dyn->insts[ninst].will_write && dyn->smwrite == 0) { \
/* Will write but never written, this is the start of a SEQ, put a barrier. */ \
if (box64_dynarec_weakbarrier) \
DMB_ISHLD(); \
else \
DMB_ISH(); \
} else if (box64_dynarec_strongmem >= STRONGMEM_LAST_WRITE && box64_dynarec_weakbarrier != 2 \
&& dyn->insts[ninst].last_write) { \
/* Last write, put a barrier */ \
if (box64_dynarec_weakbarrier) \
DMB_ISHST(); \
else \
DMB_ISH(); \
} \
} while (0)
// Similar to WILLWRITE, but checks lock.
#define WILLWRITELOCK(lock) \
do { \
if (lock) { \
DMB_ISH(); \
} else { \
WILLWRITE(); \
} \
} while (0)
// Used to clear the state at the start of a SEQ
#define SMSTART() \
do { \
dyn->smwrite = 0; \
} while (0)
// Will be put at the end of the SEQ
#define SMEND() \
do { \
if (box64_dynarec_strongmem) { \
/* It's a SEQ, put a barrier here. */ \
if (dyn->smwrite) { \
/* Check if the next instruction has a end loop mark */ \
if (box64_dynarec_weakbarrier) \
DMB_ISHST(); \
else \
DMB_ISH(); \
} \
} \
dyn->smwrite = 0; \
} while (0)
// The barrier.
#define SMDMB() DMB_ISH()
#endif
#ifdef ARM64
#include "arm64/dynarec_arm64_helper.h"
#elif defined(LA64)
@@ -11,4 +194,4 @@
#error Unsupported architecture
#endif
#endif //__DYNAREC_HELPER__H_
#endif //__DYNAREC_HELPER__H_
+142 -15
View File
@@ -101,6 +101,11 @@ void add_jump(dynarec_native_t *dyn, int ninst) {
dyn->jmps[dyn->jmp_sz++] = ninst;
}
int get_first_jump(dynarec_native_t *dyn, int next) {
if(next<0 || next>dyn->size)
return -2;
return get_first_jump_addr(dyn, dyn->insts[next].x64.addr);
}
int get_first_jump_addr(dynarec_native_t *dyn, uintptr_t next) {
for(int i=0; i<dyn->jmp_sz; ++i)
if(dyn->insts[dyn->jmps[i]].x64.jmp == next)
return dyn->jmps[i];
@@ -116,6 +121,8 @@ int is_nops(dynarec_native_t *dyn, uintptr_t addr, int n)
return is_nops(dyn, addr+1, n-1);
if(n>1 && PK(0)==0x66) // if opcode start with 0x66, and there is more after, than is *can* be a NOP
return is_nops(dyn, addr+1, n-1);
if(n>1 && PK(0)==0xF3 && PK(1)==0x90)
return is_nops(dyn, addr+2, n-2);
if(n>2 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x00)
return is_nops(dyn, addr+3, n-3);
if(n>2 && PK(0)==0x8d && PK(1)==0x76 && PK(2)==0x00) // lea esi, [esi]
@@ -224,6 +231,14 @@ int next_instruction(dynarec_native_t *dyn, uintptr_t addr)
case 0xBE:
case 0xBF:
return 5;
case 0xF3:
nextop = PK(1);
switch(nextop) {
case 0x90:
return 2;
default: break;
}
break;
case 0xFF:
nextop = PK(1);
switch((nextop>>3)&7) {
@@ -357,7 +372,7 @@ static void fillPredecessors(dynarec_native_t* dyn)
}
}
// updateNeed goes backward, from last instruction to top
// updateNeed for the current block. recursive function that goes backward
static int updateNeed(dynarec_native_t* dyn, int ninst, uint8_t need) {
while (ninst>=0) {
// need pending but instruction is only a subset: remove pend and use an X_ALL instead
@@ -400,6 +415,87 @@ static int updateNeed(dynarec_native_t* dyn, int ninst, uint8_t need) {
return ninst;
}
static void updateYmm0s(dynarec_native_t* dyn, int ninst, int max_ninst_reached) {
int can_incr = ninst == max_ninst_reached; // Are we the top-level call?
int ok = 1;
while ((can_incr || ok) && ninst<dyn->size) {
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "update ninst=%d (%d): can_incr=%d\n", ninst, max_ninst_reached, can_incr);
uint16_t new_purge_ymm, new_ymm0_in, new_ymm0_out;
if (dyn->insts[ninst].pred_sz && dyn->insts[ninst].x64.alive) {
// The union of the empty set is empty (0), the intersection is the universe (-1)
// The first instruction is the entry point, which has a virtual pred with ymm0_out = 0
// Similarly, float barriers reset ymm0s
uint16_t ymm0_union = 0;
uint16_t ymm0_inter = (ninst && !(dyn->insts[ninst].x64.barrier & BARRIER_FLOAT)) ? ((uint16_t)-1) : (uint16_t)0;
for (int i = 0; i < dyn->insts[ninst].pred_sz; ++i) {
int pred = dyn->insts[ninst].pred[i];
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "\twith pred[%d] = %d", i, pred);
if (pred >= max_ninst_reached) {
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, " (skipped)\n");
continue;
}
int pred_out = dyn->insts[pred].x64.has_callret ? 0 : dyn->insts[pred].ymm0_out;
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, " ~> %04X\n", pred_out);
ymm0_union |= pred_out;
ymm0_inter &= pred_out;
}
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "\t=> %04X,%04X\n", ymm0_union, ymm0_inter);
// Notice the default values yield something coherent here (if all pred are after ninst)
new_purge_ymm = ymm0_union & ~ymm0_inter;
new_ymm0_in = ymm0_inter;
new_ymm0_out = (ymm0_inter | dyn->insts[ninst].ymm0_add) & ~dyn->insts[ninst].ymm0_sub;
if ((dyn->insts[ninst].purge_ymm != new_purge_ymm) || (dyn->insts[ninst].ymm0_in != new_ymm0_in) || (dyn->insts[ninst].ymm0_out != new_ymm0_out)) {
// Need to update self and next(s)
dyn->insts[ninst].purge_ymm = new_purge_ymm;
dyn->insts[ninst].ymm0_in = new_ymm0_in;
dyn->insts[ninst].ymm0_out = new_ymm0_out;
if (can_incr) {
// We always have ninst == max_ninst_reached when can_incr == 1
++max_ninst_reached;
} else {
// We need to stop here if the opcode has no "real" next or if we reached the ninst of the toplevel
ok = (max_ninst_reached - 1 != ninst) && dyn->insts[ninst].x64.has_next && !dyn->insts[ninst].x64.has_callret;
}
int jmp = (dyn->insts[ninst].x64.jmp)?dyn->insts[ninst].x64.jmp_insts:-1;
if((jmp!=-1) && (jmp < max_ninst_reached)) {
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "\t! jump to %d\n", jmp);
// The jump goes before the last instruction reached, update the destination
// If this is the top level call, this means the jump goes backward (jmp != ninst)
// Otherwise, since we don't update all instructions, we may miss the update (don't use jmp < ninst)
updateYmm0s(dyn, jmp, max_ninst_reached);
}
} else {
if (can_incr) {
// We always have ninst == max_ninst_reached when can_incr == 1
++max_ninst_reached;
// Also update jumps to before (they are skipped otherwise)
int jmp = (dyn->insts[ninst].x64.jmp)?dyn->insts[ninst].x64.jmp_insts:-1;
if((jmp!=-1) && (jmp < max_ninst_reached)) {
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "\t! jump to %d\n", jmp);
updateYmm0s(dyn, jmp, max_ninst_reached);
}
} else {
// We didn't update anything, we can leave
ok = 0;
}
}
} else if (can_incr) {
// We always have ninst == max_ninst_reached when can_incr == 1
++max_ninst_reached;
} else {
// We didn't update anything, we can leave
ok = 0;
}
++ninst;
}
}
void* current_helper = NULL;
static int static_jmps[MAX_INSTS+2];
static uintptr_t static_next[MAX_INSTS+2];
@@ -428,7 +524,7 @@ uintptr_t native_pass1(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
uintptr_t native_pass2(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits);
uintptr_t native_pass3(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits);
void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr, int is32bits) {
block->isize = 0;
block->done = 0;
size_t sz = 4*sizeof(void*);
@@ -443,6 +539,7 @@ void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
block->actual_block = actual_p;
block->block = p;
block->jmpnext = p;
block->is32bits = is32bits;
*(dynablock_t**)actual_p = block;
*(void**)(p+2*sizeof(void*)) = native_epilog;
CreateJmpNext(block->jmpnext, p+2*sizeof(void*));
@@ -467,7 +564,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
*/
if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end) {
dynarec_log(LOG_INFO, "Create empty block in no-dynarec zone\n");
return CreateEmptyBlock(block, addr);
return CreateEmptyBlock(block, addr, is32bits);
}
if(current_helper) {
dynarec_log(LOG_DEBUG, "Canceling dynarec FillBlock at %p as another one is going on\n", (void*)addr);
@@ -500,7 +597,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
if(!helper.size) {
dynarec_log(LOG_INFO, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
CancelBlock64(0);
return CreateEmptyBlock(block, addr);
return CreateEmptyBlock(block, addr, is32bits);
}
if(!isprotectedDB(addr, 1)) {
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
@@ -553,22 +650,27 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
k=i2;
}*/
if(k!=-1) {
if(k!=-1 && !helper.insts[i].barrier_maybe)
if(!helper.insts[i].barrier_maybe)
helper.insts[k].x64.barrier |= BARRIER_FULL;
// special case, loop on itself with some nop in between
if(k<i && !helper.insts[i].x64.has_next && is_nops(&helper, helper.insts[k].x64.addr, helper.insts[i].x64.addr-helper.insts[k].x64.addr)) {
helper.always_test = 1;
k = -1;
}
helper.insts[i].x64.jmp_insts = k;
}
}
}
// no need for next and jmps anymore
// no need for next anymore
helper.next_sz = helper.next_cap = 0;
helper.next = NULL;
helper.jmp_sz = helper.jmp_cap = 0;
helper.jmps = NULL;
// fill predecessors with the jump address
int alloc_size = sizePredecessors(&helper);
helper.predecessor = (int*)alloca(alloc_size*sizeof(int));
fillPredecessors(&helper);
PREUPDATE_SPECIFICS(&helper);
int pos = helper.size;
while (pos>=0)
pos = updateNeed(&helper, pos, 0);
@@ -576,10 +678,27 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
for(int i=1; i<helper.size-1; ++i)
if(!helper.insts[i].pred_sz) {
int ii = i;
while(ii<helper.size && !helper.insts[ii].pred_sz)
fpu_reset_ninst(&helper, ii++);
while(ii<helper.size && !helper.insts[ii].pred_sz) {
fpu_reset_ninst(&helper, ii);
helper.insts[ii].ymm0_in = helper.insts[ii].ymm0_sub = helper.insts[ii].ymm0_add = helper.insts[ii].ymm0_out = helper.insts[ii].purge_ymm = 0;
RAZ_SPECIFIC(&helper, ii);
++ii;
}
i = ii;
}
// remove trailling dead code
while(helper.size && !helper.insts[helper.size-1].x64.alive) {
helper.isize-=helper.insts[helper.size-1].x64.size;
--helper.size;
}
if(!helper.size) {
// NULL block after removing dead code, how is that possible?
dynarec_log(LOG_INFO, "Warning, null-sized dynarec block after trimming dead code (%p)\n", (void*)addr);
CancelBlock64(0);
return CreateEmptyBlock(block, addr, is32bits);
}
updateYmm0s(&helper, 0, 0);
UPDATE_SPECIFICS(&helper);
// pass 1, float optimizations, first pass for flags
@@ -632,15 +751,19 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
int oldtable64size = helper.table64size;
size_t oldnativesize = helper.native_size;
size_t oldinstsize = helper.insts_size;
int oldsize= helper.size;
helper.native_size = 0;
helper.table64size = 0; // reset table64 (but not the cap)
helper.insts_size = 0; // reset
native_pass3(&helper, addr, alternate, is32bits);
if(helper.abort) {
if(box64_dynarec_dump || box64_dynarec_log)dynarec_log(LOG_NONE, "Abort dynablock on pass1\n");
if(box64_dynarec_dump || box64_dynarec_log)dynarec_log(LOG_NONE, "Abort dynablock on pass3\n");
CancelBlock64(0);
return NULL;
}
// no need for jmps anymore
helper.jmp_sz = helper.jmp_cap = 0;
helper.jmps = NULL;
// keep size of instructions for signal handling
block->instsize = instsize;
helper.table64 = NULL;
@@ -652,6 +775,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
block->jmpnext = next+sizeof(void*);
block->always_test = helper.always_test;
block->dirty = block->always_test;
block->is32bits = is32bits;
*(dynablock_t**)next = block;
*(void**)(next+3*sizeof(void*)) = native_next;
CreateJmpNext(block->jmpnext, next+3*sizeof(void*));
@@ -661,20 +785,23 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
// Check if something changed, to abort if it is
if((block->hash != hash)) {
if((helper.abort || (block->hash != hash))) {
dynarec_log(LOG_DEBUG, "Warning, a block changed while being processed hash(%p:%ld)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash);
CancelBlock64(0);
return NULL;
}
if((oldnativesize!=helper.native_size) || (oldtable64size<helper.table64size)) {
printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%zu) & pass3 (%zu)!\n", sz, helper.native_size+helper.table64size*8);
printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%zu, %d) & pass3 (%zu, %d)!\n", oldnativesize+oldtable64size*8, oldsize, helper.native_size+helper.table64size*8, helper.size);
uint8_t *dump = (uint8_t*)helper.start;
printf_log(LOG_NONE, "Dump of %d x64 opcodes:\n", helper.size);
for(int i=0; i<helper.size; ++i) {
printf_log(LOG_NONE, "%p:", dump);
printf_log(LOG_NONE, "%s%p:", (helper.insts[i].size2!=helper.insts[i].size)?"=====> ":"", dump);
for(; dump<(uint8_t*)helper.insts[i+1].x64.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, "\t%d -> %d", helper.insts[i].size2, helper.insts[i].size);
if(helper.insts[i].ymm0_pass2 || helper.insts[i].ymm0_pass3)
printf_log(LOG_NONE, "\t %04x -> %04x", helper.insts[i].ymm0_pass2, helper.insts[i].ymm0_pass3);
printf_log(LOG_NONE, "\n");
}
printf_log(LOG_NONE, "Table64 \t%d -> %d\n", oldtable64size*8, helper.table64size*8);
printf_log(LOG_NONE, " ------------\n");
+207 -47
View File
@@ -59,10 +59,20 @@ void native_fpatan(x64emu_t* emu)
}
void native_fxtract(x64emu_t* emu)
{
int32_t tmp32s = (ST1.q&0x7ff0000000000000LL)>>52;
tmp32s -= 1023;
ST1.d /= exp2(tmp32s);
ST0.d = tmp32s;
int tmp32s;
if(isnan(ST1.d)) {
ST0.d = ST1.d;
} else if(isinf(ST1.d)) {
ST0.d = ST1.d;
ST1.d = INFINITY;
} else if(ST1.d==0.0) {
ST0.d = ST1.d;
ST1.d = -INFINITY;
} else {
// LD80bits doesn't have implicit "1" bit, so need to adjust for that
ST0.d = frexp(ST1.d, &tmp32s)*2;
ST1.d = tmp32s-1;
}
}
void native_fprem(x64emu_t* emu)
{
@@ -172,7 +182,7 @@ void native_ud(x64emu_t* emu)
void native_priv(x64emu_t* emu)
{
emu->test.test = 0;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0xbad0);
}
void native_int(x64emu_t* emu, int num)
@@ -188,13 +198,13 @@ void native_singlestep(x64emu_t* emu)
void native_int3(x64emu_t* emu)
{
emit_signal(emu, SIGTRAP, (void*)R_RIP, 128);
emit_signal(emu, SIGTRAP, NULL, 3);
}
void native_div0(x64emu_t* emu)
{
emu->test.test = 0;
emit_div0(emu, (void*)R_RIP, 0);
emit_div0(emu, (void*)R_RIP, 1);
}
void native_fsave(x64emu_t* emu, uint8_t* ed)
@@ -204,7 +214,18 @@ void native_fsave(x64emu_t* emu, uint8_t* ed)
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
LD2D(p, &ST(i).d);
LD2D(p, &emu->x87[7-i].d);
p+=10;
}
}
void native_fsave16(x64emu_t* emu, uint8_t* ed)
{
fpu_savenv(emu, (char*)ed, 1);
uint8_t* p = ed;
p += 14;
for (int i=0; i<8; ++i) {
LD2D(p, &emu->x87[7-i].d);
p+=10;
}
}
@@ -215,7 +236,19 @@ void native_frstor(x64emu_t* emu, uint8_t* ed)
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
D2LD(&ST(i).d, p);
D2LD(&emu->x87[7-i].d, p);
p+=10;
}
}
void native_frstor16(x64emu_t* emu, uint8_t* ed)
{
fpu_loadenv(emu, (char*)ed, 1);
uint8_t* p = ed;
p += 14;
for (int i=0; i<8; ++i) {
D2LD(&emu->x87[7-i].d, p);
p+=10;
}
@@ -245,23 +278,23 @@ void native_fprem1(x64emu_t* emu)
static uint8_t ff_mult(uint8_t a, uint8_t b)
{
int retval = 0;
int retval = 0;
for(int i = 0; i < 8; i++) {
if((b & 1) == 1)
retval ^= a;
for(int i = 0; i < 8; i++) {
if((b & 1) == 1)
retval ^= a;
if((a & 0x80)) {
a <<= 1;
a ^= 0x1b;
} else {
a <<= 1;
}
if((a & 0x80)) {
a <<= 1;
a ^= 0x1b;
} else {
a <<= 1;
}
b >>= 1;
}
b >>= 1;
}
return retval;
return retval;
}
void native_aesimc(x64emu_t* emu, int xmm)
@@ -275,6 +308,17 @@ void native_aesimc(x64emu_t* emu, int xmm)
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
}
void native_aesimc_y(x64emu_t* emu, int ymm)
{
sse_regs_t eay1 = emu->ymm[ymm];
for(int j=0; j<4; ++j) {
emu->ymm[ymm].ub[0+j*4] = ff_mult(0x0E, eay1.ub[0+j*4]) ^ ff_mult(0x0B, eay1.ub[1+j*4]) ^ ff_mult(0x0D, eay1.ub[2+j*4]) ^ ff_mult(0x09, eay1.ub[3+j*4]);
emu->ymm[ymm].ub[1+j*4] = ff_mult(0x09, eay1.ub[0+j*4]) ^ ff_mult(0x0E, eay1.ub[1+j*4]) ^ ff_mult(0x0B, eay1.ub[2+j*4]) ^ ff_mult(0x0D, eay1.ub[3+j*4]);
emu->ymm[ymm].ub[2+j*4] = ff_mult(0x0D, eay1.ub[0+j*4]) ^ ff_mult(0x09, eay1.ub[1+j*4]) ^ ff_mult(0x0E, eay1.ub[2+j*4]) ^ ff_mult(0x0B, eay1.ub[3+j*4]);
emu->ymm[ymm].ub[3+j*4] = ff_mult(0x0B, eay1.ub[0+j*4]) ^ ff_mult(0x0D, eay1.ub[1+j*4]) ^ ff_mult(0x09, eay1.ub[2+j*4]) ^ ff_mult(0x0E, eay1.ub[3+j*4]);
}
}
void native_aesmc(x64emu_t* emu, int xmm)
{
sse_regs_t eax1 = emu->xmm[xmm];
@@ -286,29 +330,40 @@ void native_aesmc(x64emu_t* emu, int xmm)
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
}
}
void native_aesmc_y(x64emu_t* emu, int ymm)
{
sse_regs_t eay1 = emu->ymm[ymm];
for(int j=0; j<4; ++j) {
emu->ymm[ymm].ub[0+j*4] = ff_mult(0x02, eay1.ub[0+j*4]) ^ ff_mult(0x03, eay1.ub[1+j*4]) ^ eay1.ub[2+j*4] ^ eay1.ub[3+j*4] ;
emu->ymm[ymm].ub[1+j*4] = eay1.ub[0+j*4] ^ ff_mult(0x02, eay1.ub[1+j*4]) ^ ff_mult(0x03, eay1.ub[2+j*4]) ^ eay1.ub[3+j*4] ;
emu->ymm[ymm].ub[2+j*4] = eay1.ub[0+j*4] ^ eay1.ub[1+j*4] ^ ff_mult(0x02, eay1.ub[2+j*4]) ^ ff_mult(0x03, eay1.ub[3+j*4]);
emu->ymm[ymm].ub[3+j*4] = ff_mult(0x03, eay1.ub[0+j*4]) ^ eay1.ub[1+j*4] ^ eay1.ub[2+j*4] ^ ff_mult(0x02, eay1.ub[3+j*4]);
}
}
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A N K H E B O L I F C P M J G D
static const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
static const uint8_t invsubbytes[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
void native_aesdlast(x64emu_t* emu, int xmm)
{
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A N K H E B O L I F C P M J G D
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
const uint8_t invsubbytes[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
sse_regs_t eax1;
for(int i=0; i<16; ++i)
@@ -317,6 +372,17 @@ void native_aesdlast(x64emu_t* emu, int xmm)
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = invsubbytes[eax1.ub[i]];
}
void native_aesdlast_y(x64emu_t* emu, int ymm)
{
sse_regs_t eay1;
for(int i=0; i<16; ++i)
eay1.ub[i] = emu->ymm[ymm].ub[invshiftrows[i]];
//STATE ← InvSubBytes( STATE );
for(int i=0; i<16; ++i)
emu->ymm[ymm].ub[i] = invsubbytes[eay1.ub[i]];
}
static const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
static const uint8_t subbytes[256] = {
@@ -348,16 +414,34 @@ void native_aeselast(x64emu_t* emu, int xmm)
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = subbytes[eax1.ub[i]];
}
void native_aeselast_y(x64emu_t* emu, int ymm)
{
sse_regs_t eay1;
for(int i=0; i<16; ++i)
eay1.ub[i] = emu->ymm[ymm].ub[shiftrows[i]];
for(int i=0; i<16; ++i)
emu->ymm[ymm].ub[i] = subbytes[eay1.ub[i]];
}
void native_aesd(x64emu_t* emu, int xmm)
{
native_aesdlast(emu, xmm);
native_aesimc(emu, xmm);
}
void native_aesd_y(x64emu_t* emu, int ymm)
{
native_aesdlast_y(emu, ymm);
native_aesimc_y(emu, ymm);
}
void native_aese(x64emu_t* emu, int xmm)
{
native_aeselast(emu, xmm);
native_aesmc(emu, xmm);
}
void native_aese_y(x64emu_t* emu, int ymm)
{
native_aeselast_y(emu, ymm);
native_aesmc_y(emu, ymm);
}
void native_aeskeygenassist(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8)
{
sse_regs_t *EX = p?((sse_regs_t*)p):&emu->xmm[ex];
@@ -393,6 +477,40 @@ void native_pclmul(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8)
GX->q[0] = result&0xffffffffffffffffLL;
GX->q[1] = (result>>64)&0xffffffffffffffffLL;
}
void native_pclmul_x(x64emu_t* emu, int gx, int vx, void* p, uint32_t u8)
{
sse_regs_t *EX = ((uintptr_t)p<16)?((sse_regs_t*)p):&emu->xmm[(uintptr_t)p];
sse_regs_t *GX = &emu->xmm[gx];
sse_regs_t *VX = &emu->xmm[vx];
int g = (u8&1)?1:0;
int e = (u8&0b10000)?1:0;
__int128 result = 0;
__int128 op2 = EX->q[e];
for (int i=0; i<64; ++i)
if(VX->q[g]&(1LL<<i))
result ^= (op2<<i);
GX->q[0] = result&0xffffffffffffffffLL;
GX->q[1] = (result>>64)&0xffffffffffffffffLL;
}
void native_pclmul_y(x64emu_t* emu, int gy, int vy, void* p, uint32_t u8)
{
sse_regs_t *EY = ((uintptr_t)p<16)?((sse_regs_t*)p):&emu->ymm[(uintptr_t)p];
sse_regs_t *GY = &emu->ymm[gy];
sse_regs_t *VY = &emu->ymm[vy];
int g = (u8&1)?1:0;
int e = (u8&0b10000)?1:0;
__int128 result = 0;
__int128 op2 = EY->q[e];
for (int i=0; i<64; ++i)
if(VY->q[g]&(1LL<<i))
result ^= (op2<<i);
GY->q[0] = result&0xffffffffffffffffLL;
GY->q[1] = (result>>64)&0xffffffffffffffffLL;
}
void native_clflush(x64emu_t* emu, void* p)
{
@@ -405,7 +523,7 @@ static int flagsCacheNeedsTransform(dynarec_native_t* dyn, int ninst) {
return 0;
if(dyn->insts[ninst].f_exit.dfnone) // flags are fully known, nothing we can do more
return 0;
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone)
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone && !dyn->insts[jmp].df_notneeded)
return 1;
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: return 0;
@@ -476,7 +594,7 @@ uintptr_t fakeed(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nexto
}
return addr;
}
// return Ib on a mod/rm opcode without emiting anything
// return Ib on a mod/rm opcode without emitting anything
uint8_t geted_ib(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
{
addr = fakeed(dyn, addr, ninst, nextop);
@@ -484,9 +602,11 @@ uint8_t geted_ib(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nexto
}
#undef F8
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn)
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, int is32bits, uintptr_t* calladdress, uint16_t* retn)
{
(void)dyn;
if(is32bits)
addr &= 0xFFFFFFFFLL;
#define PK(a) *(uint8_t*)(addr+a)
#define PK32(a) *(int32_t*)(addr+a)
@@ -500,7 +620,7 @@ int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress,
if(!addr || !getProtection(addr))
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) {
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver64) {
// found !
if(retn) *retn = (b->C3==0xC2)?b->N:0;
if(calladdress) *calladdress = addr+1;
@@ -510,3 +630,43 @@ int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress,
#undef PK32
#undef PK
}
// AVX
void avx_mark_zero(dynarec_native_t* dyn, int ninst, int reg)
{
dyn->ymm_zero |= (1<<reg);
}
int is_avx_zero(dynarec_native_t* dyn, int ninst, int reg)
{
return (dyn->ymm_zero>>reg)&1;
}
int is_avx_zero_unset(dynarec_native_t* dyn, int ninst, int reg)
{
if((dyn->ymm_zero>>reg)&1) {
dyn->ymm_zero &= ~(1<<reg);
return 1;
}
return 0;
}
void avx_mark_zero_reset(dynarec_native_t* dyn, int ninst)
{
dyn->ymm_zero = 0;
}
void avx_unmark_zero(dynarec_native_t* dyn, int ninst, int reg)
{
dyn->ymm_zero &= ~(1<<reg);
}
void propagate_nodf(dynarec_native_t* dyn, int ninst)
{
while(ninst>=0) {
if(dyn->insts[ninst].df_notneeded)
return; // already flagged
if(dyn->insts[ninst].x64.gen_flags || dyn->insts[ninst].x64.use_flags)
return; // flags are use, so maybe it's needed
dyn->insts[ninst].df_notneeded = 1;
--ninst;
}
}
+20 -2
View File
@@ -30,16 +30,25 @@ void native_fistp64(x64emu_t* emu, int64_t* ed);
void native_fistt64(x64emu_t* emu, int64_t* ed);
void native_fld(x64emu_t* emu, uint8_t* ed);
void native_fsave(x64emu_t* emu, uint8_t* ed);
void native_fsave16(x64emu_t* emu, uint8_t* ed);
void native_frstor(x64emu_t* emu, uint8_t* ed);
void native_frstor16(x64emu_t* emu, uint8_t* ed);
void native_fprem1(x64emu_t* emu);
void native_aesd(x64emu_t* emu, int xmm);
void native_aesd_y(x64emu_t* emu, int ymm);
void native_aese(x64emu_t* emu, int xmm);
void native_aese_y(x64emu_t* emu, int ymm);
void native_aesdlast(x64emu_t* emu, int xmm);
void native_aesdlast_y(x64emu_t* emu, int ymm);
void native_aeselast(x64emu_t* emu, int xmm);
void native_aeselast_y(x64emu_t* emu, int ymm);
void native_aesimc(x64emu_t* emu, int xmm);
void native_aesimc_y(x64emu_t* emu, int ymm);
void native_aeskeygenassist(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8);
void native_pclmul(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8);
void native_pclmul_x(x64emu_t* emu, int gx, int vx, void* p, uint32_t u8);
void native_pclmul_y(x64emu_t* emu, int gy, int vy, void* p, uint32_t u8);
void native_clflush(x64emu_t* emu, void* p);
@@ -52,6 +61,8 @@ void native_div0(x64emu_t* emu);
// Caches transformation (for loops) // Specific, need to be written par backend
int CacheNeedsTransform(dynarec_native_t* dyn, int i1);
// propagete defererd to unknow, as state is not needed
void propagate_nodf(dynarec_native_t* dyn, int ninst);
// predecessor access
int isPred(dynarec_native_t* dyn, int ninst, int pred);
@@ -59,11 +70,18 @@ int getNominalPred(dynarec_native_t* dyn, int ninst);
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
// return Ib on a mod/rm opcode without emiting anything
// return Ib on a mod/rm opcode without emitting anything
uint8_t geted_ib(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
// Is what pointed at addr a native call? And if yes, to what function?
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, int is32bits, uintptr_t* calladdress, uint16_t* retn);
// AVX utilities
void avx_mark_zero(dynarec_native_t* dyn, int ninst, int reg);
int is_avx_zero(dynarec_native_t* dyn, int ninst, int reg);
int is_avx_zero_unset(dynarec_native_t* dyn, int ninst, int reg);
void avx_mark_zero_reset(dynarec_native_t* dyn, int ninst);
void avx_unmark_zero(dynarec_native_t* dyn, int ninst, int reg);
ADDITIONNAL_DEFINITION()
+40 -24
View File
@@ -49,23 +49,24 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
dyn->forward_to = 0;
dyn->forward_size = 0;
dyn->forward_ninst = 0;
dyn->ymm_zero = 0;
#if STEP == 0
memset(&dyn->insts[ninst], 0, sizeof(instruction_native_t));
#endif
fpu_reset(dyn);
ARCH_INIT();
int reset_n = -1;
int reset_n = -1; // -1 no reset; -2 reset to 0; else reset to the state of reset_n
dyn->last_ip = (alternate || (dyn->insts && dyn->insts[0].pred_sz))?0:ip; // RIP is always set at start of block unless there is a predecessor!
int stopblock = 2+(FindElfAddress(my_context, addr)?0:1); // if block is in elf_memory, it can be extended with box64_dynarec_bigblock==2, else it needs 3
// ok, go now
INIT;
#if STEP == 0
uintptr_t cur_page = (addr)&~box64_pagesize;
uintptr_t cur_page = (addr)&~(box64_pagesize-1);
#endif
while(ok) {
#if STEP == 0
if(cur_page != ((addr)&~box64_pagesize)) {
cur_page = (addr)&~box64_pagesize;
if(cur_page != ((addr)&~(box64_pagesize-1))) {
cur_page = (addr)&~(box64_pagesize-1);
if(!(getProtection(addr)&PROT_READ)) {
need_epilog = 1;
break;
@@ -88,6 +89,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
dyn->f.dfnone = 0;
dyn->f.pending = 0;
fpu_reset(dyn);
ARCH_RESET();
} else {
fpu_reset_cache(dyn, ninst, reset_n);
dyn->f = dyn->insts[reset_n].f_exit;
@@ -107,21 +109,24 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
else if(ninst && (dyn->insts[ninst].pred_sz>1 || (dyn->insts[ninst].pred_sz==1 && dyn->insts[ninst].pred[0]!=ninst-1)))
dyn->last_ip = 0; // reset IP if some jump are coming here
#endif
dyn->f.dfnone_here = 0;
NEW_INST;
#if STEP == 0
if(ninst && dyn->insts[ninst-1].x64.barrier_next) {
BARRIER(dyn->insts[ninst-1].x64.barrier_next);
}
#endif
MESSAGE(LOG_DUMP, "New Instruction %s:%p, native:%p\n", is32bits?"x86":"x64",(void*)addr, (void*)dyn->block);
if(!ninst) {
GOTEST(x1, x2);
}
if(dyn->insts[ninst].pred_sz>1) {SMSTART();}
fpu_reset_scratch(dyn);
#if STEP > 1
if (dyn->insts[ninst].lock) {
WILLWRITELOCK(dyn->insts[ninst].lock);
} else if (dyn->insts[ninst].will_write) {
WILLWRITE();
}
#endif
if((dyn->insts[ninst].x64.need_before&~X_PEND) && !dyn->insts[ninst].pred_sz) {
READFLAGS(dyn->insts[ninst].x64.need_before&~X_PEND);
}
if(box64_dynarec_test) {
if(box64_dynarec_test && (!box64_dynarec_test_end || (ip>=box64_dynarec_test_start && ip<box64_dynarec_test_end) )) {
MESSAGE(LOG_DUMP, "TEST STEP ----\n");
fpu_reflectcache(dyn, ninst, x1, x2, x3);
GO_TRACE(x64test_step, 1, x5);
@@ -166,14 +171,19 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
if(dyn->abort)
return ip;
INST_EPILOG;
fpu_reset_scratch(dyn);
int next = ninst+1;
#if STEP > 0
if(!dyn->insts[ninst].x64.has_next && dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts!=-1)
next = dyn->insts[ninst].x64.jmp_insts;
if(dyn->insts[ninst].x64.has_next && dyn->insts[next].x64.barrier) {
if(dyn->insts[next].x64.barrier&BARRIER_FLOAT) {
#ifdef RV64
uint8_t tmp1, tmp2, tmp3;
if(dyn->insts[next].nat_flags_fusion) get_free_scratch(dyn, next, &tmp1, &tmp2, &tmp3, x1, x2, x3, x4, x5);
else { tmp1=x1; tmp2=x2; tmp3=x3; }
fpu_purgecache(dyn, ninst, 0, tmp1, tmp2, tmp3);
#else
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
#endif
}
if(dyn->insts[next].x64.barrier&BARRIER_FLAGS) {
dyn->f.pending = 0;
@@ -189,26 +199,30 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
if(!ok && !need_epilog && (addr < (dyn->start+dyn->isize))) {
ok = 1;
// we use the 1st predecessor here
int ii = ninst+1;
if(ii<dyn->size && !dyn->insts[ii].x64.alive) {
while(ii<dyn->size && !dyn->insts[ii].x64.alive) {
if((ninst+1)<dyn->size && !dyn->insts[ninst+1].x64.alive) {
// reset fpu value...
dyn->f.dfnone = 0;
dyn->f.pending = 0;
fpu_reset(dyn);
while((ninst+1)<dyn->size && !dyn->insts[ninst+1].x64.alive) {
// may need to skip opcodes to advance
++ninst;
NEW_INST;
MESSAGE(LOG_DEBUG, "Skipping unused opcode\n");
INST_NAME("Skipped opcode");
addr += dyn->insts[ninst].x64.size;
INST_EPILOG;
addr += dyn->insts[ii].x64.size;
++ii;
}
}
if((dyn->insts[ii].x64.barrier&BARRIER_FULL)==BARRIER_FULL)
if((dyn->insts[ninst+1].x64.barrier&BARRIER_FULL)==BARRIER_FULL)
reset_n = -2; // hack to say Barrier!
else {
reset_n = getNominalPred(dyn, ii); // may get -1 if no predecessor are available
reset_n = getNominalPred(dyn, ninst+1); // may get -1 if no predecessor are available
if(reset_n==-1) {
reset_n = -2;
MESSAGE(LOG_DEBUG, "Warning, Reset Caches mark not found\n");
if(!dyn->insts[ninst].x64.has_callret) {
MESSAGE(LOG_DEBUG, "Warning, Reset Caches mark not found\n");
}
}
}
}
@@ -222,7 +236,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
if(dyn->forward) {
if(dyn->forward_to == addr && !need_epilog && ok>=0) {
// we made it!
reset_n = get_first_jump(dyn, addr);
reset_n = get_first_jump_addr(dyn, addr);
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block for %d bytes %s%p -> %p (ninst %d - %d)\n", dyn->forward_to-dyn->forward, dyn->insts[dyn->forward_ninst].x64.has_callret?"(opt. call) ":"", (void*)dyn->forward, (void*)dyn->forward_to, reset_n, ninst);
if(dyn->insts[dyn->forward_ninst].x64.has_callret && !dyn->insts[dyn->forward_ninst].x64.has_next)
dyn->insts[dyn->forward_ninst].x64.has_next = 1; // this block actually continue
@@ -260,7 +274,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
reset_n = get_first_jump(dyn, next);
}
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %s%p -> %p (ninst=%d, jump from %d)\n", dyn, dyn->insts[ninst].x64.has_callret?"(opt. call) ":"", (void*)addr, (void*)next, ninst+1, dyn->insts[ninst].x64.has_callret?ninst:reset_n);
} else if(next && (next-addr)<box64_dynarec_forward && (getProtection(next)&PROT_READ)/*box64_dynarec_bigblock>=stopblock*/) {
} else if(next && (int)(next-addr)<box64_dynarec_forward && (getProtection(next)&PROT_READ)/*box64_dynarec_bigblock>=stopblock*/) {
if(!((box64_dynarec_bigblock<stopblock) && !isJumpTableDefault64((void*)next))) {
if(dyn->forward) {
if(next<dyn->forward_to)
@@ -304,6 +318,8 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
}
if((ok>0) && dyn->insts[ninst].x64.has_callret)
reset_n = -2;
if((ok>0) && reset_n==-1 && dyn->insts[ninst+1].purge_ymm)
PURGE_YMM();
++ninst;
#if STEP == 0
memset(&dyn->insts[ninst], 0, sizeof(instruction_native_t));
+3 -1
View File
@@ -29,6 +29,9 @@
#define SF_NODF 16
#define SF_SET_NODF (SF_SET|SF_NODF)
#define NAT_FLAGS_FUSION 0
#define NAT_FLAGS_NOFUSION 1
typedef struct instruction_x64_s {
uintptr_t addr; //address of the instruction
int32_t size; // size of the instruction
@@ -39,7 +42,6 @@ typedef struct instruction_x64_s {
uint8_t has_callret:1; // this instruction have an optimised call setup
uint8_t alive:1; // this opcode gets executed (0 if dead code in that block)
uint8_t barrier; // next instruction is a jump point, so no optim allowed
uint8_t barrier_next; // next instruction needs a barrier
uint8_t state_flags;// One of SF_XXX state
uint8_t use_flags; // 0 or combination of X_?F
uint8_t set_flags; // 0 or combination of X_?F
File diff suppressed because it is too large. Load diff
+454 -77
View File
@@ -24,7 +24,7 @@
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_functions.h"
#include "dynarec_la64_helper.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
@@ -66,17 +66,12 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if(MODREG) {
switch(nextop) {
case 0xD0:
INST_NAME("FAKE xgetbv");
nextop = F8;
addr = fakeed(dyn, addr, ninst, nextop);
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
GETIP(ip);
STORE_XEMU_CALL();
CALL(native_ud, -1);
LOAD_XEMU_CALL();
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
*ok = 0;
INST_NAME("XGETBV");
BEQZ_MARK(xRCX);
EMIT(0); // Is there any assigned illegal instruction?
MARK;
MOV32w(xRAX, 0b111);
MOV32w(xRDX, 0);
break;
default:
DEFAULT;
@@ -98,12 +93,34 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
LOAD_XEMU_CALL();
TABLE64(x3, addr); // expected return address
BNE_MARK(xRIP, x3);
LD_W(w1, xEmu, offsetof(x64emu_t, quit));
CBZ_NEXT(w1);
LD_W(x1, xEmu, offsetof(x64emu_t, quit));
CBZ_NEXT(x1);
MARK;
LOAD_XEMU_REM();
jump_to_epilog(dyn, 0, xRIP, ninst);
break;
case 0x0B:
INST_NAME("UD2");
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
GETIP(ip);
STORE_XEMU_CALL();
CALL(native_ud, -1);
LOAD_XEMU_CALL();
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
*ok = 0;
break;
case 0x0D:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 1:
INST_NAME("PREFETCHW");
FAKEED;
break;
default: //???
DEFAULT;
}
break;
case 0x10:
INST_NAME("MOVUPS Gx,Ex");
nextop = F8;
@@ -264,6 +281,20 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SMWRITE2();
}
break;
case 0x2B:
INST_NAME("MOVNTPS Ex,Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if (MODREG) {
ed = (nextop & 7) + (rex.b << 3);
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VOR_V(v1, v0, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0);
VST(v0, ed, fixedaddress);
}
break;
case 0x2E:
// no special check...
case 0x2F:
@@ -305,36 +336,125 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SPILL_EFLAGS();
}
break;
#define GO(GETFLAGS, NO, YES, F, I) \
READFLAGS(F); \
if (la64_lbt) { \
X64_SETJ(x1, I); \
} else { \
GETFLAGS; \
} \
nextop = F8; \
GETGD; \
if (MODREG) { \
ed = TO_LA64((nextop & 7) + (rex.b << 3)); \
if (la64_lbt) \
BEQZ(x1, 8); \
else \
B##NO(x1, 8); \
MV(gd, ed); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x4, &fixedaddress, rex, NULL, 1, 0); \
if (la64_lbt) \
BEQZ(x1, 8); \
else \
B##NO(x1, 8); \
LDxw(gd, ed, fixedaddress); \
} \
if (!rex.w) ZEROUP(gd);
case 0x31:
INST_NAME("RDTSC");
NOTEST(x1);
// TODO: how to read the wall-clock real time on LoongArch?
CALL(ReadTSC, x3); // will return the u64 in x3
if (box64_rdtsc_shift) {
SRLI_D(x3, x3, box64_rdtsc_shift);
}
SRLI_D(xRDX, x3, 32);
ZEROUP2(xRDX, x3);
break;
case 0x38:
// SSE3
nextop = F8;
switch (nextop) {
case 0xC8 ... 0xCD:
u8 = nextop;
switch (u8) {
case 0xC8:
INST_NAME("SHA1NEXTE Gx, Ex");
break;
case 0xC9:
INST_NAME("SHA1MSG1 Gx, Ex");
break;
case 0xCA:
INST_NAME("SHA1MSG2 Gx, Ex");
break;
case 0xCB:
INST_NAME("SHA256RNDS2 Gx, Ex");
break;
case 0xCC:
INST_NAME("SHA256MSG1 Gx, Ex");
break;
case 0xCD:
INST_NAME("SHA256MSG2 Gx, Ex");
break;
}
nextop = F8;
if (MODREG) {
ed = (nextop & 7) + (rex.b << 3);
sse_reflect_reg(dyn, ninst, ed);
ADDI_D(x2, xEmu, offsetof(x64emu_t, xmm[ed]));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 0, 0);
if (ed != x2) {
MV(x2, ed);
}
}
GETG;
sse_forget_reg(dyn, ninst, gd);
ADDI_D(x1, xEmu, offsetof(x64emu_t, xmm[gd]));
sse_reflect_reg(dyn, ninst, 0);
switch (u8) {
case 0xC8:
CALL(sha1nexte, -1);
break;
case 0xC9:
CALL(sha1msg1, -1);
break;
case 0xCA:
CALL(sha1msg2, -1);
break;
case 0xCB:
CALL(sha256rnds2, -1);
break;
case 0xCC:
CALL(sha256msg1, -1);
break;
case 0xCD:
CALL(sha256msg2, -1);
break;
}
break;
default:
DEFAULT;
}
break;
#define GO(GETFLAGS, NO, YES, F, I) \
READFLAGS(F); \
if (la64_lbt) { \
X64_SETJ(x1, I); \
} else { \
GETFLAGS; \
} \
nextop = F8; \
GETGD; \
if (MODREG) { \
ed = TO_NAT((nextop & 7) + (rex.b << 3)); \
if (la64_lbt) \
BEQZ(x1, 8); \
else \
B##NO(x1, 8); \
MV(gd, ed); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x4, &fixedaddress, rex, NULL, 1, 0); \
if (la64_lbt) \
BEQZ(x1, 8); \
else \
B##NO(x1, 8); \
LDxw(gd, ed, fixedaddress); \
} \
if (!rex.w) ZEROUP(gd);
GOCOND(0x40, "CMOV", "Gd, Ed");
#undef GO
case 0x50:
INST_NAME("MOVMSPKPS Gd, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGD;
q1 = fpu_get_scratch(dyn);
VMSKLTZ_W(q1, q0);
MOVFR2GR_S(gd, q1);
BSTRPICK_D(gd, gd, 31, 0);
break;
case 0x51:
INST_NAME("SQRTPS Gx, Ex");
nextop = F8;
@@ -350,6 +470,15 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETGX_empty(q1);
VFRSQRT_S(q1, q0);
break;
case 0x53:
INST_NAME("RCPPS Gx, Ex");
nextop = F8;
SKIPTEST(x1);
GETEX(q0, 0, 0);
GETGX_empty(q1);
// TODO: use v1.1 vfrecipe when possible
VFRECIP_S(q1, q0);
break;
case 0x54:
INST_NAME("ANDPS Gx, Ex");
nextop = F8;
@@ -406,6 +535,13 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETGX(q1, 1);
VFCVTL_D_S(q1, q0);
break;
case 0x5B:
INST_NAME("CVTDQ2PS Gx, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGX_empty(q1);
VFFINT_S_W(q1, q0);
break;
case 0x5C:
INST_NAME("SUBPS Gx, Ex");
nextop = F8;
@@ -413,13 +549,53 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETGX(v0, 1);
VFSUB_S(v0, v0, q0);
break;
case 0x5D:
INST_NAME("MINPS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 0);
if (!box64_dynarec_fastnan && v0 != v1) {
q0 = fpu_get_scratch(dyn);
// always copy from v1 if any oprand is NaN
VFCMP_S(q0, v0, v1, cUN);
VANDN_V(v0, q0, v0);
VAND_V(q0, q0, v1);
VOR_V(v0, v0, q0);
}
VFMIN_S(v0, v0, v1);
break;
case 0x5E:
INST_NAME("DIVPS Gx, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGX(v0, 1);
VFDIV_S(v0, v0, q0);
break;
case 0x5F:
INST_NAME("MAXPS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 0);
if (!box64_dynarec_fastnan && v0 != v1) {
q0 = fpu_get_scratch(dyn);
// always copy from v1 if any oprand is NaN
VFCMP_S(q0, v0, v1, cUN);
VANDN_V(v0, q0, v0);
VAND_V(q0, q0, v1);
VOR_V(v0, v0, q0);
}
VFMAX_S(v0, v0, v1);
break;
#define GO(GETFLAGS, NO, YES, F, I) \
if (box64_dynarec_test == 2) { NOTEST(x1); } \
READFLAGS(F); \
i32_ = F32S; \
if(rex.is32bits) \
j64 = (uint32_t)(addr+i32_); \
else \
j64 = addr+i32_; \
BARRIER(BARRIER_MAYBE); \
JUMP(addr + i32_, 1); \
JUMP(j64, 1); \
if (la64_lbt) { \
X64_SETJ(x1, I); \
} else { \
@@ -435,7 +611,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (dyn->insts[ninst].x64.jmp_insts == -1) { \
if (!(dyn->insts[ninst].x64.barrier & BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr + i32_, 0, ninst, rex.is32bits); \
jump_to_next(dyn, j64, 0, ninst, rex.is32bits); \
} else { \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address - (dyn->native_size); \
@@ -455,30 +631,30 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
#undef GO
#define GO(GETFLAGS, NO, YES, F, I) \
READFLAGS(F); \
if (la64_lbt) { \
X64_SETJ(x3, I); \
} else { \
GETFLAGS; \
S##YES(x3, x1); \
} \
nextop = F8; \
if (MODREG) { \
if (rex.rex) { \
eb1 = TO_LA64((nextop & 7) + (rex.b << 3)); \
eb2 = 0; \
} else { \
ed = (nextop & 7); \
eb2 = (ed >> 2) * 8; \
eb1 = TO_LA64(ed & 3); \
} \
BSTRINS_D(eb1, x3, eb2 + 7, eb2); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); \
ST_B(x3, ed, fixedaddress); \
SMWRITE(); \
}
#define GO(GETFLAGS, NO, YES, F, I) \
READFLAGS(F); \
if (la64_lbt) { \
X64_SETJ(x3, I); \
} else { \
GETFLAGS; \
S##YES(x3, x1); \
} \
nextop = F8; \
if (MODREG) { \
if (rex.rex) { \
eb1 = TO_NAT((nextop & 7) + (rex.b << 3)); \
eb2 = 0; \
} else { \
ed = (nextop & 7); \
eb2 = (ed >> 2) * 8; \
eb1 = TO_NAT(ed & 3); \
} \
BSTRINS_D(eb1, x3, eb2 + 7, eb2); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); \
ST_B(x3, ed, fixedaddress); \
SMWRITE(); \
}
GOCOND(0x90, "SET", "Eb");
#undef GO
@@ -499,7 +675,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
@@ -515,6 +691,162 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
else
BSTRINS_D(xFlags, x4, F_CF, F_CF);
break;
case 0xA4:
nextop = F8;
INST_NAME("SHLD Ed, Gd, Ib");
if (geted_ib(dyn, addr, ninst, nextop)) {
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED(1);
GETGD;
u8 = F8;
emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
WBACK;
} else {
FAKEED;
F8;
}
break;
case 0xAB:
INST_NAME("BTS Ed, Gd");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE();
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
SRAI_D(x1, gd, 5 + rex.w);
ALSL_D(x3, x1, wback, 2 + rex.w);
LDxw(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
ANDI(x2, gd, rex.w ? 0x3f : 0x1f);
IFX (X_CF) {
SRL_D(x4, ed, x2);
if (la64_lbt) {
X64_SET_EFLAGS(x4, X_CF);
} else {
BSTRINS_D(xFlags, x4, F_CF, F_CF);
}
}
ADDI_D(x4, xZR, 1);
SLL_D(x4, x4, x2);
OR(ed, ed, x4);
if (wback) {
SDxw(ed, wback, fixedaddress);
SMWRITE();
} else if (!rex.w) {
ZEROUP(ed);
}
break;
case 0xAC:
nextop = F8;
INST_NAME("SHRD Ed, Gd, Ib");
if (geted_ib(dyn, addr, ninst, nextop)) {
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED(1);
GETGD;
u8 = F8;
u8 &= (rex.w ? 0x3f : 0x1f);
emit_shrd32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
WBACK;
} else {
FAKEED;
F8;
}
break;
case 0xAE:
nextop = F8;
if (MODREG)
switch (nextop) {
case 0xE8:
INST_NAME("LFENCE");
SMDMB();
break;
case 0xF0:
INST_NAME("MFENCE");
SMDMB();
break;
case 0xF8:
INST_NAME("SFENCE");
SMDMB();
break;
default:
DEFAULT;
}
else
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("FXSAVE Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SKIPTEST(x1);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
if (MODREG) {
DEFAULT;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x3, &fixedaddress, rex, NULL, 0, 0);
if (ed != x1) { MV(x1, ed); }
CALL(rex.is32bits ? ((void*)fpu_fxsave32) : ((void*)fpu_fxsave64), -1);
}
break;
case 1:
INST_NAME("FXRSTOR Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SKIPTEST(x1);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x3, &fixedaddress, rex, NULL, 0, 0);
if (ed != x1) { MV(x1, ed); }
CALL(rex.is32bits ? ((void*)fpu_fxrstor32) : ((void*)fpu_fxrstor64), -1);
break;
case 2:
INST_NAME("LDMXCSR Md");
GETED(0);
ST_W(ed, xEmu, offsetof(x64emu_t, mxcsr));
if (box64_sse_flushto0) {
// TODO
}
break;
case 3:
INST_NAME("STMXCSR Md");
addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, NULL, 0, 0);
LD_WU(x4, xEmu, offsetof(x64emu_t, mxcsr));
ST_W(x4, wback, fixedaddress);
break;
case 4:
INST_NAME("XSAVE Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, NULL, 0, 0);
if (ed != x1) { MV(x1, ed); }
MOV32w(x2, rex.w?0:1);
CALL((void*)fpu_xsave, -1);
break;
case 5:
INST_NAME("XRSTOR Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, NULL, 0, 0);
if (ed != x1) { MV(x1, ed); }
MOV32w(x2, rex.w?0:1);
CALL((void*)fpu_xrstor, -1);
break;
case 7:
INST_NAME("CLFLUSH Ed");
MESSAGE(LOG_DUMP, "Need Optimization?\n");
addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, NULL, 0, 0);
if (wback != A1) {
MV(A1, wback);
}
CALL_(native_clflush, -1, 0);
break;
default:
DEFAULT;
}
break;
case 0xAF:
INST_NAME("IMUL Gd, Ed");
SETFLAGS(X_ALL, SF_PENDING);
@@ -560,7 +892,9 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (la64_lbt) {
X64_MUL_W(gd, ed);
}
MUL_D(gd, gd, ed);
SLLI_W(gd, gd, 0);
SLLI_W(x3, ed, 0);
MUL_D(gd, gd, x3);
SRLI_D(x3, gd, 32);
SLLI_W(gd, gd, 0);
IFX (X_PEND) {
@@ -593,11 +927,11 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETGD;
if (MODREG) {
if (rex.rex) {
eb1 = TO_LA64((nextop & 7) + (rex.b << 3));
eb1 = TO_NAT((nextop & 7) + (rex.b << 3));
eb2 = 0;
} else {
ed = (nextop & 7);
eb1 = TO_LA64(ed & 3); // Ax, Cx, Dx or Bx
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = (ed & 4) >> 2; // L or H
}
BSTRPICK_D(gd, eb1, eb2 * 8 + 7, eb2 * 8);
@@ -612,7 +946,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
BSTRPICK_D(gd, ed, 15, 0);
} else {
SMREAD();
@@ -653,6 +987,8 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (wback) {
SDxw(ed, wback, fixedaddress);
SMWRITE();
} else if (!rex.w) {
ZEROUP(ed);
}
MARK;
break;
@@ -672,9 +1008,33 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (wback) {
SDxw(ed, wback, fixedaddress);
SMWRITE();
} else if (!rex.w) {
ZEROUP(ed);
}
MARK;
break;
case 7:
INST_NAME("BTC Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE();
GETED(1);
u8 = F8;
u8 &= rex.w ? 0x3f : 0x1f;
BSTRPICK_D(x3, ed, u8, u8);
BSTRINS_D(xFlags, x3, 0, 0);
if (u8 <= 10) {
XORI(ed, ed, (1LL << u8));
} else {
MOV64xw(x3, (1LL << u8));
XOR(ed, ed, x3);
}
if (wback) {
SDxw(ed, wback, fixedaddress);
SMWRITE();
} else if (!rex.w) {
ZEROUP(ed);
}
break;
default:
DEFAULT;
}
@@ -687,7 +1047,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETED(0);
GETGD;
if (!rex.w && MODREG) {
AND(x4, ed, xMASK);
ZEROUP2(x4, ed);
ed = x4;
}
BNE_MARK(ed, xZR);
@@ -719,7 +1079,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETED(0);
GETGD;
if (!rex.w && MODREG) {
AND(x4, ed, xMASK);
ZEROUP2(x4, ed);
ed = x4;
}
BNE_MARK(ed, xZR);
@@ -750,12 +1110,12 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETGD;
if (MODREG) {
if (rex.rex) {
wback = TO_LA64((nextop & 7) + (rex.b << 3));
wback = TO_NAT((nextop & 7) + (rex.b << 3));
wb2 = 0;
} else {
wback = (nextop & 7);
wb2 = (wback >> 2) * 8;
wback = TO_LA64(wback & 3);
wback = TO_NAT(wback & 3);
}
BSTRPICK_D(gd, wback, wb2 + 7, wb2);
EXT_W_B(gd, gd);
@@ -771,7 +1131,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
EXT_W_H(gd, ed);
} else {
SMREAD();
@@ -780,6 +1140,23 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
if (!rex.w) ZEROUP(gd);
break;
case 0xC2:
INST_NAME("CMPPS Gx, Ex, Ib");
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 1);
u8 = F8;
switch (u8 & 7) {
case 0: VFCMP_S(v0, v0, v1, cEQ); break; // Equal
case 1: VFCMP_S(v0, v0, v1, cLT); break; // Less than
case 2: VFCMP_S(v0, v0, v1, cLE); break; // Less or equal
case 3: VFCMP_S(v0, v0, v1, cUN); break; // NaN
case 4: VFCMP_S(v0, v0, v1, cUNE); break; // Not Equal or unordered
case 5: VFCMP_S(v0, v1, v0, cULE); break; // Greater or equal or unordered
case 6: VFCMP_S(v0, v1, v0, cULT); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
case 7: VFCMP_S(v0, v0, v1, cOR); break; // not NaN
}
break;
case 0xC6:
INST_NAME("SHUFPS Gx, Ex, Ib");
nextop = F8;
@@ -804,7 +1181,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xCE:
case 0xCF:
INST_NAME("BSWAP Reg");
gd = TO_LA64((opcode & 7) + (rex.b << 3));
gd = TO_NAT((opcode & 7) + (rex.b << 3));
REVBxw(gd, gd);
break;
default:
+353 -5
View File
@@ -8,6 +8,7 @@
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "la64_emitter.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
@@ -19,7 +20,7 @@
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog)
@@ -60,6 +61,24 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETREX();
switch (opcode) {
case 0x03:
INST_NAME("ADD Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_add32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x2B:
INST_NAME("SUB Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_sub32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x33:
INST_NAME("XOR Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -69,18 +88,347 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETEDO(x4, 0);
emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x64:
addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog);
break;
case 0x65:
addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _GS, ok, need_epilog);
break;
case 0x66:
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, seg, ok, need_epilog);
break;
case 0x80:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0: // ADD
INST_NAME("ADD Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_add8c(dyn, ninst, x1, u8, x2, x4, x5);
EBBACK();
break;
case 1: // OR
INST_NAME("OR Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_or8c(dyn, ninst, x1, u8, x2, x4, x5);
EBBACK();
break;
case 2: // ADC
INST_NAME("ADC Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
EBBACK();
break;
case 3: // SBB
INST_NAME("SBB Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
EBBACK();
break;
case 4: // AND
INST_NAME("AND Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_and8c(dyn, ninst, x1, u8, x2, x4);
EBBACK();
break;
case 5: // SUB
INST_NAME("SUB Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
EBBACK();
break;
case 6: // XOR
INST_NAME("XOR Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_xor8c(dyn, ninst, x1, u8, x2, x4);
EBBACK();
break;
case 7: // CMP
INST_NAME("CMP Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
if (u8) {
MOV32w(x2, u8);
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6);
} else {
emit_cmp8_0(dyn, ninst, x1, x3, x4);
}
break;
default:
DEFAULT;
}
break;
case 0x81:
case 0x83:
nextop = F8;
grab_segdata(dyn, addr, ninst, x6, seg);
switch ((nextop >> 3) & 7) {
case 0:
if (opcode == 0x81) {
INST_NAME("ADD Ed, Id");
} else {
INST_NAME("ADD Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x7);
WBACKO(x6);
break;
case 1:
if (opcode == 0x81) {
INST_NAME("OR Ed, Id");
} else {
INST_NAME("OR Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACKO(x6);
break;
case 2:
if (opcode == 0x81) {
INST_NAME("ADC Ed, Id");
} else {
INST_NAME("ADC Ed, Ib");
}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
MOV64xw(x5, i64);
IFXA (X_ALL, !la64_lbt)
ST_D(x6, xEmu, offsetof(x64emu_t, scratch));
emit_adc32(dyn, ninst, rex, ed, x5, x3, x4, x6, x7);
IFXA (X_ALL, !la64_lbt) {
LD_D(x6, xEmu, offsetof(x64emu_t, scratch));
}
WBACKO(x6);
break;
case 3:
if (opcode == 0x81) {
INST_NAME("SBB Ed, Id");
} else {
INST_NAME("SBB Ed, Ib");
}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
MOV64xw(x5, i64);
emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4, x7);
WBACKO(x6);
break;
case 4:
if (opcode == 0x81) {
INST_NAME("AND Ed, Id");
} else {
INST_NAME("AND Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_and32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACKO(x6);
break;
case 5:
if (opcode == 0x81) {
INST_NAME("SUB Ed, Id");
} else {
INST_NAME("SUB Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x7);
WBACKO(x6);
break;
case 6:
if (opcode == 0x81) {
INST_NAME("XOR Ed, Id");
} else {
INST_NAME("XOR Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_xor32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACKO(x6);
break;
case 7:
if (opcode == 0x81) {
INST_NAME("CMP Ed, Id");
} else {
INST_NAME("CMP Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
if (i64) {
MOV64xw(x2, i64);
emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6);
} else
emit_cmp32_0(dyn, ninst, rex, ed, x3, x4);
break;
}
break;
case 0x89:
INST_NAME("MOV Seg:Ed, Gd");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
if (MODREG) { // reg <= reg
MVxw(TO_NAT((nextop & 7) + (rex.b << 3)), gd);
} else { // mem <= reg
if (rex.is32bits) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
ADDz(x4, ed, x4);
SDxw(gd, x4, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 0, 0);
SDXxw(gd, ed, x4);
}
SMWRITE2();
}
break;
case 0x8B:
INST_NAME("MOV Gd, Seg:Ed");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
if (MODREG) { // reg <= reg
MVxw(gd, TO_LA64((nextop & 7) + (rex.b << 3)));
MVxw(gd, TO_NAT((nextop & 7) + (rex.b << 3)));
} else { // mem <= reg
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
ADD_D(x4, ed, x4);
LDxw(gd, x4, fixedaddress);
if (rex.is32bits) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
ADDz(x4, ed, x4);
LDxw(gd, x4, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 0, 0);
LDXxw(gd, ed, x4);
}
}
break;
case 0xA1:
INST_NAME("MOV EAX, FS:Od");
grab_segdata(dyn, addr, ninst, x4, seg);
if (rex.is32bits)
u64 = F32;
else
u64 = F64;
MOV64z(x1, u64);
if (rex.is32bits) {
ADDz(x4, x1, x4);
LDxw(xRAX, x4, 0);
} else
LDXxw(xRAX, x4, x1);
break;
case 0xC6:
INST_NAME("MOV Seg:Eb, Ib");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
if (MODREG) { // reg <= u8
u8 = F8;
if (!rex.rex) {
ed = (nextop & 7);
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = (ed & 4) >> 2; // L or H
} else {
eb1 = TO_NAT((nextop & 7) + (rex.b << 3));
eb2 = 0;
}
MOV32w(x3, u8);
BSTRINS_D(eb1, x3, eb2 * 8 + 7, eb2 * 8);
} else { // mem <= u8
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 1);
u8 = F8;
if (u8) {
ADDI_D(x3, xZR, u8);
ed = x3;
} else
ed = xZR;
if (rex.is32bits) {
ADDz(x4, wback, x4);
ST_B(ed, x4, 0);
} else {
STX_B(ed, wback, x4);
}
SMWRITE2();
}
break;
case 0xC7:
INST_NAME("MOV Seg:Ed, Id");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
if (MODREG) { // reg <= i32
i64 = F32S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV64xw(ed, i64);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 4);
i64 = F32S;
if (i64) {
MOV64x(x3, i64);
ed = x3;
} else
ed = xZR;
if (rex.is32bits) {
ADDz(x4, wback, x4);
SDxw(ed, x4, 0);
} else {
SDXxw(ed, wback, x4);
}
SMWRITE2();
}
break;
default:
+364 -30
View File
@@ -20,7 +20,7 @@
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_la64_functions.h"
@@ -83,7 +83,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
BSTRPICK_D(x1, xRAX, 15, 0);
MOV32w(x2, i32);
emit_add16(dyn, ninst, x1, x2, x3, x4, x6);
BSTRINS_D(xRAX, x1, 15, 0);
BSTRINSz(xRAX, x1, 15, 0);
break;
case 0x09:
INST_NAME("OR Ew, Gw");
@@ -91,7 +91,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_or16(dyn, ninst, x1, x2, x4, x2);
emit_or16(dyn, ninst, x1, x2, x4, x5);
EWBACK;
break;
case 0x0B:
@@ -103,6 +103,15 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
emit_or16(dyn, ninst, x1, x2, x4, x5);
GWBACK;
break;
case 0x0D:
INST_NAME("OR AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
MOV32w(x2, i32);
emit_or16(dyn, ninst, x1, x2, x3, x4);
BSTRINSz(xRAX, x1, 15, 0);
break;
case 0x0F:
switch (rep) {
case 0: addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
@@ -110,6 +119,36 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
DEFAULT;
}
break;
case 0x11:
INST_NAME("ADC Ew, Gw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_adc16(dyn, ninst, x1, x2, x4, x6, x5);
EWBACK;
break;
case 0x13:
INST_NAME("ADC Gw, Ew");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_adc16(dyn, ninst, x1, x2, x4, x6, x5);
GWBACK;
break;
case 0x15:
INST_NAME("ADC AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
u64 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
MOV64x(x2, u64);
emit_adc16(dyn, ninst, x1, x2, x3, x4, x5);
BSTRINSz(xRAX, x1, 15, 0);
break;
case 0x19:
INST_NAME("SBB Ew, Gw");
READFLAGS(X_CF);
@@ -120,6 +159,26 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
emit_sbb16(dyn, ninst, x1, x2, x4, x5, x6);
EWBACK;
break;
case 0x1B:
INST_NAME("SBB Gw, Ew");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_sbb16(dyn, ninst, x1, x2, x6, x4, x5);
GWBACK;
break;
case 0x1D:
INST_NAME("SBB AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
BSTRPICK_D(x1, xRAX, 15, 0);
u64 = F16;
MOV64x(x2, u64);
emit_sbb16(dyn, ninst, x1, x2, x3, x4, x5);
BSTRINSz(xRAX, x1, 15, 0);
break;
case 0x21:
INST_NAME("AND Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -145,7 +204,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
BSTRPICK_D(x1, xRAX, 15, 0);
MOV32w(x2, i32);
emit_and16(dyn, ninst, x1, x2, x3, x4);
BSTRINS_D(xRAX, x1, 15, 0);
BSTRINSz(xRAX, x1, 15, 0);
break;
case 0x29:
INST_NAME("SUB Ew, Gw");
@@ -172,7 +231,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
BSTRPICK_D(x1, xRAX, 15, 0);
MOV32w(x2, i32);
emit_sub16(dyn, ninst, x1, x2, x3, x4, x5);
BSTRINS_D(xRAX, x1, 15, 0);
BSTRINSz(xRAX, x1, 15, 0);
break;
case 0x31:
INST_NAME("XOR Ew, Gw");
@@ -183,6 +242,24 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
emit_xor16(dyn, ninst, x1, x2, x4, x5, x6);
EWBACK;
break;
case 0x33:
INST_NAME("XOR Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_xor16(dyn, ninst, x1, x2, x3, x4, x5);
GWBACK;
break;
case 0x35:
INST_NAME("XOR AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
MOV32w(x2, i32);
emit_xor16(dyn, ninst, x1, x2, x3, x4, x5);
BSTRINSz(xRAX, x1, 15, 0);
break;
case 0x39:
INST_NAME("CMP Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -211,6 +288,36 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
emit_cmp16_0(dyn, ninst, x1, x3, x4);
}
break;
case 0x64:
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _FS, ok, need_epilog);
break;
case 0x65:
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _GS, ok, need_epilog);
break;
case 0x66:
addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0x69:
case 0x6B:
if (opcode == 0x69) {
INST_NAME("IMUL Gw,Ew,Iw");
} else {
INST_NAME("IMUL Gw,Ew,Ib");
}
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
GETSEW(x1, (opcode == 0x69) ? 2 : 1);
if (opcode == 0x69)
i32 = F16S;
else
i32 = F8S;
MOV32w(x2, i32);
MUL_W(x2, x2, x1);
UFLAG_RES(x2);
gd = x2;
GWBACK;
UFLAG_DF(x1, d_imul16);
break;
case 0x81:
case 0x83:
nextop = F8;
@@ -224,10 +331,10 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
i16 = F16S;
u64 = F16;
else
i16 = F8S;
MOV64x(x5, i16);
u64 = (uint16_t)(int16_t)F8S;
MOV64x(x5, u64);
emit_add16(dyn, ninst, ed, x5, x2, x4, x6);
EWBACK;
break;
@@ -240,13 +347,47 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
i16 = F16S;
u64 = F16;
else
i16 = F8S;
MOV64x(x5, i16);
u64 = (uint16_t)(int16_t)F8S;
MOV64x(x5, u64);
emit_or16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 2: // ADC
if (opcode == 0x81) {
INST_NAME("ADC Ew, Iw");
} else {
INST_NAME("ADC Ew, Ib");
}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
u64 = F16;
else
u64 = (uint16_t)(int16_t)F8S;
MOV64x(x5, u64);
emit_adc16(dyn, ninst, x1, x5, x2, x4, x6);
EWBACK;
break;
case 3: // SBB
if (opcode == 0x81) {
INST_NAME("SBB Ew, Iw");
} else {
INST_NAME("SBB Ew, Ib");
}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
u64 = F16;
else
u64 = (uint16_t)(int16_t)F8S;
MOV64x(x5, u64);
emit_sbb16(dyn, ninst, x1, x5, x2, x4, x6);
EWBACK;
break;
case 4: // AND
if (opcode == 0x81) {
INST_NAME("AND Ew, Iw");
@@ -256,10 +397,10 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
i16 = F16S;
u64 = F16;
else
i16 = F8S;
MOV64x(x5, i16);
u64 = (uint16_t)(int16_t)F8S;
MOV64x(x5, u64);
emit_and16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -272,13 +413,29 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
i16 = F16S;
u64 = F16;
else
i16 = F8S;
MOV32w(x5, i16);
u64 = (uint16_t)(int16_t)F8S;
MOV32w(x5, u64);
emit_sub16(dyn, ninst, x1, x5, x2, x4, x6);
EWBACK;
break;
case 6: // XOR
if (opcode == 0x81) {
INST_NAME("XOR Ew, Iw");
} else {
INST_NAME("XOR Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
u64 = F16;
else
u64 = (uint16_t)(int16_t)F8S;
MOV32w(x5, u64);
emit_xor16(dyn, ninst, x1, x5, x2, x4, x6);
EWBACK;
break;
case 7: // CMP
if (opcode == 0x81) {
INST_NAME("CMP Ew, Iw");
@@ -288,11 +445,11 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
i16 = F16S;
u64 = F16;
else
i16 = F8S;
if (i16) {
MOV64x(x2, i16);
u64 = (uint16_t)(int16_t)F8S;
if (u64) {
MOV64x(x2, u64);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
} else
emit_cmp16_0(dyn, ninst, x1, x3, x4);
@@ -314,9 +471,9 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if (ed != gd) {
BSTRINS_D(ed, gd, 15, 0);
BSTRINSz(ed, gd, 15, 0);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
@@ -324,6 +481,22 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SMWRITELOCK(lock);
}
break;
case 0x8B:
INST_NAME("MOV Gw, Ew");
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if (ed != gd) {
BSTRINSz(gd, ed, 15, 0);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
SMREADLOCK(lock);
LD_HU(x1, ed, fixedaddress);
BSTRINSz(gd, x1, 15, 0);
}
break;
case 0x90:
case 0x91:
case 0x92:
@@ -332,16 +505,86 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x95:
case 0x96:
case 0x97:
gd = TO_LA64((opcode & 0x07) + (rex.b << 3));
gd = TO_NAT((opcode & 0x07) + (rex.b << 3));
if (gd == xRAX) {
INST_NAME("NOP");
} else {
INST_NAME("XCHG AX, Reg");
MV(x2, xRAX);
BSTRINS_D(xRAX, gd, 15, 0);
BSTRINS_D(gd, x2, 15, 0);
BSTRINSz(xRAX, gd, 15, 0);
BSTRINSz(gd, x2, 15, 0);
}
break;
case 0xA4:
if (rep) {
INST_NAME("REP MOVSB");
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1 << F_DF);
BNEZ_MARK2(x1);
MARK; // Part with DF==0
LD_BU(x1, xRSI, 0);
ST_B(x1, xRDI, 0);
ADDI_D(xRSI, xRSI, 1);
ADDI_D(xRDI, xRDI, 1);
ADDI_D(xRCX, xRCX, -1);
BNEZ_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
LD_BU(x1, xRSI, 0);
ST_B(x1, xRDI, 0);
ADDI_D(xRSI, xRSI, -1);
ADDI_D(xRDI, xRDI, -1);
ADDI_D(xRCX, xRCX, -1);
BNEZ_MARK2(xRCX);
// done
} else {
INST_NAME("MOVSB");
GETDIR(x3, x1, 1);
LD_BU(x1, xRSI, 0);
ST_B(x1, xRDI, 0);
ADD_D(xRSI, xRSI, x3);
ADD_D(xRDI, xRDI, x3);
}
break;
case 0xA5:
if (rep) {
INST_NAME("REP MOVSW");
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1 << F_DF);
BNEZ_MARK2(x1);
MARK; // Part with DF==0
LD_H(x1, xRSI, 0);
ST_H(x1, xRDI, 0);
ADDI_D(xRSI, xRSI, 2);
ADDI_D(xRDI, xRDI, 2);
ADDI_D(xRCX, xRCX, -1);
BNEZ_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
LD_H(x1, xRSI, 0);
ST_H(x1, xRDI, 0);
ADDI_D(xRSI, xRSI, -2);
ADDI_D(xRDI, xRDI, -2);
ADDI_D(xRCX, xRCX, -1);
BNEZ_MARK2(xRCX);
// done
} else {
INST_NAME("MOVSW");
GETDIR(x3, x1, 2);
LD_H(x1, xRSI, 0);
ST_H(x1, xRDI, 0);
ADD_D(xRSI, xRSI, x3);
ADD_D(xRDI, xRDI, x3);
}
break;
case 0xA9:
INST_NAME("TEST AX,Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
u16 = F16;
MOV32w(x2, u16);
BSTRPICK_D(x1, xRAX, 15, 0);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0xAB:
if (rep) {
INST_NAME("REP STOSW");
@@ -378,8 +621,8 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("MOV Reg16, Iw");
u16 = F16;
MOV32w(x1, u16);
gd = TO_LA64((opcode & 7) + (rex.b << 3));
BSTRINS_D(gd, x1, 15, 0);
gd = TO_NAT((opcode & 7) + (rex.b << 3));
BSTRINSz(gd, x1, 15, 0);
break;
case 0xC1:
nextop = F8;
@@ -436,6 +679,20 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr16);
break;
case 7:
INST_NAME("SAR Ew, Ib");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_IF { MESSAGE(LOG_DUMP, "Need Optimization for flags\n"); }
GETSEW(x1, 1);
u8 = F8;
UFLAG_IF { MOV32w(x2, (u8 & 15)); }
UFLAG_OP12(ed, x2)
SRAI_D(ed, ed, u8 & 15);
if (MODREG) BSTRPICK_D(ed, ed, 15, 0);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar16);
break;
default:
DEFAULT;
}
@@ -444,10 +701,10 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("MOV Ew, Iw");
nextop = F8;
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
u16 = F16;
MOV32w(x1, u16);
BSTRINS_D(ed, x1, 15, 0);
BSTRINSz(ed, x1, 15, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 2);
u16 = F16;
@@ -524,9 +781,86 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
MOV32w(x2, u16);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 3:
INST_NAME("NEG Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, 0);
emit_neg16(dyn, ninst, ed, x2, x4);
EWBACK;
break;
case 6:
INST_NAME("DIV Ew");
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE();
GETEW(x1, 0);
BSTRPICK_D(x2, xRAX, 15, 0);
SLLI_D(x7, xRDX, 48);
SRLI_D(x7, x7, 32);
OR(x2, x2, x7);
if(box64_dynarec_div0) {
BNE_MARK3(ed, xZR);
GETIP_(ip);
STORE_XEMU_CALL();
CALL(native_div0, -1);
CLEARIP();
LOAD_XEMU_CALL();
jump_to_epilog(dyn, 0, xRIP, ninst);
MARK3;
}
DIV_WU(x7, x2, ed);
MOD_WU(x4, x2, ed);
BSTRINSz(xRAX, x7, 15, 0);
BSTRINSz(xRDX, x4, 15, 0);
break;
case 7:
INST_NAME("IDIV Ew");
NOTEST(x1);
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE();
GETSEW(x1, 0);
if (box64_dynarec_div0) {
BNE_MARK3(ed, xZR);
GETIP_(ip);
STORE_XEMU_CALL();
CALL(native_div0, -1);
CLEARIP();
LOAD_XEMU_CALL();
jump_to_epilog(dyn, 0, xRIP, ninst);
MARK3;
}
BSTRPICK_D(x2, xRAX, 15, 0);
SLLI_D(x3, xRDX, 16);
OR(x2, x2, x3);
DIV_W(x3, x2, ed);
MOD_W(x4, x2, ed);
BSTRINSz(xRAX, x3, 15, 0);
BSTRINSz(xRDX, x4, 15, 0);
break;
default:
DEFAULT;
}
break;
case 0xFF:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("INC Ew");
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING);
GETEW(x1, 0);
emit_inc16(dyn, ninst, x1, x2, x4, x5);
EWBACK;
break;
case 1:
INST_NAME("DEC Ew");
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING);
GETEW(x1, 0);
emit_dec16(dyn, ninst, x1, x2, x4, x5, x6);
EWBACK;
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
+570 -10
View File
@@ -21,7 +21,7 @@
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_functions.h"
#include "dynarec_la64_helper.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
@@ -51,6 +51,48 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
MAYUSE(j64);
switch (opcode) {
case 0x10:
INST_NAME("MOVUPD Gx,Ex");
nextop = F8;
GETG;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if (MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0);
VOR_V(v0, v1, v1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0);
VLD(v0, ed, fixedaddress);
}
break;
case 0x11:
INST_NAME("MOVUPD Ex,Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if (MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop & 7) + (rex.b << 3));
VOR_V(v1, v0, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0);
VST(v0, ed, fixedaddress);
SMWRITE2();
}
break;
case 0x12:
INST_NAME("MOVLPD Gx, Eq");
nextop = F8;
GETGX(v0, 1);
if (MODREG) {
DEFAULT;
return addr;
}
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0);
v1 = fpu_get_scratch(dyn);
FLD_D(v1, wback, fixedaddress);
VEXTRINS_D(v0, v1, 0);
break;
case 0x14:
INST_NAME("UNPCKLPD Gx, Ex");
nextop = F8;
@@ -65,6 +107,21 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
VEXTRINS_D(v0, v1, 0x10);
break;
case 0x16:
INST_NAME("MOVHPD Gx, Eq");
nextop = F8;
GETGX(v0, 1);
if (MODREG) {
// access register instead of memory is bad opcode!
DEFAULT;
return addr;
}
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0);
v1 = fpu_get_scratch(dyn);
FLD_D(v1, ed, fixedaddress);
VEXTRINS_D(v0, v1, 0x10);
break;
case 0x1F:
INST_NAME("NOP (multibyte)");
nextop = F8;
@@ -86,6 +143,21 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
VLD(v0, ed, fixedaddress);
}
break;
case 0x29:
INST_NAME("MOVAPD Ex,Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if (MODREG) {
ed = (nextop & 7) + (rex.b << 3);
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VOR_V(v1, v0, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0);
VST(v0, ed, fixedaddress);
SMWRITE2();
}
break;
case 0x2E:
// no special check...
case 0x2F:
@@ -248,6 +320,150 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
DEFAULT;
}
break;
case 0x3A: // these are some more SSSE3+ opcodes
opcode = F8;
switch (opcode) {
case 0x0F:
INST_NAME("PALIGNR Gx, Ex, Ib");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 1);
u8 = F8;
if (u8 > 31) {
VXOR_V(q0, q0, q0);
} else if (u8 > 15) {
VBSRL_V(q0, q0, u8 - 16);
} else if (!u8) {
VOR_V(q0, q1, q1);
} else {
d0 = fpu_get_scratch(dyn);
VBSLL_V(q0, q0, 16 - u8);
VBSRL_V(d0, q1, u8);
VOR_V(q0, q0, d0);
}
break;
case 0x16:
if (rex.w) {
INST_NAME("PEXTRQ Ed, Gx, Ib");
} else {
INST_NAME("PEXTRD Ed, Gx, Ib");
}
nextop = F8;
GETGX(q0, 0);
d0 = fpu_get_scratch(dyn);
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
u8 = F8;
if (rex.w) {
VBSRL_V(d0, q0, (u8 & 1) * 8);
MOVFR2GR_D(ed, d0);
} else {
VBSRL_V(d0, q0, (u8 & 3) * 4);
MOVFR2GR_S(ed, d0);
ZEROUP(ed);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, x5, &fixedaddress, rex, NULL, 1, 1);
u8 = F8;
if (rex.w) {
VBSRL_V(d0, q0, (u8 & 1) * 8);
FST_D(d0, ed, fixedaddress);
} else {
VBSRL_V(d0, q0, (u8 & 3) * 4);
FST_S(d0, ed, fixedaddress);
}
SMWRITE2();
}
break;
case 0x22:
INST_NAME("PINSRD Gx, ED, Ib");
nextop = F8;
GETGX(q0, 1);
GETED(1);
u8 = F8;
d0 = fpu_get_scratch(dyn);
if (rex.w) {
MOVGR2FR_D(d0, ed);
VEXTRINS_D(q0, d0, (u8 & 1) << 4);
} else {
MOVGR2FR_W(d0, ed);
VEXTRINS_W(q0, d0, (u8 & 3) << 4);
}
break;
case 0x44:
INST_NAME("PCLMULQDQ Gx, Ex, Ib");
nextop = F8;
GETG;
sse_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd); // gx
if (MODREG) {
ed = (nextop & 7) + (rex.b << 3);
sse_forget_reg(dyn, ninst, ed);
MOV32w(x2, ed);
MOV32w(x3, 0); // p = NULL
} else {
MOV32w(x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, x5, &fixedaddress, rex, NULL, 0, 1);
if (ed != x3) {
MV(x3, ed);
}
}
u8 = F8;
MOV32w(x4, u8);
CALL(native_pclmul, -1);
break;
case 0xDF:
INST_NAME("AESKEYGENASSIST Gx, Ex, Ib"); // AES-NI
nextop = F8;
GETG;
sse_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd); // gx
if (MODREG) {
ed = (nextop & 7) + (rex.b << 3);
sse_forget_reg(dyn, ninst, ed);
MOV32w(x2, ed);
MOV32w(x3, 0); // p = NULL
} else {
MOV32w(x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, 1);
if (ed != x3) {
MV(x3, ed);
}
}
u8 = F8;
MOV32w(x4, u8);
CALL(native_aeskeygenassist, -1);
break;
default:
DEFAULT;
}
break;
#define GO(GETFLAGS, NO, YES, F, I) \
READFLAGS(F); \
if (la64_lbt) { \
X64_SETJ(x1, I); \
} else { \
GETFLAGS; \
} \
nextop = F8; \
GETGD; \
if (MODREG) { \
ed = TO_NAT((nextop & 7) + (rex.b << 3)); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x4, &fixedaddress, rex, NULL, 1, 0); \
LD_HU(x4, ed, fixedaddress); \
ed = x4; \
} \
if (la64_lbt) \
BEQZ(x1, 4 + 4); \
else \
B##NO(x1, 4 + 4); \
BSTRINS_D(gd, ed, 15, 0);
GOCOND(0x40, "CMOV", "Gd, Ed");
#undef GO
case 0x54:
INST_NAME("ANDPD Gx, Ex");
nextop = F8;
@@ -283,17 +499,128 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
VXOR_V(q0, q0, q1);
}
break;
case 0x58:
INST_NAME("ADDPD Gx, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGX(q1, 1);
if (!box64_dynarec_fastnan) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
VFCMP_D(v0, q0, q1, cUN);
}
VFADD_D(q1, q1, q0);
if (!box64_dynarec_fastnan) {
VFCMP_D(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
VSLLI_D(v1, v1, 48);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
}
break;
case 0x59:
INST_NAME("MULPD Gx, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGX(q1, 1);
if (!box64_dynarec_fastnan) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
VFCMP_D(v0, q0, q1, cUN);
}
VFMUL_D(q1, q1, q0);
if (!box64_dynarec_fastnan) {
VFCMP_D(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
VSLLI_D(v1, v1, 48);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
}
break;
case 0x5A:
INST_NAME("CVTPD2PS Gx, Ex");
nextop = F8;
GETEX(v1, 0, 0);
GETGX_empty(v0);
// TODO: is there any way to support !box64_dynarec_fastround?
// TODO: !box64_dynarec_fastround
q0 = fpu_get_scratch(dyn);
VFCVT_S_D(q0, v1, v1);
VXOR_V(v0, v0, v0);
VEXTRINS_D(v0, q0, 0);
break;
case 0x5B:
INST_NAME("CVTPS2DQ Gx, Ex");
nextop = F8;
GETEX(v1, 0, 0);
GETGX_empty(v0);
u8 = sse_setround(dyn, ninst, x6, x4);
if (v0 == v1 && !box64_dynarec_fastround) {
v1 = fpu_get_scratch(dyn);
VOR_V(v1, v0, v0);
}
VFTINT_W_S(v0, v1);
if (!box64_dynarec_fastround) {
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VFCMP_S(q0, v1, v1, cEQ);
VLDI(q1, 0b1001110000000); // broadcast 0x80000000
VAND_V(v0, q0, v0);
VANDN_V(d1, q0, q1);
VOR_V(v0, v0, d1);
VSUBI_WU(d1, q1, 1);
VSEQ_W(q0, v0, d1);
VSRLI_W(q0, q0, 31);
VADD_W(v0, v0, q0);
}
x87_restoreround(dyn, ninst, u8);
break;
case 0x5C:
INST_NAME("SUBPD Gx, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGX(q1, 1);
if (!box64_dynarec_fastnan) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
VFCMP_D(v0, q0, q1, cUN);
}
VFSUB_D(q1, q1, q0);
if (!box64_dynarec_fastnan) {
VFCMP_D(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
VSLLI_D(v1, v1, 48);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
}
break;
case 0x5E:
INST_NAME("DIVPD Gx, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGX(q1, 1);
if (!box64_dynarec_fastnan) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
VFCMP_D(v0, q0, q1, cUN);
}
VFDIV_D(q1, q1, q0);
if (!box64_dynarec_fastnan) {
VFCMP_D(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
VSLLI_D(v1, v1, 48);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
}
break;
case 0x60:
INST_NAME("PUNPCKLBW Gx,Ex");
nextop = F8;
@@ -315,6 +642,21 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETEX(q0, 0, 0);
VILVL_W(v0, q0, v0);
break;
case 0x63:
INST_NAME("PACKSSWB Gx,Ex");
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 0);
q0 = fpu_get_scratch(dyn);
if (v0 == v1) {
VSAT_H(v0, v0, 7);
VPICKEV_B(v0, v0, v0);
} else {
VSAT_H(v0, v0, 7);
VSAT_H(q0, v1, 7);
VPICKEV_B(v0, q0, v0);
}
break;
case 0x64:
INST_NAME("PCMPGTB Gx,Ex");
nextop = F8;
@@ -377,6 +719,16 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETEX(q1, 0, 0);
VILVH_W(q0, q1, q0);
break;
case 0x6B:
INST_NAME("PACKSSDW Gx,Ex");
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 0);
d0 = fpu_get_scratch(dyn);
VOR_V(d0, v1, v1);
VSSRANI_H_W(d0, v0, 0);
VOR_V(v0, d0, d0);
break;
case 0x6C:
INST_NAME("PUNPCKLQDQ Gx,Ex");
nextop = F8;
@@ -410,7 +762,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGX_empty(v0);
v1 = fpu_get_scratch(dyn);
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if (rex.w) {
MOVGR2FR_D(v1, ed);
} else {
@@ -596,6 +948,20 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
DEFAULT;
}
break;
case 0x74:
INST_NAME("PCMPEQB Gx,Ex");
nextop = F8;
GETGX(v0, 1);
GETEX(q0, 0, 0);
VSEQ_B(v0, v0, q0);
break;
case 0x75:
INST_NAME("PCMPEQW Gx,Ex");
nextop = F8;
GETGX(v0, 1);
GETEX(q0, 0, 0);
VSEQ_H(v0, v0, q0);
break;
case 0x76:
INST_NAME("PCMPEQD Gx,Ex");
nextop = F8;
@@ -609,7 +975,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGX(v0, 0);
if (rex.w) {
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOVFR2GR_D(ed, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0);
@@ -618,7 +984,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
} else {
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOVFR2GR_S(ed, v0);
ZEROUP(ed);
} else {
@@ -645,13 +1011,13 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("IMUL Gw,Ew");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
UFLAG_DF(x1, d_imul16);
GETSEW(x1, 0);
GETSGW(x2);
MUL_W(x2, x2, x1);
UFLAG_RES(x2);
BSTRPICK_D(x2, x2, 15, 0);
GWBACK;
UFLAG_DF(x1, d_imul16);
break;
case 0xBE:
INST_NAME("MOVSX Gw, Eb");
@@ -659,12 +1025,12 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGD;
if (MODREG) {
if (rex.rex) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
eb1 = ed;
eb2 = 0;
} else {
ed = (nextop & 7);
eb1 = TO_LA64(ed & 3); // Ax, Cx, Dx or Bx
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = (ed & 4) >> 2; // L or H
}
if (eb2) {
@@ -680,6 +1046,80 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
BSTRINS_D(gd, x1, 15, 0);
break;
case 0xC4:
INST_NAME("PINSRW Gx, Ed, Ib");
nextop = F8;
GETGX(v0, 1);
if (MODREG) {
u8 = (F8) & 7;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x4, &fixedaddress, rex, NULL, 1, 1);
u8 = (F8) & 7;
ed = x3;
LD_HU(ed, wback, fixedaddress);
}
d0 = fpu_get_scratch(dyn);
MOVGR2FR_D(d0, ed);
VEXTRINS_H(v0, d0, (u8 << 4));
break;
case 0xC5:
INST_NAME("PEXTRW Gd, Ex, Ib");
nextop = F8;
GETGD;
if (MODREG) {
GETEX(v0, 0, 1);
u8 = (F8) & 7;
v1 = fpu_get_scratch(dyn);
VBSRL_V(v1, v0, (u8 << 1));
MOVFR2GR_D(gd, v1);
BSTRPICK_D(gd, gd, 15, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x4, &fixedaddress, rex, NULL, 1, 1);
u8 = (F8) & 7;
LD_HU(gd, wback, (u8 << 1));
}
break;
case 0xC6:
INST_NAME("SHUFPD Gx, Ex, Ib");
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 1);
u8 = F8;
VSHUF4I_D(v0, v1, 0x8 | (u8 & 1) | ((u8 & 2) << 1));
break;
case 0xD2:
INST_NAME("PSRLD Gx, Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
VSAT_DU(v0, q1, 31);
VREPLVEI_W(v0, v0, 0);
VLDI(v1, 0b1000000011111); // broadcast 31 as uint32
VSLT_WU(v1, v1, v0);
VMINI_WU(v0, v0, 31);
VSRL_W(q0, q0, v0);
VSRL_W(q0, q0, v1);
break;
case 0xD3:
INST_NAME("PSRLQ Gx,Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn);
VREPLVEI_D(v0, q1, 0);
VLDI(v1, 0b0110000111111); // broadcast 63 as uint64
VMIN_DU(d0, v0, v1);
VSLT_DU(v1, v1, v0);
VSRL_D(q0, q0, d0);
VSRL_D(q0, q0, v1);
break;
case 0xD4:
INST_NAME("PADDQ Gx, Ex");
nextop = F8;
@@ -700,14 +1140,39 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGX(v0, 0);
if (MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop & 7) + (rex.b << 3));
VXOR_V(v1, v1, v1);
VEXTRINS_D(v1, v0, 0);
if (v0 == v1) {
// clear upper bits
q0 = fpu_get_scratch(dyn);
VXOR_V(q0, q0, q0);
VEXTRINS_D(q0, v0, 0);
VOR_V(v1, q0, q0);
} else {
VXOR_V(v1, v1, v1);
VEXTRINS_D(v1, v0, 0);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0);
FST_D(v0, ed, fixedaddress);
SMWRITE2();
}
break;
case 0xD7:
INST_NAME("PMOVMSKB Gd, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGD;
v0 = fpu_get_scratch(dyn);
VMSKLTZ_B(v0, q0);
MOVFR2GR_D(x1, v0);
BSTRPICK_D(gd, x1, 15, 0);
break;
case 0xD9:
INST_NAME("PSUBUSW Gx, Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
VSSUB_HU(q0, q0, q1);
break;
case 0xDB:
INST_NAME("PAND Gx,Ex");
nextop = F8;
@@ -715,6 +1180,13 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETEX(q0, 0, 0);
VAND_V(v0, v0, q0);
break;
case 0xDC:
INST_NAME("PADDUSB Gx,Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
VSADD_BU(q0, q0, q1);
break;
case 0xDF:
INST_NAME("PANDN Gx,Ex");
nextop = F8;
@@ -722,6 +1194,30 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETEX(q0, 0, 0);
VANDN_V(v0, v0, q0);
break;
case 0xE0:
INST_NAME("PAVGB Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 0);
VAVGR_BU(v0, v0, v1);
break;
case 0xE1:
INST_NAME("PSRAW Gx, Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
v0 = fpu_get_scratch(dyn);
VMINI_HU(v0, q1, 15);
VREPLVEI_H(v0, v0, 0);
VSRA_H(q0, q0, v0);
break;
case 0xE3:
INST_NAME("PAVGW Gx,Ex");
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 0);
VAVGR_HU(v0, v0, v1);
break;
case 0xE4:
INST_NAME("PMULHUW Gx,Ex");
nextop = F8;
@@ -729,6 +1225,33 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETEX(v1, 0, 0);
VMUH_HU(v0, v0, v1);
break;
case 0xE5:
INST_NAME("PMULHW Gx,Ex");
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 0);
VMUH_H(v0, v0, v1);
break;
case 0xE6:
INST_NAME("CVTTPD2DQ Gx, Ex");
nextop = F8;
GETEX(v1, 0, 0);
GETGX_empty(v0);
// TODO: fastround
VFTINTRZ_W_D(v0, v1, v1);
break;
case 0xE7:
INST_NAME("MOVNTDQ Ex, Gx");
nextop = F8;
GETGX(v0, 0);
if (MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop & 7) + (rex.b << 3));
VOR_V(v1, v0, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0);
VST(v0, ed, fixedaddress);
}
break;
case 0xEB:
INST_NAME("POR Gx,Ex");
nextop = F8;
@@ -750,6 +1273,43 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
VXOR_V(q0, q0, q1);
}
break;
case 0xF4:
INST_NAME("PMULUDQ Gx,Ex");
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 0);
VMULWEV_D_WU(v0, v0, v1);
break;
case 0xF6:
INST_NAME("PSADBW Gx, Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VABSD_BU(q0, q0, q1);
// 8bit -> 16bit merge
VPICKEV_B(d0, q0, q0);
VPICKOD_B(d1, q0, q0);
VEXTH_HU_BU(d0, d0);
VEXTH_HU_BU(d1, d1);
VADD_H(q0, d0, d1);
// 16bit to 32bit merge
VPICKEV_H(d0, q0, q0);
VPICKOD_H(d1, q0, q0);
VEXTH_WU_HU(d0, d0);
VEXTH_WU_HU(d1, d1);
VADD_W(q0, d0, d1);
// 32bit to 64bit merge
VPICKEV_W(d0, q0, q0);
VPICKOD_W(d1, q0, q0);
VEXTH_DU_WU(d0, d0);
VEXTH_DU_WU(d1, d1);
VADD_D(q0, d0, d1);
break;
case 0xF8:
INST_NAME("PSUBB Gx,Ex");
nextop = F8;
+71
View File
@@ -0,0 +1,71 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "la64_emitter.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "../dynarec_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_6664(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
int64_t j64;
int v0, v1;
int64_t fixedaddress;
int unscaled;
MAYUSE(j64);
GETREX();
switch (opcode) {
case 0x8B:
INST_NAME("MOV Gd, FS:Ed");
nextop = F8;
GETGD;
if (MODREG) { // reg <= reg
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if (rex.w) {
MV(gd, ed);
} else {
if (ed != gd) BSTRINS_D(gd, ed, 15, 0);
}
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
ADDz(x4, ed, x4);
if (rex.w) {
LD_D(gd, x4, fixedaddress);
} else {
LD_HU(x1, x4, fixedaddress);
BSTRINS_D(gd, x1, 15, 0);
}
}
break;
default:
DEFAULT;
}
return addr;
}
+190
View File
@@ -0,0 +1,190 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include <assert.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "la64_emitter.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "../dynarec_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2, eb1, eb2;
int64_t fixedaddress;
int unscaled;
int8_t i8;
uint8_t u8;
int32_t i32;
int64_t j64, i64;
int cacheupd = 0;
int lock;
int v0, v1, s0;
MAYUSE(i32);
MAYUSE(j64);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(s0);
MAYUSE(lock);
MAYUSE(cacheupd);
if(rex.is32bits) {
// should do a different file
DEFAULT;
return addr;
}
GETREX();
rep = 0;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
switch(opcode) {
case 0x19:
INST_NAME("SBB Ed, Gd");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_sbb32(dyn, ninst, rex, ed, gd, x3, x4, x5);
WBACK;
break;
case 0x1A:
INST_NAME("SBB Gb, Eb");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_sbb8(dyn, ninst, x1, x2, x3, x4, x5);
GBBACK();
break;
case 0x1B:
INST_NAME("SBB Gd, Ed");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_sbb32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x1D:
INST_NAME("SBB EAX, Id");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
MOV64xw(x2, i64);
emit_sbb32(dyn, ninst, rex, xRAX, x2, x3, x4, x5);
break;
case 0x88:
INST_NAME("MOV Eb, Gb");
nextop = F8;
gd = ((nextop & 0x38) >> 3) + (rex.r << 3);
if (rex.rex) {
gb2 = 0;
gb1 = TO_NAT(gd);
} else {
gb2 = ((gd & 4) << 1);
gb1 = TO_NAT(gd & 3);
}
if (gb2) {
gd = x4;
BSTRPICK_D(gd, gb1, gb2 + 7, gb2);
} else {
gd = gb1; // no need to extract
}
if (MODREG) {
ed = (nextop & 7) + (rex.b << 3);
if (rex.rex) {
eb1 = TO_NAT(ed);
eb2 = 0;
} else {
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = ((ed & 4) >> 2); // L or H
}
BSTRINS_D(eb1, gd, eb2 * 8 + 7, eb2 * 8);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
ST_B(gb1, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0x89:
INST_NAME("MOV Ed, Gd");
nextop = F8;
GETGD;
if (MODREG) { // reg <= reg
MVxw(TO_NAT((nextop & 7) + (rex.b << 3)), gd);
} else { // mem <= reg
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
SDxw(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0x8D:
INST_NAME("LEA Gd, Ed");
nextop = F8;
GETGD;
if (MODREG) { // reg <= reg? that's an invalid operation
DEFAULT;
} else { // mem <= reg
addr = geted32(dyn, addr, ninst, nextop, &ed, gd, x1, &fixedaddress, rex, NULL, 0, 0);
ZEROUP2(gd, ed);
}
break;
case 0xF7:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 4:
INST_NAME("MUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
GETED32(0);
if (rex.w) {
if (ed == xRDX)
gd = x3;
else
gd = xRDX;
MULH_DU(gd, xRAX, ed);
MUL_D(xRAX, xRAX, ed);
if (gd != xRDX) MV(xRDX, gd);
} else {
MUL_D(xRDX, xRAX, ed); // 64 <- 32x32
ZEROUP2(xRAX, xRDX);
SRLI_W(xRDX, xRDX, 32);
}
UFLAG_RES(xRAX);
UFLAG_OP1(xRDX);
UFLAG_DF(x2, rex.w ? d_mul64 : d_mul32);
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
+9 -5
View File
@@ -20,7 +20,7 @@
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_functions.h"
#include "dynarec_la64_helper.h"
#include "../dynarec_helper.h"
// emit XOR8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_xor8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
@@ -465,7 +465,7 @@ void emit_or16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
IFXA (X_ALL, la64_lbt) {
X64_OR_W(s1, s2);
X64_OR_H(s1, s2);
}
OR(s1, s1, s2);
@@ -509,13 +509,15 @@ void emit_or32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
}
OR(s1, s1, s2);
if (!rex.w) ZEROUP(s1);
IFX(X_PEND) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
if(la64_lbt) return;
if (la64_lbt) {
if (!rex.w) ZEROUP(s1);
return;
}
CLEAR_FLAGS(s3);
// test sign bit before zeroup.
@@ -524,6 +526,8 @@ void emit_or32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) ZEROUP(s1);
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
+672 -28
View File
@@ -20,7 +20,7 @@
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_functions.h"
#include "dynarec_la64_helper.h"
#include "../dynarec_helper.h"
// emit ADD32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_add32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
@@ -57,8 +57,8 @@ void emit_add32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
IFX(X_CF)
{
if (rex.w) {
AND(s5, xMASK, s1);
AND(s4, xMASK, s2);
ZEROUP2(s5, s1);
ZEROUP2(s4, s2);
ADD_D(s5, s5, s4);
SRLI_D(s3, s1, 0x20);
SRLI_D(s4, s2, 0x20);
@@ -69,8 +69,8 @@ void emit_add32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
BEQZ(s5, 8);
ORI(xFlags, xFlags, 1 << F_CF);
} else {
AND(s3, s1, xMASK);
AND(s4, s2, xMASK);
ZEROUP2(s3, s1);
ZEROUP2(s4, s2);
ADD_D(s5, s3, s4);
SRLI_D(s5, s5, 0x20);
BEQZ(s5, 8);
@@ -134,17 +134,20 @@ void emit_add32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
if (s1 == xRSP && (!dyn->insts || dyn->insts[ninst].x64.gen_flags == X_PEND)) {
// special case when doing math on ESP and only PEND is needed: ignoring it!
if (c >= -2048 && c < 2048) {
ADDIxw(s1, s1, c);
ADDI_D(s1, s1, c);
} else {
MOV64xw(s2, c);
ADDxw(s1, s1, s2);
MOV64x(s2, c);
ADD_D(s1, s1, s2);
}
if (!rex.w) { ZEROUP(s1); }
return;
}
IFX(X_PEND | X_AF | X_CF | X_OF)
{
MOV64xw(s2, c);
} else if (la64_lbt) MOV64xw(s2, c);
} else if (la64_lbt) {
MOV64xw(s2, c);
}
IFX(X_PEND)
{
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
@@ -175,8 +178,8 @@ void emit_add32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
IFX(X_CF)
{
if (rex.w) {
AND(s5, xMASK, s1);
AND(s4, xMASK, s2);
ZEROUP2(s5, s1);
ZEROUP2(s4, s2);
ADD_D(s5, s5, s4);
SRLI_D(s3, s1, 0x20);
SRLI_D(s4, s2, 0x20);
@@ -187,8 +190,8 @@ void emit_add32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
BEQZ(s5, 8);
ORI(xFlags, xFlags, 1 << F_CF);
} else {
AND(s3, s1, xMASK);
AND(s4, s2, xMASK);
ZEROUP2(s3, s1);
ZEROUP2(s4, s2);
ADD_D(s5, s3, s4);
SRLI_D(s5, s5, 0x20);
BEQZ(s5, 8);
@@ -285,7 +288,7 @@ void emit_add8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
IFX(X_AF | X_OF) {
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
OR(s3, s3, s2); // cc = (~res & (op1 | op2)) | (op1 & op2)
OR(s3, s3, s4); // cc = (~res & (op1 | op2)) | (op1 & op2)
IFX(X_AF) {
ANDI(s4, s3, 0x08); // AF: cc & 0x08
BEQZ(s4, 8);
@@ -420,7 +423,7 @@ void emit_add16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
}
IFXA (X_ALL, la64_lbt) {
X64_ADD_DU(s1, s2);
X64_ADD_H(s1, s2);
}
ADD_D(s1, s1, s2);
@@ -640,6 +643,7 @@ void emit_sub32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
MOV64xw(s2, c);
SUBxw(s1, s1, s2);
}
if (!rex.w) { ZEROUP(s1); }
return;
}
@@ -727,7 +731,7 @@ void emit_sbb8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
X64_SBC_B(s1, s2);
}
MV(s1, s3);
ANDI(s1, s3, 0xff);
IFX (X_PEND)
ST_B(s1, xEmu, offsetof(x64emu_t, res));
return;
@@ -844,9 +848,9 @@ void emit_sbb32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
}
IFX (X_ALL) {
if (rex.w)
X64_SBC_W(s1, s2);
else
X64_SBC_D(s1, s2);
else
X64_SBC_W(s1, s2);
}
MVxw(s1, s3);
@@ -985,7 +989,7 @@ void emit_neg32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
return;
}
CLEAR_FLAGS(s3);
CLEAR_FLAGS(s2);
IFX (X_CF) {
BEQZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_CF);
@@ -1025,6 +1029,165 @@ void emit_neg32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
}
}
// emit ADC8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_adc8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_adc8);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
ADC_B(s3, s1, s2);
IFX (X_ALL) {
X64_ADC_B(s1, s2);
}
MV(s1, s3);
IFX (X_PEND) {
ST_W(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
IFX (X_AF | X_OF) {
OR(s4, s1, s2); // s4 = op1 | op2
AND(s5, s1, s2); // s5 = op1 & op2
}
ADD_D(s1, s1, s2);
ANDI(s3, xFlags, 1 << F_CF);
ADD_D(s1, s1, s3);
CLEAR_FLAGS(s3);
IFX (X_PEND) {
ST_W(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_AF | X_OF) {
ANDN(s3, s4, s1); // s3 = ~res & (op1 | op2)
OR(s3, s3, s5); // cc = (~res & (op1 | op2)) | (op1 & op2)
IFX (X_AF) {
ANDI(s4, s3, 0x08); // AF: cc & 0x08
BEQZ(s4, 8);
ORI(xFlags, xFlags, 1 << F_AF);
}
IFX (X_OF) {
SRLI_D(s3, s3, 6);
SRLI_D(s4, s3, 1);
XOR(s3, s3, s4);
ANDI(s3, s3, 1); // OF: xor of two MSB's of cc
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_OF);
}
}
IFX (X_CF) {
SRLI_D(s3, s1, 8);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_CF);
}
ANDI(s1, s1, 0xff);
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_SF) {
SRLI_D(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit ADC8 instruction, from s1, const c, store result in s1 using s3, s4, s5 and s6 as scratch
void emit_adc8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4, int s5, int s6)
{
MOV32w(s5, c & 0xff);
emit_adc8(dyn, ninst, s1, s5, s3, s4, s6);
}
// emit ADC16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_adc16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_adc16);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
ADC_H(s3, s1, s2);
IFX (X_ALL) {
X64_ADC_H(s1, s2);
}
MV(s1, s3);
IFX (X_PEND) {
ST_W(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
IFX (X_AF | X_OF) {
OR(s4, s1, s2); // s4 = op1 | op2
AND(s5, s1, s2); // s5 = op1 & op2
}
ADD_D(s1, s1, s2);
ANDI(s3, xFlags, 1 << F_CF);
ADD_D(s1, s1, s3);
CLEAR_FLAGS(s3);
IFX (X_PEND) {
ST_W(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_AF | X_OF) {
ANDN(s3, s4, s1); // s3 = ~res & (op1 | op2)
OR(s3, s3, s5); // cc = (~res & (op1 | op2)) | (op1 & op2)
IFX (X_AF) {
ANDI(s4, s3, 0x08); // AF: cc & 0x08
BEQZ(s4, 8);
ORI(xFlags, xFlags, 1 << F_AF);
}
IFX (X_OF) {
SRLI_D(s3, s3, 14);
SRLI_D(s4, s3, 1);
XOR(s3, s3, s4);
ANDI(s3, s3, 1); // OF: xor of two MSB's of cc
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_OF);
}
}
IFX (X_CF) {
SRLI_D(s3, s1, 16);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_CF);
}
BSTRPICK_D(s1, s1, 15, 0);
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_SF) {
SRLI_D(s3, s1, 15);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit ADC32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_adc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5, int s6)
{
@@ -1037,17 +1200,18 @@ void emit_adc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
}
if (la64_lbt) {
if (rex.w)
ADC_D(s3, s1, s2);
else
ADC_W(s3, s1, s2);
IFX (X_ALL) {
if (rex.w)
X64_ADC_D(s1, s2);
else
X64_ADC_W(s1, s2);
}
if (rex.w)
ADC_D(s1, s1, s2);
else
ADC_W(s1, s1, s2);
MV(s1, s3);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -1056,9 +1220,11 @@ void emit_adc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
IFX (X_CF) {
if (rex.w) {
AND(s5, xMASK, s1);
AND(s4, xMASK, s2);
ZEROUP2(s5, s1);
ZEROUP2(s4, s2);
ADD_D(s5, s5, s4); // lo
ANDI(s3, xFlags, 1);
ADD_D(s5, s5, s3); // add carry
SRLI_D(s3, s1, 0x20);
SRLI_D(s4, s2, 0x20);
ADD_D(s4, s4, s3);
@@ -1066,9 +1232,11 @@ void emit_adc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
ADD_D(s5, s5, s4); // hi
SRAI_D(s6, s5, 0x20);
} else {
AND(s3, s1, xMASK);
AND(s4, s2, xMASK);
ZEROUP2(s3, s1);
ZEROUP2(s4, s2);
ADD_D(s5, s3, s4);
ANDI(s3, xFlags, 1);
ADD_D(s5, s5, s3); // add carry
SRLI_D(s6, s5, 0x20);
}
}
@@ -1122,3 +1290,479 @@ void emit_adc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
ORI(xFlags, xFlags, 1 << F_ZF);
}
}
// emit INC8 instruction, from s1, store result in s1 using s2, s3 and s4 as scratch
void emit_inc8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, d_inc8);
} else IFX (X_ALL) {
SET_DFNONE();
}
IFXA (X_AF | X_OF, !la64_lbt) {
ORI(s3, s1, 1); // s3 = op1 | op2
ANDI(s4, s1, 1); // s5 = op1 & op2
}
IFXA (X_ALL, la64_lbt) {
X64_INC_B(s1);
}
ADDI_W(s1, s1, 1);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) {
ANDI(s1, s1, 0xff);
return;
}
IFX (X_ALL) {
// preserving CF
MOV64x(s4, (1UL << F_AF) | (1UL << F_OF) | (1UL << F_ZF) | (1UL << F_SF) | (1UL << F_PF));
ANDN(xFlags, xFlags, s4);
}
IFX (X_AF | X_OF) {
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
OR(s3, s3, s4); // cc = (~res & (op1 | op2)) | (op1 & op2)
IFX (X_AF) {
ANDI(s2, s3, 0x08); // AF: cc & 0x08
BEQZ(s2, 8);
ORI(xFlags, xFlags, 1 << F_AF);
}
IFX (X_OF) {
SRLI_D(s3, s3, 6);
SRLI_D(s2, s3, 1);
XOR(s3, s3, s2);
ANDI(s3, s3, 1); // OF: xor of two MSB's of cc
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_OF);
}
}
IFX (X_SF) {
ANDI(s2, s1, 0x80);
BEQZ(s2, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
ANDI(s1, s1, 0xff);
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s2);
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
}
// emit INC16 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_inc16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, d_inc16);
} else IFX (X_ZF | X_OF | X_AF | X_SF | X_PF) {
SET_DFNONE();
}
IFXA (X_AF | X_OF, !la64_lbt) {
ORI(s3, s1, 1); // s3 = op1 | op2
ANDI(s4, s1, 1); // s4 = op1 & op2
}
IFXA (X_ALL, la64_lbt) {
X64_INC_H(s1);
}
ADDI_D(s1, s1, 1);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) {
BSTRPICK_D(s1, s1, 15, 0);
return;
}
IFX (X_ALL) {
// preserving CF
MOV64x(s4, (1UL << F_AF) | (1UL << F_OF) | (1UL << F_ZF) | (1UL << F_SF) | (1UL << F_PF));
ANDN(xFlags, xFlags, s4);
}
IFX (X_AF | X_OF) {
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
OR(s3, s3, s4); // cc = (~res & (op1 | op2)) | (op1 & op2)
IFX (X_AF) {
ANDI(s4, s3, 0x08); // AF: cc & 0x08
BEQZ(s4, 8);
ORI(xFlags, xFlags, 1 << F_AF);
}
IFX (X_OF) {
SRLI_D(s3, s3, 14);
SRLI_D(s4, s3, 1);
XOR(s3, s3, s4);
ANDI(s3, s3, 1); // OF: xor of two MSB's of cc
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_OF);
}
}
BSTRPICK_D(s1, s1, 15, 0);
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_SF) {
SRLI_D(s3, s1, 15);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit INC32 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_inc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
{
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, rex.w ? d_inc64 : d_inc32);
} else IFX (X_ALL) {
SET_DFNONE();
}
IFXA (X_AF | X_OF, !la64_lbt) {
ORI(s3, s1, 1); // s3 = op1 | op2
ANDI(s5, s1, 1); // s5 = op1 & op2
}
IFXA (X_ALL, la64_lbt) {
if (rex.w) {
X64_INC_D(s1);
} else {
X64_INC_W(s1);
}
}
ADDIxw(s1, s1, 1);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) {
if (!rex.w) ZEROUP(s1);
return;
}
IFX (X_ALL) {
// preserving CF
MOV64x(s4, (1UL << F_AF) | (1UL << F_OF) | (1UL << F_ZF) | (1UL << F_SF) | (1UL << F_PF));
ANDN(xFlags, xFlags, s4);
}
IFX (X_AF | X_OF) {
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
OR(s3, s3, s5); // cc = (~res & (op1 | op2)) | (op1 & op2)
IFX (X_AF) {
ANDI(s2, s3, 0x08); // AF: cc & 0x08
BEQZ(s2, 8);
ORI(xFlags, xFlags, 1 << F_AF);
}
IFX (X_OF) {
SRLI_D(s3, s3, rex.w ? 62 : 30);
SRLI_D(s2, s3, 1);
XOR(s3, s3, s2);
ANDI(s3, s3, 1); // OF: xor of two MSB's of cc
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_OF);
}
}
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s2);
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
}
// emit DEC8 instruction, from s1, store result in s1 using s2, s3 and s4 as scratch
void emit_dec8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, d_dec8);
} else IFX (X_ALL) {
SET_DFNONE();
}
IFXA (X_AF | X_OF, !la64_lbt) {
NOR(s4, xZR, s1); // s4 = ~op1
ORI(s3, s4, 1); // s3 = ~op1 | op2
ANDI(s4, s4, 1); // s4 = ~op1 & op2
}
IFXA (X_ALL, la64_lbt) {
X64_DEC_B(s1);
}
ADDI_W(s1, s1, -1);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) {
ANDI(s1, s1, 0xff);
return;
}
IFX (X_ALL) {
// preserving CF
MOV64x(s4, (1UL << F_AF) | (1UL << F_OF) | (1UL << F_ZF) | (1UL << F_SF) | (1UL << F_PF));
ANDN(xFlags, xFlags, s4);
}
IFX (X_AF | X_OF) {
AND(s3, s1, s3); // s3 = res & (~op1 | op2)
OR(s3, s3, s4); // cc = (res & (~op1 | op2)) | (~op1 & op2)
IFX (X_AF) {
ANDI(s2, s3, 0x08); // AF: cc & 0x08
BEQZ(s2, 8);
ORI(xFlags, xFlags, 1 << F_AF);
}
IFX (X_OF) {
SRLI_D(s3, s3, 6);
SRLI_D(s2, s3, 1);
XOR(s3, s3, s2);
ANDI(s3, s3, 1); // OF: xor of two MSB's of cc
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_OF);
}
}
IFX (X_SF) {
ANDI(s2, s1, 0x80);
BEQZ(s2, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
ANDI(s1, s1, 0xff);
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s2);
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
}
// emit DEC16 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_dec16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, d_dec16);
} else IFX (X_ALL) {
SET_DFNONE();
}
IFX (X_AF | X_OF) {
NOR(s5, xZR, s1);
ORI(s3, s5, 1); // s3 = ~op1 | op2
ANDI(s5, s5, 1); // s5 = ~op1 & op2
}
IFXA (X_ALL, la64_lbt) {
X64_DEC_H(s1);
}
ADDI_W(s1, s1, -1);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) {
BSTRPICK_D(s1, s1, 15, 0);
return;
}
IFX (X_ALL) {
// preserving CF
MOV64x(s4, (1UL << F_AF) | (1UL << F_OF) | (1UL << F_ZF) | (1UL << F_SF) | (1UL << F_PF));
ANDN(xFlags, xFlags, s4);
}
IFX (X_AF | X_OF) {
AND(s3, s1, s3); // s3 = res & (~op1 | op2)
OR(s3, s3, s5); // cc = (res & (~op1 | op2)) | (~op1 & op2)
IFX (X_AF) {
ANDI(s2, s3, 0x08); // AF: cc & 0x08
BEQZ(s2, 8);
ORI(xFlags, xFlags, 1 << F_AF);
}
IFX (X_OF) {
SRLI_D(s3, s3, 14);
SRLI_D(s2, s3, 1);
XOR(s3, s3, s2);
ANDI(s3, s3, 1); // OF: xor of two MSB's of cc
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_OF);
}
}
SLLI_W(s1, s1, 16);
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
SRLI_W(s1, s1, 16);
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s2);
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
}
// emit DEC32 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_dec32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
{
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, rex.w ? d_dec64 : d_dec32);
} else IFX (X_ALL) {
SET_DFNONE();
}
IFXA (X_AF | X_OF, !la64_lbt) {
NOR(s5, xZR, s1);
ORI(s3, s5, 1); // s3 = ~op1 | op2
ANDI(s5, s5, 1); // s5 = ~op1 & op2
}
IFXA (X_ALL, la64_lbt) {
if (rex.w) {
X64_DEC_D(s1);
} else {
X64_DEC_W(s1);
}
}
ADDIxw(s1, s1, -1);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) {
if (!rex.w) ZEROUP(s1);
return;
}
IFX (X_ALL) {
// preserving CF
MOV64x(s4, (1UL << F_AF) | (1UL << F_OF) | (1UL << F_ZF) | (1UL << F_SF) | (1UL << F_PF));
ANDN(xFlags, xFlags, s4);
}
IFX (X_AF | X_OF) {
AND(s3, s1, s3); // s3 = res & (~op1 | op2)
OR(s3, s3, s5); // cc = (res & (~op1 | op2)) | (~op1 & op2)
IFX (X_AF) {
ANDI(s2, s3, 0x08); // AF: cc & 0x08
BEQZ(s2, 8);
ORI(xFlags, xFlags, 1 << F_AF);
}
IFX (X_OF) {
SRLI_D(s3, s3, rex.w ? 62 : 30);
SRLI_D(s2, s3, 1);
XOR(s3, s3, s2);
ANDI(s3, s3, 1); // OF: xor of two MSB's of cc
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_OF);
}
}
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s2);
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
}
// emit NEG16 instruction, from s1, store result in s1 using s2 and s3 as scratch
void emit_neg16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3)
{
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, d_neg16);
} else IFX (X_ALL) {
SET_DFNONE();
}
IFX (X_AF | X_OF) {
MV(s3, s1); // s3 = op1
}
NEG_D(s1, s1);
BSTRPICK_D(s1, s1, 15, 0);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
CLEAR_FLAGS(s3);
IFX (X_CF) {
BEQZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_CF);
}
IFX (X_AF | X_OF) {
OR(s3, s1, s3); // s3 = res | op1
IFX (X_AF) {
/* af = bc & 0x8 */
ANDI(s2, s3, 8);
BEQZ(s2, 8);
ORI(xFlags, xFlags, 1 << F_AF);
}
IFX (X_OF) {
/* of = ((bc >> (width-2)) ^ (bc >> (width-1))) & 0x1; */
SRLI_D(s2, s3, 14);
SRLI_D(s3, s2, 1);
XOR(s2, s2, s3);
ANDI(s2, s2, 1);
BEQZ(s2, 8);
ORI(xFlags, xFlags, 1 << F_OF);
}
}
IFX (X_SF) {
SRLI_D(s3, s1, 15 - F_SF); // put sign bit in place
ANDI(s3, s3, 1 << F_SF); // 1<<F_SF is sign bit, so just mask
OR(xFlags, xFlags, s3);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s2);
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFXA (X_ALL, la64_lbt) {
SPILL_EFLAGS();
}
}
+293 -27
View File
@@ -20,7 +20,7 @@
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_functions.h"
#include "dynarec_la64_helper.h"
#include "../dynarec_helper.h"
// emit SHL16 instruction, from s1 , shift s2, store result in s1 using s3, s4 and s5 as scratch
void emit_shl16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
@@ -514,7 +514,7 @@ void emit_sar16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
IFX (X_PEND) {
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, d_sar8);
SET_DF(s4, d_sar16);
} else IFX (X_ALL) {
SET_DFNONE();
}
@@ -612,6 +612,8 @@ void emit_sar32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
}
OR(xFlags, xFlags, s3);
}
// For the SAR instruction, the OF flag is cleared for all 1-bit shifts.
// OF nop
if (rex.w) {
SRAI_D(s1, s1, c);
@@ -659,13 +661,11 @@ void emit_ror32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
return;
}
if (la64_lbt) {
IFX (X_ALL) {
if (rex.w)
X64_ROTRI_D(s1, c);
else
X64_ROTRI_W(s1, c);
}
IFXA ((X_CF | X_OF), la64_lbt) {
if (rex.w)
X64_ROTRI_D(s1, c);
else
X64_ROTRI_W(s1, c);
}
ROTRIxw(s1, s1, c);
@@ -676,7 +676,10 @@ void emit_ror32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
if (la64_lbt) return;
CLEAR_FLAGS(s3);
IFX (X_CF | X_OF) {
MOV64x(s4, ((1UL << F_CF) | (1UL << F_OF)));
ANDN(xFlags, xFlags, s4);
}
IFX (X_CF) {
SRLIxw(s3, s1, rex.w ? 63 : 31);
OR(xFlags, xFlags, s3);
@@ -706,23 +709,18 @@ void emit_rol32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
SET_DFNONE();
}
if (la64_lbt) {
IFX (X_ALL) {
if (rex.w)
X64_ROTL_D(s1, s2);
else
X64_ROTL_W(s1, s2);
}
IFXA ((X_CF | X_OF), la64_lbt) {
if (rex.w)
X64_ROTL_D(s1, s2);
else
X64_ROTL_W(s1, s2);
}
if (rex.w) {
ANDI(s4, s2, 0x3f);
} else {
ANDI(s4, s2, 0x1f);
}
if (!rex.w) ZEROUP(s1);
BEQ_NEXT(s2, xZR);
SLLxw(s3, s1, s4);
NEG_D(s4, s4);
SLLxw(s3, s1, s2);
NEG_D(s4, s2);
ADDI_D(s4, s4, rex.w ? 64 : 32);
SRLxw(s1, s1, s4);
OR(s1, s3, s1);
@@ -733,18 +731,286 @@ void emit_rol32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
if (la64_lbt) return;
CLEAR_FLAGS(s3);
IFX (X_CF | X_OF) {
MOV64x(s4, ((1UL << F_CF) | (1UL << F_OF)));
ANDN(xFlags, xFlags, s4);
}
IFX (X_CF | X_OF) {
ANDI(s4, s1, 1); // LSB == F_CF
IFX (X_CF) OR(xFlags, xFlags, s4);
}
IFX (X_OF) {
// the OF flag is set to the exclusive OR of the CF bit (after the rotate) and the most-significant bit of the result.
ADDI_D(s3, xZR, 1);
BNE_NEXT(s2, s3);
ADDI_D(s3, s2, -1);
BNEZ_MARK(s3);
SRLIxw(s3, s1, rex.w ? 63 : 31);
XOR(s3, s3, s4); // s3: MSB, s4: CF bit
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
MARK;
}
}
// emit ROR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_ror32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
int64_t j64;
if (!rex.w) {
ZEROUP(s1);
}
BEQ_NEXT(s2, xZR);
IFX (X_PEND) {
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w ? d_ror64 : d_ror32);
} else IFX (X_ALL) {
SET_DFNONE();
}
IFXA ((X_CF | X_OF), la64_lbt) {
if (rex.w)
X64_ROTR_D(s1, s2);
else
X64_ROTR_W(s1, s2);
}
if (rex.w) {
ROTR_D(s1, s1, s2);
} else {
ROTR_W(s1, s1, s2);
}
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) return;
IFX (X_CF | X_OF) {
MOV64x(s4, ((1UL << F_CF) | (1UL << F_OF)));
ANDN(xFlags, xFlags, s4);
}
IFX (X_CF) {
SRLIxw(s3, s1, rex.w ? 63 : 31);
OR(xFlags, xFlags, s3);
}
IFX (X_OF) {
// the OF flag is set to the exclusive OR of the two most-significant bits of the result
ADDI_D(s3, s2, -1);
BNEZ_MARK(s3);
SRLIxw(s3, s1, rex.w ? 63 : 31);
SRLIxw(s4, s1, rex.w ? 62 : 30);
XOR(s3, s3, s4);
ANDI(s3, s3, 1);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
MARK;
}
}
// emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rol32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
{
if (!c) return;
IFX (X_PEND) {
MOV32w(s3, c);
SDxw(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w ? d_rol64 : d_rol32);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (!c) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
IFXA ((X_CF | X_OF), la64_lbt) {
if (rex.w)
X64_ROTLI_D(s1, c);
else
X64_ROTLI_W(s1, c);
}
ROTRIxw(s1, s1, (rex.w ? 64 : 32) - c);
if (!rex.w) ZEROUP(s1);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) return;
IFX (X_CF | X_OF) {
MOV64x(s3, ((1UL << F_CF) | (1UL << F_OF)));
ANDN(xFlags, xFlags, s3);
}
IFX (X_CF | X_OF) {
ANDI(s4, s1, 1 << F_CF);
IFX (X_CF) OR(xFlags, xFlags, s4);
}
IFX (X_OF) {
// the OF flag is set to the exclusive OR of the CF bit (after the rotate) and the most-significant bit of the result.
if (c == 1) {
SRLIxw(s3, s1, rex.w ? 63 : 31);
XOR(s3, s3, s4);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
}
}
void emit_shld32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4)
{
c &= (rex.w ? 0x3f : 0x1f);
IFX (X_PEND) {
if (c) {
MOV64x(s3, c);
SDxw(s3, xEmu, offsetof(x64emu_t, op2));
} else
SDxw(xZR, xEmu, offsetof(x64emu_t, op2));
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, rex.w ? d_shld64 : d_shld32);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (!c) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX (X_CF) {
if (c > 0) {
SRLI_D(s3, s1, (rex.w ? 64 : 32) - c);
ANDI(s4, s3, 1); // F_CF
OR(xFlags, xFlags, s4);
}
}
IFX (X_OF) {
// Store sign for later use.
if (c == 1) SRLIxw(s4, s1, rex.w ? 63 : 31);
}
SLLIxw(s3, s1, c);
SRLIxw(s1, s2, (rex.w ? 64 : 32) - c);
OR(s1, s1, s3);
if (!rex.w) {
ZEROUP(s1);
}
IFX (X_SF) {
SRLIxw(s3, s1, rex.w ? 63 : 31);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_OF) {
// the OF flag is set if a sign change occurred
if (c == 1) {
SRLIxw(s3, s1, rex.w ? 63 : 31);
XOR(s3, s3, s4);
SLLI_D(s3, s3, F_OF);
ORI(xFlags, xFlags, s3);
}
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
IFXA (X_ALL, la64_lbt) {
SPILL_EFLAGS();
}
}
// emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shrd32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4)
{
c &= (rex.w ? 0x3f : 0x1f);
IFX (X_PEND) {
if (c) {
MOV64x(s3, c);
SDxw(s3, xEmu, offsetof(x64emu_t, op2));
} else
SDxw(xZR, xEmu, offsetof(x64emu_t, op2));
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, rex.w ? d_shrd64 : d_shrd32);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (!c) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX (X_CF) {
if (c > 1) {
SRAI_D(s3, s1, c - 1);
ANDI(s3, s3, 1); // LSB == F_CF
} else {
ANDI(s3, s1, 1); // LSB == F_CF
}
OR(xFlags, xFlags, s3);
}
IFX (X_OF) {
// Store sign for later use.
if (c == 1) SRLIxw(s4, s1, rex.w ? 63 : 31);
}
SRLIxw(s3, s1, c);
SLLIxw(s1, s2, (rex.w ? 64 : 32) - c);
OR(s1, s1, s3);
if (!rex.w) {
ZEROUP(s1);
}
IFX (X_SF) {
SRLIxw(s3, s1, rex.w ? 63 : 31);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_OF) {
// the OF flag is set if a sign change occurred
if (c == 1) {
SRLI_D(s3, s1, rex.w ? 63 : 31);
XOR(s3, s3, s4);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
IFXA (X_ALL, la64_lbt) {
SPILL_EFLAGS();
}
}
+1 -1
View File
@@ -19,7 +19,7 @@
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_functions.h"
#include "dynarec_la64_helper.h"
#include "../dynarec_helper.h"
// emit CMP8 instruction, from cmp s1, s2, using s3, s4, s5 and s6 as scratch
+363 -7
View File
@@ -19,7 +19,7 @@
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_la64_functions.h"
@@ -60,7 +60,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETGD;
SMDMB();
if ((nextop & 0xC0) == 0xC0) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_add32(dyn, ninst, rex, ed, gd, x3, x4, x5);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
@@ -75,9 +75,103 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
SMDMB();
break;
case 0x09:
INST_NAME("LOCK OR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
SMDMB();
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_or32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LLxw(x1, wback, 0);
OR(x4, x1, gd);
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
IFX (X_ALL | X_PEND)
emit_or32(dyn, ninst, rex, x1, gd, x3, x4);
}
SMDMB();
break;
case 0x0F:
nextop = F8;
switch (nextop) {
case 0xB0:
switch (rep) {
case 0:
INST_NAME("LOCK CMPXCHG Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
ANDI(x6, xRAX, 0xff); // AL
SMDMB();
if (MODREG) {
if (rex.rex) {
wback = TO_NAT((nextop & 7) + (rex.b << 3));
wb2 = 0;
} else {
wback = (nextop & 7);
wb2 = (wback >> 2) * 8;
wback = TO_NAT(wback & 3);
}
BSTRPICK_D(x2, wback, wb2 + 7, wb2);
wb1 = 0;
ed = x2;
UFLAG_IF {
emit_cmp8(dyn, ninst, x6, ed, x3, x4, x5, x1);
}
BNE_MARK2(x6, x2);
BSTRPICK_D(wback, x2, wb2 + 7, wb2);
GETGB(x1);
MV(ed, gd);
MARK2;
BSTRINS_D(xRAX, x2, 7, 0);
B_NEXT_nocond;
} else {
if (rex.rex) {
gb1 = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3));
gb2 = 0;
} else {
gd = (nextop & 0x38) >> 3;
gb2 = ((gd & 4) >> 2) * 8;
gb1 = TO_NAT(gd & 3);
}
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x2, &fixedaddress, rex, LOCK_LOCK, 0, 0);
ANDI(x5, wback, 0b11);
SLLI_D(x5, x5, 3); // shamt
MARKLOCK;
ADDI_D(x7, xZR, ~0b11);
AND(x7, wback, x7); // align to 32bit
LD_WU(x1, x7, 0);
LL_W(x4, x7, 0);
SRL_D(x4, x4, x5);
ANDI(x4, x4, 0xff);
BNE_MARK(x6, x4); // compare AL with m8
// AL == m8, r8 is loaded into m8
ADDI_D(x2, xZR, 0xff);
SLL_D(x2, x2, x5);
NOR(x2, x2, xZR);
AND(x2, x1, x2);
BSTRPICK_D(x1, gb1, gb2 + 7, gb2);
SLL_D(x1, x1, x5);
OR(x1, x1, x2);
SC_W(x1, x7, 0);
BEQZ_MARKLOCK(x1);
// done
MARK;
UFLAG_IF { emit_cmp8(dyn, ninst, x6, x4, x1, x2, x3, x5); }
// load m8 into AL
ANDI(xRAX, xRAX, ~0xff);
OR(xRAX, xRAX, x4);
}
SMDMB();
break;
default:
DEFAULT;
}
break;
case 0xB1:
switch (rep) {
case 0:
@@ -86,7 +180,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
UFLAG_IF { emit_cmp32(dyn, ninst, rex, xRAX, ed, x3, x4, x5, x6); }
MV(x1, ed); // save value
@@ -98,6 +192,9 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
ANDI(x1, wback, (1 << (rex.w + 2)) - 1);
BNEZ_MARK3(x1);
// Aligned
MARKLOCK;
MV(x4, gd);
LLxw(x1, wback, 0);
@@ -106,6 +203,20 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
// EAX == Ed
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
B_MARK_nocond;
MARK3;
// Unaligned
ADDI_D(x5, xZR, -(1 << (rex.w + 2)));
AND(x5, x5, wback);
MARK2;
LDxw(x1, wback, 0);
LLxw(x6, x5, 0);
SUBxw(x3, x1, xRAX);
BNEZ_MARK(x3);
// EAX == Ed
SCxw(x6, x5, 0);
BEQZ_MARK2(x6);
SDxw(gd, wback, 0);
MARK;
UFLAG_IF { emit_cmp32(dyn, ninst, rex, xRAX, x1, x3, x4, x5, x6); }
MVxw(xRAX, x1);
@@ -125,7 +236,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETGD;
SMDMB();
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MVxw(x1, ed);
MVxw(ed, gd);
MVxw(gd, x1);
@@ -149,10 +260,173 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
DEFAULT;
}
break;
case 0xC7:
// rep has no impact here
nextop = F8;
switch ((nextop >> 3) & 7) {
case 1:
if (rex.w) {
INST_NAME("LOCK CMPXCHG16B Gq, Eq");
if (!la64_scq) {
static int warned = 0;
PASS3(if (!warned) dynarec_log(LOG_INFO, "Warning, LOCK CMPXCHG16B is not well supported on LoongArch without SCQ and issues are expected.\n"));
warned = 1;
}
} else {
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
}
SETFLAGS(X_ZF, SF_SUBSET);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, LOCK_LOCK, 0, 0);
UFLAG_IF {
if (la64_lbt) {
X64_SET_EFLAGS(xZR, X_ZF);
} else {
ADDI_D(x2, xZR, ~(1 << F_ZF));
AND(xFlags, xFlags, x2);
}
}
if (rex.w) {
if (la64_scq) {
MARKLOCK;
LL_D(x2, wback, 0);
LD_D(x3, wback, 8);
// compare RDX:RAX with x3:x2
BNE_MARK(x2, xRAX);
BNE_MARK(x3, xRDX);
MV(x5, xRBX);
SC_Q(x5, xRCX, wback);
BEQZ_MARKLOCK(x5);
UFLAG_IF {
if (la64_lbt) {
ADDI_D(x5, xZR, -1);
X64_SET_EFLAGS(x5, X_ZF);
} else {
ORI(xFlags, xFlags, 1 << F_ZF);
}
}
B_MARK3_nocond;
MARK;
MV(xRAX, x2);
MV(xRDX, x3);
MARK3;
SMDMB();
} else {
// if scq extension is not available, implement it with mutex
LD_D(x6, xEmu, offsetof(x64emu_t, context));
ADDI_D(x6, x6, offsetof(box64context_t, mutex_16b));
ADDI_D(x4, xZR, 1);
MARKLOCK;
AMSWAP_DB_W(x5, x4, x6);
// x4 == 1 if locked
BNEZ_MARKLOCK(x5);
LD_D(x2, wback, 0);
LD_D(x3, wback, 8);
BNE_MARK(x2, xRAX);
BNE_MARK(x3, xRDX);
ST_D(xRBX, wback, 0);
ST_D(xRCX, wback, 8);
UFLAG_IF {
if (la64_lbt) {
ADDI_D(x5, xZR, -1);
X64_SET_EFLAGS(x5, X_ZF);
} else {
ORI(xFlags, xFlags, 1 << F_ZF);
}
}
B_MARK3_nocond;
MARK;
MV(xRAX, x2);
MV(xRDX, x3);
MARK3;
// unlock
AMSWAP_DB_W(xZR, xZR, x6);
}
} else {
SMDMB();
BSTRINS_D(x3, xRAX, 31, 0);
BSTRINS_D(x3, xRDX, 63, 32);
BSTRINS_D(x4, xRBX, 31, 0);
BSTRINS_D(x4, xRCX, 63, 32);
ANDI(x2, wback, 7);
BNEZ_MARK2(x2);
// Aligned
MARKLOCK;
LL_D(x2, wback, 0);
BNE_MARK(x2, x3); // EDX_EAX != Ed
MV(x5, x4);
SC_D(x5, wback, 0);
BEQZ_MARKLOCK(x5);
UFLAG_IF {
if (la64_lbt) {
ADDI_D(x5, xZR, -1);
X64_SET_EFLAGS(x5, X_ZF);
} else {
ORI(xFlags, xFlags, 1 << F_ZF);
}
}
B_MARK3_nocond;
MARK2;
// Unaligned
ADDI_W(x5, xZR, 0xFF8);
AND(x5, wback, x5);
MARKLOCK2;
LD_D(x2, wback, 0);
LL_D(x6, x5, 0);
BNE_MARK(x2, x3); // EDX_EAX != Ed
SC_D(x6, x5, 0);
BEQZ_MARKLOCK2(x6);
ST_D(x4, wback, 0);
UFLAG_IF {
if (la64_lbt) {
ADDI_D(x5, xZR, -1);
X64_SET_EFLAGS(x5, X_ZF);
} else {
ORI(xFlags, xFlags, 1 << F_ZF);
}
}
B_MARK3_nocond;
MARK;
SLLI_D(xRDX, x2, 32);
ZEROUP2(xRAX, x2);
MARK3;
SMDMB();
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
break;
case 0x11:
INST_NAME("LOCK ADC Ed, Gd");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
SMDMB();
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_adc32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LLxw(x1, wback, 0);
ADDxw(x3, x1, gd);
ANDI(x4, xFlags, 1 << F_CF);
ADDxw(x3, x3, x4);
SCxw(x3, wback, 0);
BEQZ_MARKLOCK(x3);
IFX (X_ALL | X_PEND) {
emit_adc32(dyn, ninst, rex, x1, gd, x3, x4, x5, x6);
}
}
SMDMB();
break;
case 0x29:
INST_NAME("LOCK SUB Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -160,7 +434,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETGD;
SMDMB();
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_sub32(dyn, ninst, rex, ed, gd, x3, x4, x5);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
@@ -191,7 +465,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
i64 = F32S;
else
i64 = F8S;
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode == 0x81) ? 4 : 1);
@@ -217,6 +491,44 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SMDMB();
}
break;
case 1: // OR
if (opcode == 0x81) {
INST_NAME("LOCK OR Ed, Id");
} else {
INST_NAME("LOCK OR Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
if (MODREG) {
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81) {
i64 = F32S;
} else {
i64 = F8S;
}
if (i64 <= -2048 || i64 > 2048) {
MOV64xw(x3, i64);
}
MARKLOCK;
LLxw(x1, wback, 0);
if (i64 >= -2048 && i64 < 2048) {
ORI(x4, x1, i64);
} else {
OR(x4, x1, x3);
}
if (!rex.w) ZEROUP(x4);
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
IFX (X_ALL | X_PEND)
emit_or32c(dyn, ninst, rex, x1, i64, x3, x4);
}
break;
case 5: // SUB
if (opcode == 0x81) {
INST_NAME("LOCK SUB Ed, Id");
@@ -229,7 +541,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
i64 = F32S;
else
i64 = F8S;
ed = xRAX + (nextop & 7) + (rex.b << 3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode == 0x81) ? 4 : 1);
@@ -279,6 +591,50 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SMDMB();
}
break;
case 0xFF:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("LOCK INC Ed");
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING);
SMDMB();
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_inc32(dyn, ninst, rex, ed, x3, x4, x5, x6);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LLxw(x1, wback, 0);
ADDIxw(x4, x1, 1);
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
IFX (X_ALL | X_PEND)
emit_inc32(dyn, ninst, rex, x1, x3, x4, x5, x6);
}
break;
case 1:
INST_NAME("LOCK DEC Ed");
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING);
SMDMB();
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_dec32(dyn, ninst, rex, ed, x3, x4, x5, x6);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LLxw(x1, wback, 0);
ADDIxw(x4, x1, -1);
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
IFX (X_ALL | X_PEND)
emit_dec32(dyn, ninst, rex, x1, x3, x4, x5, x6);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
Loaded 100 of 1605 files, more files were not shown because too many files have changed in this diff. Show more