Compare commits

...
342 Commits
Author SHA1 Message Date
ptitSeb 17bc603077 Bumped to v0.0.6 2021-03-24 19:11:58 +01:00
ptitSeb 7af9158baa Added COMPILE and USAGE docs 2021-03-24 18:51:25 +01:00
ptitSeb 571a041c25 Updated Logo and Icon with newer version from @grayduck 2021-03-24 18:14:26 +01:00
ptitSeb 0a02340e35 [DYNAREC] Added 66 0F 12/13 opcodes 2021-03-24 16:58:26 +01:00
ptitSeb 12ee624358 [DYNAREC] Added 0F BA opcode 2021-03-24 16:49:27 +01:00
ptitSeb 571de7f07f [DYNAREC] Added F2 0F 2D opcodes, and use a simpler version of the conversions (but complex one is still available under a define in dynarec_arm64_helper.h) 2021-03-24 16:00:17 +01:00
ptitSeb b055c2be65 [DYNAREC] Refined 66 0F 5B with a switch for the rounding mode 2021-03-24 15:33:52 +01:00
ptitSeb 78750b96e5 [DYNAREC] Added 64 83 opcodes 2021-03-24 14:58:28 +01:00
ptitSeb ce51207e44 [DYNAREC] Added 64 89 opcodes 2021-03-24 14:52:27 +01:00
ptitSeb a3dcaf4284 [DYNAREC] Added F2 0F 5D/5F opcodes 2021-03-24 14:49:31 +01:00
ptitSeb 181274636e [DYNAREC] Added 66 0F DF opcode 2021-03-24 14:44:06 +01:00
ptitSeb c4198554ad [DYNAREC] Added 66 0F F8..FE opcodes 2021-03-24 14:42:20 +01:00
ptitSeb ed45a8d666 [DYNAREC] Added 66 0F DB opcode 2021-03-24 14:39:49 +01:00
ptitSeb 5a8b5c8af4 [DYNAREC] Added 64 C7 opcode 2021-03-24 14:37:51 +01:00
ptitSeb 1e3c599b4e [DYNAREC] Added 66 0F F4 opcode 2021-03-24 14:33:08 +01:00
ptitSeb 41ca58a403 [DYNAREC] Added 66 0F 64..66 opcodes 2021-03-24 14:03:27 +01:00
ptitSeb e09b18d3fb [DYNAREC] Added 66 0F EB opcode 2021-03-24 13:45:31 +01:00
ptitSeb 4b7958f447 [DYNAREC] Added 66 0F 7F opcode 2021-03-24 12:41:15 +01:00
ptitSeb b0b11572d7 [DYNAREC] Added 66 0F 6B 2021-03-24 12:38:18 +01:00
ptitSeb c1684db78a [DYNAREC] Added 66 0F 5B opcode 2021-03-24 12:19:06 +01:00
ptitSeb fdbdc615da [DYNAREC] Added 0F C8..CF opcodes 2021-03-24 12:07:29 +01:00
ptitSeb 5354a134fc [DYNAREC] Added 0F 12/13 opcodes 2021-03-24 11:56:07 +01:00
ptitSeb 800d3fd109 Back ported simplified pthread_once callback handling from box86 2021-03-24 11:47:53 +01:00
ptitSeb b7f8a1eb8b [DYNAREC] Fixed 0F 10 opcode 2021-03-24 11:47:31 +01:00
ptitSeb dbeea3b8a1 [DYNAREC] Added 0F 5C opcode 2021-03-23 22:49:02 +01:00
ptitSeb 888705c7dc [DYNAREC] Added 66 A9 opcode 2021-03-23 22:48:37 +01:00
ptitSeb d9e649c023 Added remove wrapped function to libc 2021-03-23 22:48:15 +01:00
ptitSeb 14da2a9a67 Added a few more libc wrapped functions 2021-03-23 22:42:08 +01:00
ptitSeb d7e712f48b Fixed mbsrtowcs function signature 2021-03-23 22:29:11 +01:00
ptitSeb 0f9b48d446 [DYNAREC] Fixed TRN_gen emitter 2021-03-23 22:21:33 +01:00
ptitSeb 6e90c47e74 [DYNAREC] Fixed 66 F2/F2 A5 opcode 2021-03-23 22:12:28 +01:00
ptitSeb 365d2b0eb2 Update Logo and Icon with a redish version, to more clearly separate with box86 2021-03-23 22:11:37 +01:00
ptitSeb 3642119665 [DYNAREC] Added F2 0F 7C opcode 2021-03-23 21:54:54 +01:00
ptitSeb 705cb79819 [DYNAREC] Added F3 0F 12/16 opcodes 2021-03-23 21:30:05 +01:00
ptitSeb d8e5c5372a Added a few more wrapped functions to libc 2021-03-23 21:17:57 +01:00
ptitSeb 714ccbc321 [DYNAREC] Fixed FMOD_register emitter 2021-03-23 21:06:37 +01:00
ptitSeb 0917fbe0c4 [DYNAREC] Added 66 (F2/F3) A5 opcode 2021-03-23 20:43:59 +01:00
ptitSeb 1517177668 [DYNAREC] Added 66 0F 71/72 opcodes 2021-03-23 20:27:14 +01:00
ptitSeb 2487fb4d98 [DYNAREC] Added 0F 58/59 opcodes, plus lots of small bugfix (IntoTheBreach sounds good now) 2021-03-23 20:12:11 +01:00
ptitSeb de0718811e [DYNAREC] Added 0F 5B opcode 2021-03-23 17:58:31 +01:00
ptitSeb 12b9b1a6e9 [DYNAREC] Added F0 00/01 opcodes 2021-03-23 17:48:00 +01:00
ptitSeb 1f819c4924 [DYNAREC] Added 66 0F 60/61/62 opcodes 2021-03-23 17:41:35 +01:00
ptitSeb 1d209596a3 [DYNAREC] Added 66 0F D4 opcode 2021-03-23 17:34:32 +01:00
ptitSeb b1d5e27564 [DYNAREC] Added (F2/F3) A4 opcode 2021-03-23 17:26:59 +01:00
ptitSeb 732f2f106b [DYNAREC] Added 0F 16/17 opcodes 2021-03-23 17:21:13 +01:00
ptitSeb db6319b90f [DYNAREC] Added 0F C6 opcode 2021-03-23 17:01:59 +01:00
ptitSeb 601eb63c9a [DYNAREC] Small optim on 66 0F 5A opcode 2021-03-23 16:45:59 +01:00
ptitSeb d237d5e807 [DYNAREC] Added 66 C1 opcodes 2021-03-23 16:44:01 +01:00
ptitSeb da47d34705 [DYNAREC] Added 0F AE opcode 2021-03-23 16:37:23 +01:00
ptitSeb ce5a5bf356 [DYNAREC] Added F2 0F 2C opcode 2021-03-23 16:23:26 +01:00
ptitSeb c754cb75b6 [DYNAREC] Added F2 0F 2A opcode 2021-03-23 16:13:32 +01:00
ptitSeb f084966fd3 [DYNAREC] Added 66 0F 6C opcode 2021-03-23 14:46:56 +01:00
ptitSeb 79dd8c29ae [DYNAREC] Added 66 C7 opcode 2021-03-23 14:42:50 +01:00
ptitSeb a260dff197 [DYNAREC] Added C9 opcode 2021-03-23 14:37:57 +01:00
ptitSeb f83179c665 [DYNAREC] Fixed 66 0F 73 opcodes 2021-03-23 14:33:30 +01:00
ptitSeb 31508f673c [DYNAREC] Added 66 0F 68/69/6A opcodes 2021-03-23 14:19:41 +01:00
ptitSeb a1f87da9f5 [DYNAREC] Added F3 0F 6F opcode 2021-03-23 14:10:04 +01:00
ptitSeb eb102f8a82 [DYNAREC] Added 66 0F 73 opcodes 2021-03-23 14:07:06 +01:00
ptitSeb e1a2439fbf [DYNAREC] Added 66 0F 70 opcode (tricky one) 2021-03-23 13:31:10 +01:00
ptitSeb 9fb2cb86ed [DYNAREC] Added 66 0F BE opcode 2021-03-23 12:25:54 +01:00
ptitSeb f6b646ef67 [DYNAREC] Added 66 85 opcode 2021-03-23 11:43:06 +01:00
ptitSeb 068025d919 [DYNAREC] Added FC/FD opcodes 2021-03-23 11:40:50 +01:00
ptitSeb f88f59926e [DYNAREC] Added F3 0F 5D opcode 2021-03-23 11:30:48 +01:00
ptitSeb c9d593fa17 [DYNAREC] Added F0 83 opcodes 2021-03-23 11:25:02 +01:00
ptitSeb ed452e81ae [DYNAREC] Improved CMPLESS accuracy 2021-03-23 11:03:55 +01:00
ptitSeb 604da55f08 [DYNAREC] Added F3 0F 5F opcode 2021-03-23 10:39:51 +01:00
ptitSeb 57a5d517c8 [DYNAREC] Added 66 B8..BF opcodes 2021-03-23 10:03:57 +01:00
ptitSeb 2b6fa580df [DYNAREC] Added F3 0F C2 opcode 2021-03-23 10:00:29 +01:00
ptitSeb 7f750e7ac1 [DYNAREC] Added (F2/F3) AA/AB opcodes 2021-03-23 09:43:36 +01:00
ptitSeb b9779c2184 [DYNAREC] Optimized F2/F3 A5 opcode 2021-03-23 09:35:21 +01:00
ptitSeb e52c207c75 [DYNAREC] Optimized F2/F3 AE/A6 opcodes 2021-03-23 09:29:50 +01:00
ptitSeb bfdcb023b3 Added Box64 Logo and Icon from @grayduck, and added some test to README 2021-03-23 07:45:35 +01:00
ptitSeb dce3292fc7 [DYNAREC] Added 0F BE/BF ocpodes, and fixed LDRSB emitter 2021-03-22 22:55:49 +01:00
ptitSeb 98a567e102 [DYNAREC] Fixed F2/F3 AE opcode and factorized F2/F3 A6/AE opcodes 2021-03-22 22:04:28 +01:00
ptitSeb d6123a87c5 [DYNAREC] More printers 2021-03-22 22:03:41 +01:00
ptitSeb f94ceccc8a [DYNAREC] Added (F2/F3) AE opcode 2021-03-22 21:16:42 +01:00
ptitSeb cc97914ed8 [DYNAREC] Added 66 0F 54/55/56/57 opcodes 2021-03-22 21:02:45 +01:00
ptitSeb 829be9e506 [DYNAREC] Added F0 0F C1 opcode 2021-03-22 21:00:03 +01:00
ptitSeb bea68ddbfa [DYNAREC] Added 66 0F 5A opcodes 2021-03-22 20:52:04 +01:00
ptitSeb fa039a1320 [DYNAREC] Added 66 0F 14/15 opcodes 2021-03-22 20:44:57 +01:00
ptitSeb cdaf19899e [DYNAREC] ARMv8 NEON doesn't require alignment 2021-03-22 20:09:39 +01:00
ptitSeb b5847d83cb [DYNAREC] Added 0F 5A opcode 2021-03-22 19:26:00 +01:00
ptitSeb 685cc7b0ba [DYNAREC] Added 0F 14/15 opcodes 2021-03-22 18:43:09 +01:00
ptitSeb b14be7f614 [DYNAREC] Added (F2/F3) A6 opcode 2021-03-22 18:27:03 +01:00
ptitSeb 35f8500acd [DYNAREC] Switched all other lock mecnism to LDAXR/STLXR 2021-03-22 17:54:43 +01:00
ptitSeb cb0cceb9ae [DYNAREC] Small option on REP MOVSD, and go back to LDAXR/STLXR for xchg (IntoTheBreach seems to prefer) 2021-03-22 17:51:04 +01:00
ptitSeb 1405d83a56 [DYNAREC] Various bugfixes 2021-03-22 17:35:38 +01:00
ptitSeb 0878acf04c [DYNAREC] Added (F2/F3) A5 opcode 2021-03-22 16:44:11 +01:00
ptitSeb 735d9c107d [DYNAREC] Added F2 0F 5A opcode 2021-03-22 16:14:59 +01:00
ptitSeb daf148c4d6 [DYNAREC] Added 0F 54 opcode 2021-03-22 16:03:15 +01:00
ptitSeb 922fa046bb [DYNAREC] Added 0F 55 opcode 2021-03-22 16:01:32 +01:00
ptitSeb b247fd04df [DYNAREC] Added 0F 56 opcode 2021-03-22 16:00:25 +01:00
ptitSeb 0b53a98648 [DYNAREC] Fixed and simplified F0 B1 opcdes, plus some other various small improvments (IntoTheBreach still unstable, the other 3 works fine) 2021-03-22 15:42:23 +01:00
ptitSeb f76fa67303 [DYNAREC] Fixed 66 3D opcode 2021-03-22 14:54:08 +01:00
ptitSeb e6d3812d6c [DYNAREC] Added C0 opcode 2021-03-22 14:21:51 +01:00
ptitSeb c02946a913 [DYNAREC] Added 66 83 opcode 2021-03-22 14:14:31 +01:00
ptitSeb 8ec2851439 [DYNAREC] Added 66 0F 6F opcode 2021-03-22 14:08:03 +01:00
ptitSeb f2c68385ab [DYNAREC] Fixed a bug in 0F 11 opcode 2021-03-22 14:07:47 +01:00
ptitSeb f428001f42 [DYNAREC] Added F3 0F 2C opcode 2021-03-22 14:00:04 +01:00
ptitSeb 83104b32b8 [DYNAREC] Added 98/99 opcodes 2021-03-22 13:55:00 +01:00
ptitSeb 1a12bd7269 [DYNAREC] Added A8/A9 opcodes 2021-03-22 13:28:24 +01:00
ptitSeb 04aa1af72e [DYNAREC] Added 64 8B opcodes, plus some fixes to FS access 2021-03-22 12:40:07 +01:00
ptitSeb 466a8cb107 [DYNAREC] Added 66 89/8B opcodes 2021-03-22 12:16:23 +01:00
ptitSeb 23c9d574d9 [DYNAREC] Added 64 31 opcode 2021-03-22 12:12:19 +01:00
ptitSeb 5cc73fdf40 [DYNAREC] Added F0 B1 opcode (and change LDAXR/STLXR to LDXR/STXR for eXclusive access) 2021-03-22 11:53:56 +01:00
ptitSeb 3cfd4c8ec2 [DYNAREC] Added 87 XCHG opcode 2021-03-22 09:45:59 +01:00
ptitSeb 9eb6d49616 [DYNAREC] Added B0..B7 opcodes, plus potential fix for 8D LEA on 32bits modes 2021-03-21 22:21:07 +01:00
ptitSeb 8bd81dffcf [DYNAREC] Complete 81/833 opcodes, plus various bugfixes 2021-03-21 22:08:58 +01:00
ptitSeb 79ca411d6a [DYNAREC] Added 0F 57 opcode 2021-03-21 20:48:14 +01:00
ptitSeb 9cdf1f9711 [DYNAREC] Added 66 0F D6 opcode 2021-03-21 20:37:54 +01:00
ptitSeb c8b6834a5e [DYNAREC] Added F3 0F 7E/7F opcodes 2021-03-21 20:37:25 +01:00
ptitSeb e15eb5a7f6 [DYNAREC] Optimized a bit Native call push/pop regs 2021-03-21 20:36:46 +01:00
ptitSeb 3d4acc3aef [DYNAREC] Foxed printer for STP/LDP 2021-03-21 20:35:49 +01:00
ptitSeb 1349601269 [DYNAREC] Added 88 opcode 2021-03-21 19:03:56 +01:00
ptitSeb 0751aed1f0 [DYNAREC] Small optim on MOVD type SSE opcodes 2021-03-21 18:56:50 +01:00
ptitSeb 4f2ed9ba62 [DYNAREC] Added 66 90 opcode 2021-03-21 18:48:16 +01:00
ptitSeb 707f41af39 [DYNAREC] Added F3 0F 10/11 opcodes 2021-03-21 18:17:43 +01:00
ptitSeb 3d400cf91b [DYNAREC] Fixed call_c helper with SSE args 2021-03-21 18:17:19 +01:00
ptitSeb a77093e154 [DYNAREC] Added 0F B6/B7 opcodes 2021-03-21 17:55:14 +01:00
ptitSeb 6676fe3b3b [DYNAREC] Added 0F 2E/2F opcodes 2021-03-21 17:41:08 +01:00
ptitSeb 1d85580fbc [DYNAREC] Added F3 0F 2A opcode 2021-03-21 17:29:59 +01:00
ptitSeb f01e987d31 [DYNAREC] Added C6 opcode 2021-03-21 16:12:03 +01:00
ptitSeb eb96a1c03a [DYNAREC] Added 63 opcode 2021-03-21 16:04:28 +01:00
ptitSeb e99387aa83 [DYNAREC] Added F3 0F 51/58/59/5C/5E opcodes 2021-03-21 15:57:07 +01:00
ptitSeb f8341bf934 [DYNAREC] Fixed Pop SSE Cache helper 2021-03-21 15:56:13 +01:00
ptitSeb 20ccf221a8 [DYNAREC] Added 84 TEST opcode 2021-03-21 15:36:09 +01:00
ptitSeb b98fe181e8 [DYNAREC] Added 0F 28/29 opcodes 2021-03-21 15:28:09 +01:00
ptitSeb 34eea95426 [DYNAREC] Fixed F2 0F opcodes (NEON reset high part of vector, SSE doesn't) 2021-03-21 15:27:45 +01:00
ptitSeb 5f470be79e [DYNAREC] Added 0F A2 CPUID opcode 2021-03-21 15:16:55 +01:00
ptitSeb 1c8683343b [DYNAREC] Added 66 0F 2E/2F opcodes 2021-03-21 15:09:35 +01:00
ptitSeb 56f37e8745 [DYNAREC] Added 66 0F EF opcode 2021-03-21 14:30:12 +01:00
ptitSeb 910a466fad [DYNAREC] Added F2 0F 51 opcode 2021-03-21 14:24:33 +01:00
ptitSeb d3a15b7ab6 [DYNAREC] Added F2 0F 5E opcode 2021-03-21 14:16:50 +01:00
ptitSeb cd8ee4c4b4 [DYNAREC] Added F2 0F 59 opcode 2021-03-21 14:11:57 +01:00
ptitSeb c253e4a48e [DYNAREC] Added F2 0F 5C opcode 2021-03-21 13:58:17 +01:00
ptitSeb 90bd5b0cb1 [DYNAREC] Added F2 0F 10/11 opcodes 2021-03-21 13:52:46 +01:00
ptitSeb fd729da8f1 [DYNAREC] Added F2 0F 58 opcode 2021-03-21 13:35:46 +01:00
ptitSeb 9bfc027b15 [DYNAREC] Added 66 0F 28/29 opcodes 2021-03-21 12:46:41 +01:00
ptitSeb cedd8e3670 [DYNAREC] Added 0F 10/11 opcodes 2021-03-21 12:02:18 +01:00
ptitSeb 3c31ecb115 [DYNAREC] Added 66 0F 6E/7E opcodes (firsts SSE one) 2021-03-21 11:03:08 +01:00
ptitSeb cc25976743 [DYNAREC] NEON infrastructure 2021-03-21 09:29:31 +01:00
ptitSeb 6fea5e5854 [DYNAREC] Optimized prolog/epilog/next with ldp/stp 2021-03-21 09:00:51 +01:00
ptitSeb bf6ac0d608 [DYNAREC] Added 67 E0..E3 opcodes 2021-03-21 08:47:04 +01:00
ptitSeb cb7c7ad913 [DYNAREC] Fixed 69 and 6B opcodes (and now IntoTheBreach runs again) 2021-03-20 23:33:28 +01:00
ptitSeb bd9cddf211 [DYNAREC] Fixed (again) test32 emitter 2021-03-20 23:07:47 +01:00
ptitSeb 3d33454564 [DYNAREC] Added 66 0F 40..4F CMOVcc opcodes 2021-03-20 22:51:52 +01:00
ptitSeb a70109be83 [DYNAREC] Added 6A PUSH opcode 2021-03-20 22:44:07 +01:00
ptitSeb 5ec0a88949 [DYNAREC] Added (66) 69/6B IMUL opcodes 2021-03-20 22:38:23 +01:00
ptitSeb 12de380799 [DYNAREC] Added (66) 0F AF IMUL opcode 2021-03-20 22:22:16 +01:00
ptitSeb 89a3c359a6 [DYNAREC] Added (66) 0F BC/BD opcodes 2021-03-20 21:54:51 +01:00
ptitSeb 848390d9eb [DYNAREC] Fixed and32 emitter and improved test32 emitter 2021-03-20 21:46:15 +01:00
ptitSeb 2f89043b35 [DYNAREC] Various bugfixes (and now the 4 tests games works again) 2021-03-20 21:11:49 +01:00
ptitSeb fcfd0d794b [DYNAREC] Added MOVN printer 2021-03-20 19:12:37 +01:00
ptitSeb dbd83a8b28 [DYNAREC] Fixed xor8 emitter, but ThimbleWeedPark is broken 2021-03-20 19:05:03 +01:00
ptitSeb 36d62235b3 [DYNAREC] Added 66 39/3B/3C CMP opcodes 2021-03-20 18:58:08 +01:00
ptitSeb 79c4c8bdd3 [DYNAREC] Added (66) 30..35 XOR opcodes 2021-03-20 18:47:50 +01:00
ptitSeb 6be2c376e2 [DYNAREC] Added (66) 28..2D SUB opcodes 2021-03-20 18:38:17 +01:00
ptitSeb db22d8b1c9 [DYNAREC] Added (66) 20..25 AND opcodes 2021-03-20 18:25:32 +01:00
ptitSeb e4fa7bc969 [DYNAREC] Added (66) 18..1D SBB opcodes 2021-03-20 18:13:18 +01:00
ptitSeb 98b0ac713d [DYNAREC] Added 66 11/13/15 ADC opcodes 2021-03-20 17:32:58 +01:00
ptitSeb 74eea34c6e [DYNAREC] Added 66 09/0B/0D OR opcodes 2021-03-20 17:25:50 +01:00
ptitSeb bbe817e3be [DYNAREC] Added 66 01..05 ADD opcodes 2021-03-20 17:19:21 +01:00
ptitSeb f53775ac39 [DYNAREC] Added 10..15 ADC opcodes 2021-03-20 17:04:51 +01:00
ptitSeb dfb1cd4876 Renamed arm64_lock_helper to arm64_lock 2021-03-20 16:49:02 +01:00
ptitSeb c2c34ccba3 [DYNAREC] Added 00/02/04 ADD and 08/0A/0C OR opcodes 2021-03-20 16:44:55 +01:00
ptitSeb c8d005af84 [DYNAREC] Added FE INC/DEC opcodes 2021-03-20 15:50:51 +01:00
ptitSeb 7c651088b5 [DYNAREC] Added 66 FF INC/DEC opcodes 2021-03-20 15:39:21 +01:00
ptitSeb 9a9d51440a [DYNAREC] Added F6 opcodes 2021-03-20 15:17:15 +01:00
ptitSeb 4b3e632d14 [DYNAREC] Added 66 F7 opcodes 2021-03-20 14:52:45 +01:00
ptitSeb b52b321969 [DYNAREC] Added F6 opcodes and fixed issue with native call that may destroy some registers 2021-03-20 12:45:22 +01:00
ptitSeb e5b36d2997 [DYNAREC] Added D0/D2 opcodes 2021-03-20 10:48:15 +01:00
ptitSeb cc2016bbc9 [DYNAREC] Added 66 D1/D3 opcodes 2021-03-20 10:34:00 +01:00
ptitSeb a68be9117b [DYNAREC] Added D3 opcodes, and fixed sl32/shl32c/shr32/shr32c emitter 2021-03-20 10:20:51 +01:00
ptitSeb f4fceb53bc [DYNAREC] Added ASR_REG printer 2021-03-20 09:51:03 +01:00
ptitSeb 495d566401 [DYNAREC] Small optim on MOV64xw / MOV64x / MOV32w macros 2021-03-20 09:50:44 +01:00
ptitSeb 7a056851d9 [DYNAREC] 0F A5 and 66 0F A4/A5 SHLD opcodes 2021-03-19 22:09:43 +01:00
ptitSeb 44eb9cf678 [DYNAREC] Added C7 MOV opcode 2021-03-19 21:47:48 +01:00
ptitSeb 597a56d0ff [DYNAREC] Added 0F AD and 66 0F AC/AD SHLD opcodes 2021-03-19 20:29:45 +01:00
ptitSeb 967132b04e [DYNAREC] Added 0F A3 and 66 0F A3 BT opcodes 2021-03-19 20:16:54 +01:00
ptitSeb 423795b49e [DYNAREC] Added 0F AB and 66 0F AB BTS opcodes 2021-03-19 20:13:52 +01:00
ptitSeb 27b7382be5 Added 0F B3 and 66 0F B3 BTR opcodes 2021-03-19 20:09:38 +01:00
ptitSeb 25d342f829 [DYNAREC] Added 66 0F BB opcode 2021-03-19 18:59:15 +01:00
ptitSeb f683404db9 [DYNAREC] Fixed 80/7 CMP opcode (and now, all 4 tests games works again) 2021-03-19 18:23:57 +01:00
ptitSeb d8c3c38d69 [DYNAREC] Added 38/3A/3C CMP opcodes, and fixed GETGB macro (still broken) 2021-03-19 17:37:22 +01:00
ptitSeb 0400bea3bd [DYNAREC] Added 0F 90..9F SETcc Eb opcode, and fixed GETEB macro (but WorldOfGoo still broken, didn't test the others 2021-03-19 17:15:28 +01:00
ptitSeb 10088c6566 [DYNAREC] Added 0F 80..8F Jcc Id opcodes (and factorised GOCOND macro) 2021-03-19 16:50:27 +01:00
ptitSeb a2abb4e8b1 [DYNAREC] Added 90 NOP 2021-03-19 16:19:40 +01:00
ptitSeb f1625c0d92 [DYNAREC] Added 68 PUSH Id and fixed 80/7 cmp (but ThimbleweedPark, IntoTheBreach and WorldOfGoo are still broken, vvvvv works) 2021-03-19 16:16:23 +01:00
ptitSeb 5c4b0baf8b [DYNAREC] 0F 40..4F CMOVcc opcodes 2021-03-19 10:13:00 +01:00
ptitSeb af1b5a9a51 [DYNAREC] Added 80 opcodes 2021-03-19 09:49:03 +01:00
ptitSeb f5a7e63936 [DYNAREC] Added 0F BB BTC opcode 2021-03-18 18:48:42 +01:00
ptitSeb 13da8f0d75 [DYNAREC] Fixed GETED delta computation (fixing IntoTheBreach and ThimbleweedPark) 2021-03-18 18:27:53 +01:00
ptitSeb adea4ceef2 [DYNAREC] Fixed PF flags computation 2021-03-18 17:35:39 +01:00
ptitSeb cc85f79322 [DYNAREC] Added more printer 2021-03-18 17:35:13 +01:00
ptitSeb c22782d2ab [DYNAREC] Added 9B/9C/9D FWAIT/PUSHF/POPF opcodes 2021-03-18 17:03:16 +01:00
ptitSeb 994a575d32 [DYNAREC] Added B8..BF opcodes 2021-03-18 16:55:50 +01:00
ptitSeb 39faa1538d [DYNAREC] Added 83/1 83/4 83/6 and 83/7 opcodes 2021-03-18 16:48:56 +01:00
ptitSeb 153343fa9e [DYNAREC] Added 39/3B/3D CMP opcodes 2021-03-18 16:41:16 +01:00
ptitSeb 0d3e9f21ee [DYNAREC] Added 66 0F 1F NOP 2021-03-18 16:17:20 +01:00
ptitSeb 8c01412156 [DYNAREC] Added D1 opcodes 2021-03-18 16:08:36 +01:00
ptitSeb bd46fd7d4f [DYNAREC] Fixed and32 emiter and some printer (vvvvvv works, but still not IntoTheBreach) 2021-03-18 16:03:08 +01:00
ptitSeb cb25e077f9 [DYNAREC] Added CC 'Native call' and 0F 1F NOP opcodes 2021-03-18 15:08:26 +01:00
ptitSeb 0551f13f0e Fixed Protection handling 2021-03-18 15:07:53 +01:00
ptitSeb 0965273711 Improvments to bridge handling to avoid deadlock 2021-03-18 15:07:27 +01:00
ptitSeb dd9e8ae8ff [DYNAREC] Added 09/0B/0D OR and 21/23/25 AND opcodes 2021-03-18 12:18:30 +01:00
ptitSeb f08bc7846a Added 31/33/35 XOR opcodes 2021-03-18 12:14:45 +01:00
ptitSeb bac90cfe57 Added C1 opcodes anda few bugfix (no changes in vvvvvv and IntoTheBreach issues) 2021-03-18 11:33:49 +01:00
ptitSeb 6547166c2d Added 8A opcode 2021-03-18 10:33:43 +01:00
ptitSeb 5a07587437 [DYNAREC] Added C2 RETN and C3 RET opcodes 2021-03-17 17:07:04 +01:00
ptitSeb 6a14d26c1d [DYNAREC] Added 01/03/05/83 /0 ADD opcodes, plus various bugfixes (but vvvvvv and IntoTheBreach are still broken, Thimberweed and WorldOfGoo seems ok) 2021-03-17 17:01:00 +01:00
ptitSeb 477617240a [DYNAREC] Added FF opcodes 2021-03-17 12:58:20 +01:00
ptitSeb e8d2b6d25d Excplicit handling of bit size for defered flags 2021-03-17 11:17:49 +01:00
ptitSeb d1a037b38b [DYNAREC] Small optim for MOV64x on negative values 2021-03-17 10:17:50 +01:00
ptitSeb a552e5a48f [DYNAREC] Various fixes, around GETED and other stuff (vvvvvv.x86_64 works again) 2021-03-17 10:11:11 +01:00
ptitSeb b553c3f3ac [DYNAREC] Added 70..7F opcodes (and fixed ORR/AND bitmask coding/decoding, that's some convoluted encoding here) 2021-03-16 20:32:37 +01:00
ptitSeb 551542f99a [DYNAREC] Added 85 opcode 2021-03-16 16:37:37 +01:00
ptitSeb 1e5bfcdbcd [DYNAREC] Added an optimisation with RIP handling 2021-03-16 16:08:48 +01:00
ptitSeb c1b6cb7302 [DYNAREC] Added 8B opcode 2021-03-16 15:45:02 +01:00
ptitSeb 70f5003784 [DYNAREC] Small optimisation on Native call 2021-03-16 14:54:33 +01:00
ptitSeb c2a0d7bc32 [DYNAREC] Added a few more opcodes, some arm64_printer opcodes, and made sure it works 2021-03-16 14:34:44 +01:00
ptitSeb 34c1fec8f7 [DYNAREC] Added 2D and 83 /5 opcodes 2021-03-15 17:35:52 +01:00
ptitSeb 14ec226747 Added 29 opcode 2021-03-15 17:14:51 +01:00
ptitSeb aebad0cf18 [DYNAREC] Added 89 and 8D opcodes 2021-03-15 15:56:58 +01:00
ptitSeb ecac60f4c9 [DYNAREC] Added REX 50..5F opcodes 2021-03-15 15:41:22 +01:00
ptitSeb 21f8b852f2 [DYNAREC] Beggining of emitter and dynarec infrastructure (untested yet) 2021-03-15 15:36:30 +01:00
ptitSeb 4919f161cc [DYNAREC] Added Basic blocks for dynarec 2021-03-14 17:58:04 +01:00
ptitSeb 3dda84e58b Fixed a few minor leaks 2021-03-13 16:43:15 +01:00
ptitSeb 0823bfaed2 Added custom memory handling 2021-03-13 16:40:44 +01:00
ptitSeb 3bcb72a083 Start of a new dev. cycle 2021-03-13 16:10:44 +01:00
ptitSeb 634f3c0f58 Bumped to v0.0.4 2021-03-13 14:11:17 +01:00
ptitSeb f3d3a8a8ed Added wrapped libalut and libalure 2021-03-13 14:10:42 +01:00
ptitSeb 721038513f Wrapped some more functions 2021-03-13 13:47:30 +01:00
ptitSeb 195efffa15 Added a few more SSE opcodes 2021-03-13 13:47:17 +01:00
ptitSeb ae4f43fdb9 Added many wrapped function, and fixed a few one too 2021-03-13 13:11:06 +01:00
ptitSeb 4ce40ad239 Added a few opcodes 2021-03-13 10:45:20 +01:00
ptitSeb ca345d7f55 Added SDL2_mixer, SDL2_image, SDL2_ttf2 and SMPEG2 wrapped libs, plus a few more libc wrapped functions 2021-03-13 10:06:12 +01:00
ptitSeb 066410a31d Fixed some 32bits versio of F7 opcodes 2021-03-13 10:05:25 +01:00
ptitSeb 30e8fa9620 Added a few libc wrapped functions 2021-03-13 09:29:49 +01:00
ptitSeb 64826243dd Added a bunch of SSE opcodes 2021-03-13 09:26:42 +01:00
ptitSeb 2357057bb5 Added wrapped qsort and qsort_r functions 2021-03-12 22:57:49 +01:00
ptitSeb c257075df0 Added wrapped libpulse and libpulsesimple 2021-03-12 22:47:55 +01:00
ptitSeb b1fa994d82 Added F0 00..35 opcodes 2021-03-12 22:47:37 +01:00
ptitSeb 56daf71a86 Added nanosleep wrapped function 2021-03-12 22:33:55 +01:00
ptitSeb 4ac26b61b3 Fixed pthread_attr_setstacksize to avoid setting too small stack on some platforms. Also added pthread_setschedparam 2021-03-12 22:30:13 +01:00
ptitSeb cd3a042776 Fixed issue with XMM 'GETGX' modrm and REX.b 2021-03-12 20:38:07 +01:00
ptitSeb 7fd7479b84 Fixed some warning with modrm on 67 32bits prefix 2021-03-12 18:58:50 +01:00
ptitSeb 9a8c07faf5 Added a bunch of SSE2 opcodes 2021-03-12 18:56:00 +01:00
ptitSeb 335777a681 Added a large number of CPU opcodes 2021-03-12 16:38:54 +01:00
ptitSeb 9479d7ae07 Added more x87 opcodes 2021-03-11 20:21:11 +01:00
ptitSeb 4827427ac0 Added alignment for 'long double' handling in '...' 2021-03-11 19:03:28 +01:00
ptitSeb 8e732046ba Added some SSE2 and x87 opcodes 2021-03-11 17:55:16 +01:00
ptitSeb f08b88cce5 Added 67 E0..E3 opcodes 2021-03-11 17:47:14 +01:00
ptitSeb 5a244911cc Added and fixed many opcodes 2021-03-10 20:44:00 +01:00
ptitSeb 02161dc4d7 Better functions name resolving when using TRACE, and fixed some printf stuff again 2021-03-10 18:02:21 +01:00
ptitSeb a62f686024 Added a bunch of various opcodes 2021-03-10 11:33:15 +01:00
ptitSeb 1b09e8a6b0 Added 66 REX F7 opcodes 2021-03-10 10:32:28 +01:00
ptitSeb 23917fa07e Added 66 D1/D3 opcodes 2021-03-10 10:22:36 +01:00
ptitSeb 0a7963588e Fixed the already wrapped non-valist __Xprintf_chk functions 2021-03-10 10:14:34 +01:00
ptitSeb 42d281bfe3 Wrapped system function 2021-03-10 09:33:46 +01:00
ptitSeb 5e28ebef06 Wrapped some more libc funcs 2021-03-10 09:28:52 +01:00
ptitSeb 3fa01e53b9 Wrapped sprintf 2021-03-10 09:25:19 +01:00
ptitSeb ecac1815db A handfull libc wrapped functions 2021-03-09 22:08:04 +01:00
ptitSeb 79f365753e Added fdopen and fdopendir 2021-03-09 21:58:00 +01:00
ptitSeb 64b7198144 Added uname, ungetc, ungetwc, unlink and __underflow wrapped functions 2021-03-09 21:55:07 +01:00
ptitSeb f3743b6599 Added statfs64 fstatfs64 and _IO_xxxx wrapped functions 2021-03-09 21:51:08 +01:00
ptitSeb 8a0af31a49 Added 66 39/3B/3D CMP opcodes 2021-03-09 21:25:52 +01:00
ptitSeb 044b88dbce Added 6A and 6B opcodes 2021-03-09 21:19:15 +01:00
ptitSeb acf06e6a94 Add freopen wrapped functions 2021-03-09 21:07:21 +01:00
ptitSeb c8922d2efd A __printf_chk wrapped functions 2021-03-09 21:03:21 +01:00
ptitSeb 3786e7569d A few sigXXX wrapped functions 2021-03-09 21:00:50 +01:00
ptitSeb 70ad747a9c Aligned struct stat64 for fxstat(64) also 2021-03-09 20:36:49 +01:00
ptitSeb ce322774d8 Added waitpid and dl_iterate_phdr wrapped functions 2021-03-09 20:29:03 +01:00
ptitSeb 7309be6339 Added 66 64 8B opcode 2021-03-09 19:51:47 +01:00
ptitSeb 5edc83c556 Added more byte to UnImp opcode message 2021-03-09 19:45:23 +01:00
ptitSeb 2c86fb8c73 Add handling of multiple 66 prefix 2021-03-09 19:37:37 +01:00
ptitSeb 25937c5b73 Alignement of struct stat / stat64 2021-03-09 19:35:00 +01:00
ptitSeb 43833df092 Try to reduce the amount of log volume 2021-03-09 18:43:05 +01:00
ptitSeb 93c19dc3f8 Added kill and killpg wrapped functions 2021-03-09 18:37:44 +01:00
ptitSeb a4e53b929b Added some more SSE opcodes 2021-03-09 18:32:32 +01:00
ptitSeb 18534d56e2 Added clock wrapped function 2021-03-09 18:26:22 +01:00
ptitSeb fd35361614 Added F3 0F C2 opcode 2021-03-09 18:23:30 +01:00
ptitSeb 85dfd5b978 More wrapped libc functions 2021-03-09 18:20:32 +01:00
ptitSeb b23fcc83c1 Added more various opcodes 2021-03-09 18:02:39 +01:00
ptitSeb d625cf68e5 Added strtol wrapped function 2021-03-09 17:52:07 +01:00
ptitSeb b7683b77a7 Added a bunch of various opcodes 2021-03-09 17:50:34 +01:00
ptitSeb 3b81d44491 Fixed an issue with SDL Thread Creation 2021-03-09 17:32:57 +01:00
ptitSeb 949bbb40eb A large batch of wrapped libc functions 2021-03-09 17:21:53 +01:00
ptitSeb 5ce5951f5d Added REX 0F BA opcodes 2021-03-09 16:30:04 +01:00
ptitSeb 09428c185e More libc wrapped functions 2021-03-09 16:22:25 +01:00
ptitSeb ad1bfc57b4 Fixed typo in an error message 2021-03-09 16:19:27 +01:00
ptitSeb b971a37ee3 Added sdl1mixer, sdl1image, sdl1ttd, sdl1smpeg and libz wrapped libs 2021-03-09 16:18:38 +01:00
ptitSeb 3ca6ac6145 Added more libc wrapped functions 2021-03-09 15:26:34 +01:00
ptitSeb c2f4ce9c5a Fixed XOpenIM wrapped function signature 2021-03-09 15:26:19 +01:00
ptitSeb 66fee75fc2 Added some more libc wrapped functions 2021-03-09 15:02:25 +01:00
ptitSeb 367e4ac3f7 pthread_mutex_t is larger on ARM64 than on x86_64, that's unfortunate, but all mutex based function need alignements 2021-03-09 14:53:24 +01:00
ptitSeb 094f961a0a Added 66 0F 7F opcode 2021-03-09 14:07:01 +01:00
ptitSeb be676d7fa6 Added a few libc wrapped functions 2021-03-09 14:03:04 +01:00
ptitSeb 32d92866e9 Added REX 0F 5A..5F opcodes 2021-03-09 14:00:36 +01:00
ptitSeb de8a3de7ae Added some more libc wrapped functions 2021-03-09 09:34:31 +01:00
ptitSeb cdd33ffec4 Added some phtreads wrapped functions 2021-03-09 09:26:07 +01:00
ptitSeb 340bdb0b6c Added REX 0F C8..CF BSWAP opcodes 2021-03-09 09:20:17 +01:00
ptitSeb 7f4762e632 Added a few more libc wrapped functions 2021-03-09 09:13:22 +01:00
ptitSeb 22b4b9c18d Remove isCpuTopology function call to the open wrapped functions that is not needed 2021-03-08 21:38:42 +01:00
ptitSeb d31a6c0ba6 Fixed F2/F3 A6/AE opcodes 2021-03-08 21:36:01 +01:00
ptitSeb 59779aea37 Added (F2/F3) A6 (REPNZ/REPZ) CMPSB 2021-03-08 21:30:04 +01:00
ptitSeb 50fa1046c7 Switched emu flags to 64bits 2021-03-08 21:26:37 +01:00
ptitSeb 0e958fed2e Added sigismember wrapped function 2021-03-08 21:25:04 +01:00
ptitSeb def0f3564c Added more wrapped functions to libc and libpthread 2021-03-08 21:23:44 +01:00
ptitSeb 7da2c56d0a Added a few more libc wrapped libs 2021-03-08 21:11:37 +01:00
ptitSeb 1321431812 Added (F2/F3) AE (REPNZ/REPZ) SCASB opcode 2021-03-08 21:07:56 +01:00
ptitSeb d93a243738 Added a few more libc wrapped functions 2021-03-08 20:48:08 +01:00
ptitSeb fa24bbd96a Added wrapped vfprintf and fprintf functions 2021-03-08 20:41:51 +01:00
ptitSeb 5eca802a5a [TRACE] Trace is not displaying relative offsets for now, preparing functions 2021-03-08 20:41:16 +01:00
ptitSeb 89d6f73aff Added special case for stdin/stdout/stderr in elfloader R_X86_64_COPY handling 2021-03-08 20:40:32 +01:00
ptitSeb 0bb2043f97 Fixed va_list conversion for aarch64 2021-03-08 18:45:29 +01:00
ptitSeb 62c22e55e7 Attempts at conversion of va_list 2021-03-08 18:34:07 +01:00
ptitSeb 23eef578f7 Added a few libc wrapped functions 2021-03-08 17:14:42 +01:00
ptitSeb ce8a482a62 Added 66 85 TEST opcode 2021-03-08 17:10:17 +01:00
ptitSeb 76f5319b05 Fixed a few wrapped functions 2021-03-08 17:07:45 +01:00
ptitSeb 448e5155a4 Fixed non-REX.W 8D LEA opcode 2021-03-08 17:07:14 +01:00
ptitSeb 3ee26b727c Added another batch of wrapped x11 related lib (still un-tested copy from box86) 2021-03-08 16:27:55 +01:00
ptitSeb 544a496f08 Added a bunch of X11 related lib (copy from box86, mostly un-verified) 2021-03-08 16:21:33 +01:00
ptitSeb 14f0497e64 Added 0F AE /2 and /3 opcodes 2021-03-08 16:04:47 +01:00
ptitSeb 9ab80d228b Added sysv_signal wrapped function 2021-03-08 16:01:20 +01:00
ptitSeb 3f4599e562 Added A8 TEST opcode 2021-03-08 15:59:31 +01:00
ptitSeb 973714b4cc Added 66 0F 54..5F opcodes 2021-03-08 15:57:17 +01:00
ptitSeb bb3458e26b Added memrchr and memcpy wrapped functions 2021-03-08 15:55:10 +01:00
ptitSeb 0692d4f3f2 Added 66 0F 2E/2F opcodes 2021-03-08 15:53:48 +01:00
ptitSeb 7a08d50f18 Added sigaction and ceil wrapped functions 2021-03-08 15:52:11 +01:00
ptitSeb 987e6e03f1 Added more opcodes, including D8 and DD x87 ones 2021-03-08 15:50:24 +01:00
ptitSeb 5004513596 More 0F and 66 0F opcodes 2021-03-08 15:40:17 +01:00
ptitSeb 749961af32 Added a gew more various opcodes 2021-03-08 15:23:09 +01:00
ptitSeb eda8b442e0 Added wrapped libasound 2021-03-08 15:02:33 +01:00
ptitSeb 9d0e59b31c Added wrapped libX11 2021-03-08 11:24:03 +01:00
ptitSeb 1771694ee1 Wrapped function SDL_LogXXXX needs va_list 2021-03-07 20:33:08 +01:00
ptitSeb 85d16af0d0 Wrapped SDL_LogXXXX function correctly 2021-03-07 20:31:13 +01:00
ptitSeb a80c739067 Disabled va_list wrapped function in SDL2, wrapping is not done yet 2021-03-07 20:27:31 +01:00
ptitSeb 73b2eb4a72 Added a few SSE opcodes 2021-03-07 20:23:59 +01:00
ptitSeb 4c7cbe4128 Added wrapped libSDL1.2, libSDL2.0, libGL, libGLU and libopenal 2021-03-07 20:19:58 +01:00
ptitSeb 343174fd47 Default log level to INFO for now 2021-03-07 17:36:07 +01:00
ptitSeb 3c20930550 Some cosmetic refinement to signal handling 2021-03-07 17:18:20 +01:00
ptitSeb 0e109a9e33 Start of a new dev.cycle 2021-03-07 17:16:31 +01:00
166 changed files with 41895 additions and 2602 deletions

No files matched your search

Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

+22 -2
View File
@@ -1,6 +1,26 @@
Current version
v0.0.6
======
* Using box86 as a base, implemented most planned box64 part except dyanrec
* Added Dynarec for ARM64
* Many general CPU opcode added to the Dynarec
* Many SSEx opcodes added to the Dynarec
* Added a few more symbols in libc
* A few changes to the "thread once" handling
* New Logo and Icon from @grayduck
v0.0.4
======
* Added a lot of opcodes
* Added SDL1 and SDL2 wrapping
* OpenGL/GLU wrapping done
* libasound / libpulse wrapping done
* libopenal / libalure / libalut wrapping done
* Many X11 libs wrapped
* Added "install" with binfmt integration
* A few games are actualy starting now (old WorldOfGoo, Into The Breach, VVVVVV and Thimbeweed Park)
v0.0.2
======
* Using box86 as a base, implemented most planned box64 part except dynarec
* Wrapped a few libs
* ELF loader a bit crude, but seems working
* Signal handling implemented
+136 -13
View File
@@ -5,8 +5,14 @@ option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399}
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
if(RK3399 OR RPI4ARM64)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
endif()
option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" ${LD80BITS})
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
option(ARM_DYNAREC "Set to ON to use ARM Dynamic Recompilation" ${ARM_DYNAREC})
if(${CMAKE_VERSION} VERSION_LESS "3.12.2")
find_package(PythonInterp 3)
@@ -57,7 +63,7 @@ else()
set(BOX64 box64)
endif()
set(BOX64_ELF_ADDRESS "0x50062800000") #random load address...
set(BOX64_ELF_ADDRESS "0x500062800000") #random load address...
if(LD80BITS)
add_definitions(-DHAVE_LD80BITS)
@@ -71,6 +77,12 @@ if(HAVE_TRACE)
add_definitions(-DHAVE_TRACE)
endif()
if(ARM_DYNAREC)
add_definitions(-DDYNAREC)
add_definitions(-DARM64)
enable_language(ASM)
endif()
set(BOX64_ROOT ${CMAKE_SOURCE_DIR})
add_definitions(-std=gnu11 -funwind-tables -fvisibility=hidden)
@@ -113,8 +125,15 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/emu/x64run64.c"
"${BOX64_ROOT}/src/emu/x64run66.c"
"${BOX64_ROOT}/src/emu/x64run660f.c"
"${BOX64_ROOT}/src/emu/x64run6664.c"
"${BOX64_ROOT}/src/emu/x64run66d9.c"
"${BOX64_ROOT}/src/emu/x64run66dd.c"
"${BOX64_ROOT}/src/emu/x64run67.c"
"${BOX64_ROOT}/src/emu/x64rund8.c"
"${BOX64_ROOT}/src/emu/x64rund9.c"
"${BOX64_ROOT}/src/emu/x64runda.c"
"${BOX64_ROOT}/src/emu/x64rundb.c"
"${BOX64_ROOT}/src/emu/x64rundd.c"
"${BOX64_ROOT}/src/emu/x64rundf.c"
"${BOX64_ROOT}/src/emu/x64runf0.c"
"${BOX64_ROOT}/src/emu/x64runf20f.c"
@@ -127,6 +146,8 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/librarian/library.c"
"${BOX64_ROOT}/src/libtools/auxval.c"
"${BOX64_ROOT}/src/libtools/myalign.c"
"${BOX64_ROOT}/src/libtools/sdl1rwops.c"
"${BOX64_ROOT}/src/libtools/sdl2rwops.c"
"${BOX64_ROOT}/src/libtools/signals.c"
"${BOX64_ROOT}/src/libtools/threads.c"
"${BOX64_ROOT}/src/tools/box64stack.c"
@@ -140,12 +161,41 @@ set(ELFLOADER_SRC
)
set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedalure.c"
"${BOX64_ROOT}/src/wrapped/wrappedalut.c"
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibasound.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibc.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibdl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibgl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibglu.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibpthread.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibrt.c"
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibx11.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxau.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcb.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxdmcp.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxext.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxi.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxrandr.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxrender.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxxf86vm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibz.c"
"${BOX64_ROOT}/src/wrapped/wrappedopenal.c"
"${BOX64_ROOT}/src/wrapped/wrappedpulse.c"
"${BOX64_ROOT}/src/wrapped/wrappedpulsesimple.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1image.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1mixer.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1ttf.c"
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2image.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2mixer.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2ttf.c"
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg2.c"
"${BOX64_ROOT}/src/wrapped/wrappedxinerama.c"
)
#set(WRAPPEDS_HEAD "${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9_gen.h")
@@ -172,27 +222,95 @@ add_custom_command(
# OUTPUT "${BOX64_ROOT}/src/dynarec/last_run.txt"
# COMMAND "${PYTHON_EXECUTABLE}" "${BOX64_ROOT}/rebuild_printer.py" "${BOX64_ROOT}"
# MAIN_DEPENDENCY "${BOX64_ROOT}/rebuild_printer.py"
# DEPENDS "${BOX64_ROOT}/src/dynarec/arm_instructions.txt"
# BYPRODUCTS "${BOX64_ROOT}/src/dynarec/arm_printer.c"
# DEPENDS "${BOX64_ROOT}/src/dynarec/arm64_instructions.txt"
# BYPRODUCTS "${BOX64_ROOT}/src/dynarec/arm64_printer.c"
#)
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(ARM_DYNAREC)
set(DYNAREC_SRC
"${BOX64_ROOT}/src/dynarec/dynablock.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_functions.c"
"${BOX64_ROOT}/src/dynarec/arm64_printer.c"
"${BOX64_ROOT}/src/dynarec/arm64_prolog.S"
"${BOX64_ROOT}/src/dynarec/arm64_epilog.S"
"${BOX64_ROOT}/src/dynarec/arm64_next.S"
"${BOX64_ROOT}/src/dynarec/arm64_lock.S"
)
set(DYNAREC_PASS
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_helper.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_emit_tests.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_emit_math.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_emit_logic.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_emit_shift.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_pass.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_00.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_0f.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_64.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_65.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_66.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_67.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_d8.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_d9.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_da.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_db.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dc.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dd.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_de.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_df.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_f0.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_660f.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_f20f.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_f30f.c"
)
set(DYNAREC_PASS "${BOX64_ROOT}/src/wrapped/generated/wrapper.h" ${DYNAREC_PASS})
add_library(dynarec_arm OBJECT ${DYNAREC_SRC})
add_library(arm64_pass0 OBJECT ${DYNAREC_PASS})
set_target_properties(arm64_pass0 PROPERTIES COMPILE_FLAGS "-DSTEP=0")
add_library(arm64_pass1 OBJECT ${DYNAREC_PASS})
set_target_properties(arm64_pass1 PROPERTIES COMPILE_FLAGS "-DSTEP=1")
add_library(arm64_pass2 OBJECT ${DYNAREC_PASS})
set_target_properties(arm64_pass2 PROPERTIES COMPILE_FLAGS "-DSTEP=2")
add_library(arm64_pass3 OBJECT ${DYNAREC_PASS})
set_target_properties(arm64_pass3 PROPERTIES COMPILE_FLAGS "-DSTEP=3")
add_dependencies(arm64_pass0 WRAPPERS)
add_dependencies(arm64_pass1 WRAPPERS)
add_dependencies(arm64_pass2 WRAPPERS)
add_dependencies(arm64_pass3 WRAPPERS)
add_library(dynarec STATIC
$<TARGET_OBJECTS:dynarec_arm>
$<TARGET_OBJECTS:arm64_pass0>
$<TARGET_OBJECTS:arm64_pass1>
$<TARGET_OBJECTS:arm64_pass2>
$<TARGET_OBJECTS:arm64_pass3>
)
endif()
# creates git_head.h
#if(ARM_DYNAREC)
# add_custom_command(
# OUTPUT "${BOX64_ROOT}/src/git_head.h"
# COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX64_ROOT}/src/git_head.h\""
# DEPENDS dynarec ${ELFLOADER_SRC} ${WRAPPEDS}
# VERBATIM)
#else()
if(ARM_DYNAREC)
add_custom_command(
OUTPUT "${BOX64_ROOT}/src/git_head.h"
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX64_ROOT}/src/git_head.h\""
DEPENDS dynarec ${ELFLOADER_SRC} ${WRAPPEDS}
VERBATIM)
else()
add_custom_command(
OUTPUT "${BOX64_ROOT}/src/git_head.h"
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX64_ROOT}/src/git_head.h\""
DEPENDS ${ELFLOADER_SRC} ${WRAPPEDS}
VERBATIM)
#endif()
endif()
add_executable(${BOX64} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX64_ROOT}/src/git_head.h")
add_dependencies(${BOX64} WRAPPERS)
@@ -301,6 +419,11 @@ add_test(test13 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref14.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test15 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test15 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref15.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
Executable
+75
View File
@@ -0,0 +1,75 @@
Compiling
----
#### for RK3399
Using a 64bits OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
```
#### for PI4
Warning, you need a 64bits OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
```
#### for Other ARM64 Linux platforms
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
#### for x86_64 Linux
`mkdir build; cd build; cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
#### use ccmake
Alternatively, you can use the curses-bases ccmake (or any other gui frontend for cmake) to select wich platform to use interactively.
#### Customize your build
*use ccache if you have it*
Add `-DUSE_CCACHE=1` if you have ccache (it's better if you plan to touch the sources)
*have some debug info*
The `-DCMAKE_BUILD_TYPE=RelWithDebInfo` argument makes a build that is both optimized for speed, and has debug information embedded. That way, if you have a crash or try to analyse performance, you'll have some symbols.
*to have a Trace Enabled build*
To have a trace enabled build ( ***it will be slower***), add `-DHAVE_TRACE=1` but you will need, at runtime, to have the [Zydis library](https://github.com/zyantific/zydis) library in your `LD_LIBRARY_PATH` or in the system library folders.
*to have ARM Dynarec*
The Dynarec is only available on the ARM architecture(Right now, anyways.). Notes also that VFPv3 and NEON are required for the Dynarec. Activate it by using `-DARM_DYNAREC=1`. Also, be sure to use `-marm` in compilation flags (because many compileur use Thumb as default, and the dynarec will not work in this mode).
*not building from a git clone*
If you are not building from a git clone (for example, downloading a release source zipped from github), you need to activate `-DNOGIT=1` from cmake to be able to build (normal process include git sha1 of HEAD in the version that box64 print).
----
Testing
----
A few tests are included.
They can be launched with `ctest`
They are very basic and don't test much for now.
+43 -1
View File
@@ -1,7 +1,49 @@
# box64
![Official logo](Box64Logo.png "Official Logo")
Linux Userspace x86_64 Emulator with a twist
----
Box64 lets you run x86_64 Linux programs (such as games) on non-x86_64 Linux systems, like ARM (host system needs to be 64bit little-endian).
Box64 lets you run x86_64 Linux programs (such as games) on non-x86_64 Linux systems, like ARM (host system needs to be 64bit little-endian).
Because 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 some cases.
Box64 integrates a DynaRec (dynamic recompiler) for the ARM64 platform, providing a speed boost between 5 to 10 times faster than only using the interpreter.
Some x86 internal opcodes use parts of "Realmode X86 Emulator Library", see [x86primop.c](src/emu/x86primop.c) for copyright details
<img src="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](USAGE.md) for all 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](COMPILE.md)
----
Version history
----
The change log is available [here](CHANGELOG.md)
----
Final words
----
(If you use Box64 in your project, please don't forget to mention Box64!)
Executable
+136
View File
@@ -0,0 +1,136 @@
Usage
----
There are many environment variables to control Box64 behaviour.
#### BOX64_LOG
Controls the Verbosity level of the logs
* 0: NONE : No message (except some fatal error). (Default.)
* 1: INFO : Show some minimum log (Example: librairies not found)
* 2: DEBUG : Details a lot of stuff (Example: relocations or functions called).
* 3: DUMP : All DEBUG plus DUMP of all ELF Info.
#### BOX64_NOBANNER
Disables Box64 printing its version and build
* 0 : Enable printing its banner. (Default.)
* 1 : Disable printing its banner.
#### 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.
#### BOX64_PATH
Path to look for x86_64 executable. Default is current folder and `bin` in current folder.
#### BOX64_DLSYM_ERROR
Enables/Disables the logging of `dlsym` errors.
* 0 : Don't log `dlsym` errors. (Default.)
* 1 : Log 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
#### BOX64_TRACE
Only on build with trace enabled. Trace allow the logging of all instruction executed, along with register dump
* 0 : No trace. (Default.)
* 1 : Trace enabled. Trace start after the initialisation of all depending libraries is done.
* symbolname : Trace only `symbolname` (trace is disable if the symbol is not found).
* 0xXXXXXXX-0xYYYYYYY : Trace only between the 2 addresses.
#### BOX64_TRACE_INIT
Use BOX64_TRACE_INIT instead of BOX_TRACE to start trace before the initialisation of libraries and the running program
* 0 : No trace. (Default.)
* 1 : Trace enabled. The trace start with the initialisation of all depending libraries is done.
#### BOX64_TRACE_START
Only on builds with trace enabled.
* NNNNNNN : Start trace only after NNNNNNNN opcode execute (number is an `uint64_t`).
#### BOX64_TRACE_XMM
Only on builds with trace enabled.
* 0 : The XMM (i.e. SSE/SSE2) register will not be logged with the general and x86 registers. (Default.)
* 1 : Dump the XMM registers.
#### BOX64_LOAD_ADDR
Try to load at 0xXXXXXX main binary (if binary is a PIE)
* 0xXXXXXXXX : The load address . (Only active on PIE programs.)
#### BOX64_NOSIGSEGV
Disable handling of SigSEGV. (Very useful for debugging.)
* 0 : Let the x86 program set sighandler for SEGV (Default.)
* 1 : Disable the handling of SigSEGV.
#### BOX64_NOSIGILL
Disable handling of SigILL (to ease debugging mainly).
* 0 : Let x86 program set sighandler for Illegal Instruction
* 1 : Disables the handling of SigILL
#### BOX64_X11THREADS
Call XInitThreads when loading X11. (This is mostly for old Loki games with the Loki_Compat library.)
* 0 : Don't force call XInitThreads. (Default.)
* 1 : Call XInitThreads as soon as libX11 is loaded.
#### BOX64_X11GLX
Force libX11's GLX extension to be present.
* 0 : Do not force libX11's GLX extension to be present.
* 1 : GLX will always be present when using XQueryExtension. (Default.)
#### BOX64_DYNAREC_DUMP
Enables/disables Box64's Dynarec's dump.
* 0 : Disable Dynarec's blocks dump. (Default.)
* 1 : Enable Dynarec's blocks dump.
* 2 : Enable Dynarec's blocks dump with some colors.
#### BOX64_DYNAREC_LOG
Set the level of DynaRec's logs.
* 0 : NONE : No Logs for DynaRec. (Default.)
* 1 :INFO : Minimum Dynarec Logs (only unimplemented OpCode).
* 2 : DEBUG : Debug Logs for Dynarec (with details on block created / executed).
* 3 : VERBOSE : All of the above plus more.
#### BOX64_DYNAREC
Enables/Disables Box64's Dynarec.
* 0 : Disables Dynarec.
* 1 : Enable Dynarec. (Default.)
#### BOX64_DYNAREC_TRACE
Enables/Disables trace for generated code.
* 0 : Disable trace for generated code. (Default.)
* 1 : Enable trace for generated code (like regular Trace, this will slow down the program a lot and generate huge logs).
#### BOX64_NODYNAREC
Forbid dynablock creation in the interval specified (helpfull for debugging behaviour difference between Dynarec and Interpretor)
* 0xXXXXXXXX-0xYYYYYYYY : define the interval where dynablock cannot start (inclusive-exclusive)
#### BOX64_LIBGL
* libXXXX set the name for libGL (defaults to libGL.so.1).
* /PATH/TO/libGLXXX : Sets the name and path for libGL
You can also use SDL_VIDEO_GL_DRIVER
#### 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
#### 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
#### BOX64_ALLOWMISSINGLIBS
Allow Box64 to continue even if a library is missing.
* 0 : Box64 will stop if a library cannot be loaded. (Default.)
* 1 : Continue even if a needed library cannot be loaded. Unadvised, this will, in most cases, crash later on.
#### BOX64_JITGDB
* 0 : Just print the Segfault message on segfault (default)
* 1 : Launch `gdb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process and go in an endless loop, waiting.
When in gdb, you need to find the correct thread yourself (the one with `my_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)
+19 -69
View File
@@ -3,7 +3,7 @@
import os
import sys
values = ['E', 'e', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', '2', 'P', 'G', 'N', 'M']
values = ['E', 'e', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H']
def splitchar(s):
try:
ret = [len(s), values.index(s[0])]
@@ -224,17 +224,6 @@ def main(root, defines, files, ver):
#include "regs.h"
#include "x64emu.h"
typedef union ui64_s {
int64_t i;
uint64_t u;
uint32_t d[2];
} ui64_t;
typedef struct _2uint_struct_s {
uint32_t a;
uint32_t b;
} _2uint_struct_t;
extern void* my__IO_2_1_stderr_;
extern void* my__IO_2_1_stdin_ ;
extern void* my__IO_2_1_stdout_;
@@ -252,33 +241,6 @@ static void* io_convert(void* v)
return v;
}
typedef struct my_GValue_s
{
int g_type;
union {
int v_int;
int64_t v_int64;
uint64_t v_uint64;
float v_float;
double v_double;
void* v_pointer;
} data[2];
} my_GValue_t;
static void alignGValue(my_GValue_t* v, void* value)
{
v->g_type = *(int*)value;
memcpy(v->data, value+4, 2*sizeof(double));
}
static void unalignGValue(void* value, my_GValue_t* v)
{
*(int*)value = v->g_type;
memcpy(value+4, v->data, 2*sizeof(double));
}
void* VulkanFromx86(void* src, void** save);
void VulkanTox86(void* src, void* save);
#define ST0val ST0.d
int of_convert(int);
@@ -309,11 +271,9 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
// O = libc O_ flags bitfield
// S = _IO_2_1_stdXXX_ pointer (or FILE*)
// Q = ...
// 2 = struct of 2 uint
// P = Vulkan struture pointer
// G = a single GValue pointer
// N = ... automatically sending 1 arg
// M = ... automatically sending 2 args
// H = Huge 128bits value/struct
"""
}
@@ -349,8 +309,8 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
# First part: typedefs
for v in gbl["()"]:
# E e v c w i I C W u U f d D K l L p V O S 2 P G N M
types = ["x64emu_t*", "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*", "_2uint_struct_t", "void*", "void*", "...", "..."]
# E e v c w i I C W u U f d D K l L p V O S N M H
types = ["x64emu_t*", "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"]
if len(values) != len(types):
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
@@ -359,8 +319,8 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
for k in gbl_idxs:
file.write("\n#if " + k + "\n")
for v in gbl[k]:
# E e v c w i I C W u U f d D K l L p V O S 2 P G N M
types = ["x64emu_t*", "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*", "_2uint_struct_t", "void*", "void*", "...", "..."]
# E e v c w i I C W u U f d D K l L p V O S N M H
types = ["x64emu_t*", "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"]
if len(values) != len(types):
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
@@ -375,17 +335,17 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
# Helper variables
reg_arg = ["R_RDI", "R_RSI", "R_RDX", "R_RCX", "R_R8", "R_R9"]
# vreg: value is in a general register
# E e v c w i I C W u U f d D K l L p V O S 2 P G N, M
vreg = [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 2]
# E e v c w i I C W u U f d D K l L p V O S N M H
vreg = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2]
# vxmm: value is in a XMM register
# E e v c w i I C W u U f d D K l L p V O S 2 P G N, M
vxmm = [0, 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]
# E e v c w i I C W u U f d D K l L p V O S N M H
vxmm = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# vother: value is elsewere
# E e v c w i I C W u U f d D K l L p V O S 2 P G N, M
vother = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0]
# E e v c w i I C W u U f d D K l L p V O S N M, H
vother = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0]
# vstack: value is on the stack (or out of register)
# E e v c w i I C W u U f d D K l L p V O S 2 P G N, M
vstack = [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 2]
# E e v c w i I C W u U f d D K l L p V O S N M, H
vstack = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 1, 1, 1, 2, 2]
arg_s = [
"", # E
"", # e
@@ -408,11 +368,9 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
"", # V
"of_convert(*(int32_t*)(R_RSP + {p})), ", # O
"io_convert(*(void**)(R_RSP + {p})), ", # S
"(_2uint_struct_t){{*(uintptr_t*)(R_RSP + {p}),*(uintptr_t*)(R_RSP + {p} + 4)}}, ", # 2
"", # P
"", # G
"*(void**)(R_RSP + {p}), ", # N
"*(void**)(R_RSP + {p}),*(void**)(R_RSP + {p} + 8), ", # M
"*(unsigned __int128)(R_RSP + {p}), " # H
]
arg_r = [
"", # E
@@ -436,11 +394,9 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
"", # V
"of_convert((int32_t){p}), ", # O
"io_convert((void*){p}), ", # S
"", # 2
"", # P
"", # G
"(void*){p}, ", # N
"(void*){p}, ", # M
"#error use pp instead, ", #H
]
arg_x = [
"", # E
@@ -464,11 +420,9 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
"", # V
"", # O
"", # S
"", # 2
"", # P
"", # G
"", # N
"", # M
"", # H
]
arg_o = [
"emu, ", # E
@@ -492,11 +446,9 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
"(void*)(R_RSP + {p}), ", # V
"", # O
"", # S
"", # 2
"arg{p}, ", # P
"&arg{p}, ", # G
"", # N
"", # M
"", # H
]
vals = [
@@ -521,11 +473,9 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
"\n#error Invalid return type: va_list\n", # V
"\n#error Invalid return type: at_flags\n", # O
"\n#error Invalid return type: _io_file*\n", # S
"\n#error Invalid return type: _2uint_struct\n", # 2
"\n#error Invalid return type: Vulkan Struct\n", # P
"\n#error Invalid return type: GValue Pointer\n", # G
"\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
]
# Asserts
if len(values) != len(arg_s):
+5 -4
View File
@@ -27,6 +27,7 @@ void initAllHelpers(box64context_t* context)
return;
my_context = context;
init_pthread_helper();
init_bridge_helper();
init_signal_helper(context);
inited = 1;
}
@@ -39,7 +40,7 @@ void finiAllHelpers(box64context_t* context)
return;
fini_pthread_helper(context);
fini_signal_helper();
cleanAlternate();
fini_bridge_helper();
fini_custommem_helper(context);
finied = 1;
}
@@ -88,7 +89,7 @@ box64context_t *NewBox64Context(int argc)
context->local_maplib = NewLibrarian(context, 1);
context->system = NewBridge();
// create vsyscall
context->vsyscall = AddBridge(context->system, vFv, x64Syscall, 0);
context->vsyscall = AddBridge(context->system, vFv, x64Syscall, 0, NULL);
context->box64lib = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
context->dlprivate = NewDLPrivate();
@@ -180,8 +181,8 @@ void FreeBox64Context(box64context_t** context)
FreeBridge(&ctx->system);
// freeGLProcWrapper(ctx);
// freeALProcWrapper(ctx);
freeGLProcWrapper(ctx);
freeALProcWrapper(ctx);
void* ptr;
+2 -2
View File
@@ -3,6 +3,6 @@
#define BOX64_MAJOR 0
#define BOX64_MINOR 0
#define BOX64_REVISION 2
#define BOX64_REVISION 6
#endif //__BOX64_VERSION_H_
#endif //__BOX64_VERSION_H_
+748 -658
View File
File diff suppressed because it is too large. Load diff
+1184
View File
File diff suppressed because it is too large. Load diff
+54
View File
@@ -0,0 +1,54 @@
//arm epilog for dynarec
//Save stuff, prepare stack and register
//called with pointer to emu as 1st parameter
//and address to jump to as 2nd parameter
.text
.align 4
.global arm64_epilog
arm64_epilog:
//update register -> emu
stp x10, x11, [x0, (8 * 0)]
stp x12, x13, [x0, (8 * 2)]
stp x14, x15, [x0, (8 * 4)]
stp x16, x17, [x0, (8 * 6)]
stp x18, x19, [x0, (8 * 8)]
stp x20, x21, [x0, (8 * 10)]
stp x22, x23, [x0, (8 * 12)]
stp x24, x25, [x0, (8 * 14)]
stp x26, x27, [x0, (8 * 16)] // put back reg value in emu, including EIP (so x27 must be EIP now)
//restore all used register
//vpop {d8-d15}
ldp x19, x20, [sp, (8 * 0)]
ldp x21, x22, [sp, (8 * 2)]
ldp x23, x24, [sp, (8 * 4)]
ldp x25, x26, [sp, (8 * 6)]
ldr x27, [sp, (8 * 8)]
ldp d8, d9, [sp, (8 *10)]
ldp d10, d11, [sp, (8 *12)]
ldp d12, d13, [sp, (8 *14)]
ldp d14, d15, [sp, (8 *16)]
add sp, sp, (8 * 18)
ldp lr, fp, [sp], 16 // saved lr
//end, return...
ret
.global arm64_epilog_fast
arm64_epilog_fast:
//restore all used register
//vpop {d8-d15}
ldp x19, x20, [sp, (8 * 0)]
ldp x21, x22, [sp, (8 * 2)]
ldp x23, x24, [sp, (8 * 4)]
ldp x25, x26, [sp, (8 * 6)]
ldr x27, [sp, (8 * 8)]
ldp d8, d9, [sp, (8 *10)]
ldp d10, d11, [sp, (8 *12)]
ldp d12, d13, [sp, (8 *14)]
ldp d14, d15, [sp, (8 *16)]
add sp, sp, (8 * 18)
ldp lr, fp, [sp], 16 // saved lr
//end, return...
ret
+87
View File
@@ -0,0 +1,87 @@
//arm lock helper
//there is 2 part: read and write
// write return 0 on success, 1 on fail (value has been changed)
.text
.align 4
.global arm64_lock_read_b
.global arm64_lock_write_b
.global arm64_lock_read_h
.global arm64_lock_write_h
.global arm64_lock_read_d
.global arm64_lock_write_d
.global arm64_lock_read_dd
.global arm64_lock_write_dd
.global arm64_lock_xchg
.global arm64_lock_storeifnull
arm64_lock_read_b:
// address is x0, return is x0
ldaxrb w0, [x0]
ret
arm64_lock_write_b:
// address is x0, value is x1, return is x0
mov x2, x0
stlxrb w0, w1, [x2]
ret
arm64_lock_read_h:
// address is x0, return is x0
ldaxrh w0, [x0]
ret
arm64_lock_write_h:
// address is x0, value is x1, return is x0
mov x2, x0
stlxrh w0, w1, [x2]
ret
arm64_lock_read_d:
// address is x0, return is x0
ldaxr w0, [x0]
#ldx w0,[x0]
ret
arm64_lock_write_d:
// address is x0, value is w1, return is x0
mov x2, x0
stlxr w0, w1, [x2]
#str w1, [x2]
mov w0, 0
ret
arm64_lock_read_dd:
// address is x0, return is x0
ldaxr x0, [x0]
ret
arm64_lock_write_dd:
// address is x0, value is x1, return is x0
mov x2, x0
stlxr w0, x1, [x2]
ret
arm64_lock_xchg:
// address is x0, value is x1, return old value in x0
ldaxr x2, [x0]
stlxr w3, x1, [x0]
cmp w3, #1
beq arm64_lock_xchg
mov x0, x2
ret
arm64_lock_storeifnull:
// address is x0, value is x1, x1 store to x0 only if [x0] is 0. return new [x0] value (so x1 or old value)
ldaxr x2, [x0]
cmp x2, #0
bne arm64_lock_storeifnull_exit
mov x2, x1
stlxr w3, x2, [x0]
cmp w3, #1
beq arm64_lock_storeifnull
arm64_lock_storeifnull_exit:
mov x0, x2
ret
+31
View File
@@ -0,0 +1,31 @@
#ifndef __ARM64_LOCK__H__
#define __ARM64_LOCK__H__
#include <stdint.h>
// LDAXRB of ADDR
extern uint8_t arm64_lock_read_b(void* addr);
// STLXRB of ADDR, return 0 if ok, 1 if not
extern int arm64_lock_write_b(void* addr, uint8_t val);
// LDAXRH of ADDR
extern uint16_t arm64_lock_read_h(void* addr);
// STLXRH of ADDR, return 0 if ok, 1 if not
extern int arm64_lock_write_h(void* addr, uint16_t val);
// LDAXR of ADDR
extern uint32_t arm64_lock_read_d(void* addr);
// STLXR of ADDR, return 0 if ok, 1 if not
extern int arm64_lock_write_d(void* addr, uint32_t val);
// LDAXRD of ADDR
extern uint64_t arm64_lock_read_dd(void* addr);
// STLXR of ADDR, return 0 if ok, 1 if not
extern int arm64_lock_write_dd(void* addr, uint64_t val);
// Atomicaly exchange value at [p] with val, return old p
extern uintptr_t arm64_lock_xchg(void* p, uintptr_t val);
// Atomicaly store value to [p] only if [p] is NULL. Return new [p] value (so val or old)
extern void* arm64_lock_storeifnull(void*p, void* val);
#endif //__ARM64_LOCK__H__
+36
View File
@@ -0,0 +1,36 @@
//arm update linker table for dynarec
//called with pointer to emu as 1st parameter
//and address of table to as 2nd parameter
//ip is at r12
.text
.align 4
.extern LinkNext
.global arm64_next
arm64_next:
// emu is r0
// IP address is r1
sub sp, sp, (8 * 12)
stp x0, x1, [sp, (8 * 0)]
stp x10, x11, [sp, (8 * 2)]
stp x12, x13, [sp, (8 * 4)]
stp x14, x15, [sp, (8 * 6)]
stp x16, x17, [sp, (8 * 8)]
str x18, [sp, (8 * 10)]
// call the function
bl LinkNext
// preserve return value
mov x3, x0
// pop regs
ldp x0, x1, [sp, (8 * 0)]
ldp x10, x11, [sp, (8 * 2)]
ldp x12, x13, [sp, (8 * 4)]
ldp x14, x15, [sp, (8 * 6)]
ldp x16, x17, [sp, (8 * 8)]
ldr x18, [sp, (8 * 10)]
add sp, sp, (8 * 12)
// return offset is jump address
br x3
+1038
View File
File diff suppressed because it is too large. Load diff
+6
View File
@@ -0,0 +1,6 @@
#ifndef _ARM_PRINTER_H_
#define _ARM_PRINTER_H_
const char* arm64_print(uint32_t opcode, uint64_t addr);
#endif //_ARM_PRINTER_H_
+35
View File
@@ -0,0 +1,35 @@
//arm prologue for dynarec
//Save stuff, prepare stack and register
//called with pointer to emu as 1st parameter
//and address to jump to as 2nd parameter
.text
.align 4
.global arm64_prolog
arm64_prolog:
//save all 18 used register
stp lr, fp, [sp, -16]! // save lr
sub sp, sp, (8 * 18)
stp x19, x20, [sp, (8 * 0)]
stp x21, x22, [sp, (8 * 2)]
stp x23, x24, [sp, (8 * 4)]
stp x25, x26, [sp, (8 * 6)]
str x27, [sp, (8 * 8)]
stp d8, d9, [sp, (8 *10)]
stp d10, d11, [sp, (8 *12)]
stp d12, d13, [sp, (8 *14)]
stp d14, d15, [sp, (8 *16)]
//vpush {d8-d15} // save NEON regs?
//setup emu -> register
ldp x10, x11, [x0, (8 * 0)]
ldp x12, x13, [x0, (8 * 2)]
ldp x14, x15, [x0, (8 * 4)]
ldp x16, x17, [x0, (8 * 6)]
ldp x18, x19, [x0, (8 * 8)]
ldp x20, x21, [x0, (8 * 10)]
ldp x22, x23, [x0, (8 * 12)]
ldp x24, x25, [x0, (8 * 14)]
ldp x26, x27, [x0, (8 * 16)]
//jump to function
br x1
+426
View File
@@ -0,0 +1,426 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "tools/bridge_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynablock.h"
#include "dynablock_private.h"
#include "dynarec_private.h"
#include "elfloader.h"
#ifdef ARM64
#include "dynarec_arm64.h"
#include "arm64_lock.h"
#else
#error Unsupported architecture!
#endif
#include "custommem.h"
#include "khash.h"
KHASH_MAP_INIT_INT(dynablocks, dynablock_t*)
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;
}
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
{
if(!textsz) {
printf_log(LOG_NONE, "Error, creating a NULL sized Dynablock\n");
return NULL;
}
dynablocklist_t* ret = (dynablocklist_t*)calloc(1, sizeof(dynablocklist_t));
ret->text = text;
ret->textsz = textsz;
if(direct && textsz) {
ret->direct = (dynablock_t**)calloc(textsz, sizeof(dynablock_t*));
if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
}
dynarec_log(LOG_DEBUG, "New Dynablocklist %p, from %p->%p\n", ret, (void*)text, (void*)(text+textsz));
return ret;
}
void FreeDynablock(dynablock_t* db)
{
if(db) {
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p parent=%p, father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size, db->parent, db->father, db->sons_size, db->gone);
if(db->gone)
return; // already in the process of deletion!
db->done = 0;
db->gone = 1;
// remove from direct if there
uintptr_t startdb = db->parent->text;
uintptr_t enddb = db->parent->text + db->parent->textsz;
if(db->parent->direct) {
uintptr_t addr = (uintptr_t)db->x64_addr;
if(addr>=startdb && addr<enddb)
db->parent->direct[addr-startdb] = NULL;
}
// remove jumptable
setJumpTableDefault64(db->x64_addr);
// remove and free the sons
for (int i=0; i<db->sons_size; ++i) {
dynablock_t *son = (dynablock_t*)arm64_lock_xchg(&db->sons[i], 0);
FreeDynablock(son);
}
// only the father free the DynarecMap
if(!db->father) {
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
}
free(db->sons);
free(db->instsize);
free(db);
}
}
void FreeDynablockList(dynablocklist_t** dynablocks)
{
if(!dynablocks)
return;
if(!*dynablocks)
return;
dynarec_log(LOG_DEBUG, "Free Dynablocklist %p, with Direct Blocks %p\n", *dynablocks, (*dynablocks)->direct);
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father)
FreeDynablock((*dynablocks)->direct[i]);
}
free((*dynablocks)->direct);
}
(*dynablocks)->direct = NULL;
free(*dynablocks);
*dynablocks = NULL;
}
void MarkDynablock(dynablock_t* db)
{
if(db) {
if(db->father)
db = db->father; // mark only father
if(db->need_test)
return; // already done
db->need_test = 1; // test only blocks that can be marked (and so deleted)
setJumpTableDefault64(db->x64_addr);
for(int i=0; i<db->sons_size; ++i)
setJumpTableDefault64(db->sons[i]->x64_addr);
}
}
uintptr_t StartDynablockList(dynablocklist_t* db)
{
if(db)
return db->text;
return 0;
}
uintptr_t EndDynablockList(dynablocklist_t* db)
{
if(db)
return db->text+db->textsz-1;
return 0;
}
int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintptr_t end2)
{
if(start1 > end2 || start2 > end1)
return 0;
return 1;
}
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
if(!dynablocks->direct)
return;
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz -1;
uintptr_t start = addr;
uintptr_t end = addr+size-1;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
dynablock_t *db;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i)
if((db=dynablocks->direct[i-startdb]))
if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1))
MarkDynablock(db);
}
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
if(dynablocks->direct) {
dynablock_t* db;
int ret;
khint_t k;
kh_dynablocks_t *blocks = kh_init(dynablocks);
// copy in a temporary list
if(dynablocks->direct) {
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
uintptr_t start = addr;
uintptr_t end = addr+size;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i) {
db = (dynablock_t*)arm64_lock_xchg(&dynablocks->direct[i-startdb], 0);
if(db) {
if(db->father)
db = db->father;
if(db->parent==dynablocks) {
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
kh_value(blocks, k) = db;
}
}
}
}
// purge the list
kh_foreach_value(blocks, db,
FreeDynablock(db);
);
kh_destroy(dynablocks, blocks);
}
}
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
if(dynablocks->direct) {
uintptr_t new_addr = addr - dynablocks->maxsz;
uintptr_t new_size = size + dynablocks->maxsz;
MarkDirectDynablock(dynablocks, new_addr, new_size);
// the blocks check before
for(int idx=(new_addr)>>DYNAMAP_SHIFT; idx<(addr>>DYNAMAP_SHIFT); ++idx)
MarkDirectDynablock(getDB(idx), new_addr, new_size);
}
}
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks)
{
if(!dynablocks)
return NULL;
dynablock_t* db;
kh_foreach_value(dynablocks, db,
const uintptr_t s = (uintptr_t)db->block;
const uintptr_t e = (uintptr_t)db->block+db->size;
if((uintptr_t)addr>=s && (uintptr_t)addr<e)
return db->father?db->father:db;
)
return NULL;
}
static dynablocklist_t* getDBFromAddress(uintptr_t addr)
{
const uintptr_t idx = (addr>>DYNAMAP_SHIFT);
return getDB(idx);
}
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created)
{
if(!dynablocks) {
dynarec_log(LOG_INFO, "Warning: Ask to create a dynablock with a NULL dynablocklist (addr=%p)\n", (void*)addr);
*created = 0;
return NULL;
}
if((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz))) {
// this should be useless
//dynarec_log(LOG_INFO, "Warning: Refused to create a Direct Block that is out-of-bound: dynablocks=%p (%p:%p), addr=%p\n", dynablocks, (void*)(dynablocks->text), (void*)(dynablocks->text+dynablocks->textsz), (void*)addr);
//*created = 0;
//return NULL;
return AddNewDynablock(getDBFromAddress(addr), addr, created);
}
dynablock_t* block = NULL;
// first, check if it exist in direct access mode
if(dynablocks->direct) {
block = dynablocks->direct[addr-dynablocks->text];
if(block) {
dynarec_log(LOG_DUMP, "Block already exist in Direct Map\n");
*created = 0;
return block;
}
}
if (!*created)
return block;
if(!dynablocks->direct) {
dynablock_t** p = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*));
if(arm64_lock_storeifnull(&dynablocks->direct, p)!=p)
free(p); // someone already create the direct array, too late...
}
// create and add new block
dynarec_log(LOG_DUMP, "Ask for DynaRec Block creation @%p\n", (void*)addr);
block = (dynablock_t*)calloc(1, sizeof(dynablock_t));
block->parent = dynablocks;
dynablock_t* tmp = (dynablock_t*)arm64_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
if(tmp != block) {
// a block appeard!
free(block);
*created = 0;
return tmp;
}
*created = 1;
return block;
}
/*
return NULL if block is not found / cannot be created.
Don't create if create==0
*/
static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current)
{
// try the quickest way first: get parent of current and check if ok!
dynablocklist_t *dynablocks = NULL;
dynablock_t* block = NULL;
if(current) {
dynablocks = current->parent;
if(dynablocks && !(addr>=dynablocks->text && addr<(dynablocks->text+dynablocks->textsz)))
dynablocks = NULL;
}
// nope, lets do the long way
if(!dynablocks) {
dynablocks = getDBFromAddress(addr);
if(!dynablocks) {
dynablocks = GetDynablocksFromAddress(emu->context, addr);
if(!dynablocks)
return NULL;
}
}
// check direct first, without lock
if(dynablocks->direct/* && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))*/)
if((block = dynablocks->direct[addr-dynablocks->text]))
return block;
int created = create;
block = AddNewDynablock(dynablocks, addr, &created);
if(!created)
return block; // existing block...
#if 1
if(box64_dynarec_dump)
pthread_mutex_lock(&my_context->mutex_dyndump);
#endif
// fill the block
block->x64_addr = (void*)addr;
if(!FillBlock64(block, filladdr)) {
void* old = (void*)arm64_lock_xchg(&dynablocks->direct[addr-dynablocks->text], 0);
if(old!=block && old) {// put it back in place, strange things are happening here!
dynarec_log(LOG_INFO, "Warning, a wild block appeared at %p: %p\n", (void*)addr, old);
arm64_lock_xchg(&dynablocks->direct[addr-dynablocks->text], (uintptr_t)old);
}
free(block);
block = NULL;
}
#if 1
if(box64_dynarec_dump)
pthread_mutex_unlock(&my_context->mutex_dyndump);
#endif
// check size
if(block && block->x64_size) {
int blocksz = block->x64_size;
if(dynablocks->maxsz<blocksz) {
dynablocks->maxsz = blocksz;
for(int idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz)>>DYNAMAP_SHIFT); ++idx) {
dynablocklist_t* dblist;
if((dblist = getDB(idx)))
if(dblist->maxsz<blocksz)
dblist->maxsz = blocksz;
}
}
lockDB();
protectDBnolock((uintptr_t)block->x64_addr, block->x64_size);
// fill-in jumptable
addJumpTableIfDefault64(block->x64_addr, block->block);
for(int i=0; i<block->sons_size; ++i)
addJumpTableIfDefault64(block->sons[i]->x64_addr, block->sons[i]->block);
unlockDB();
}
dynarec_log(LOG_DEBUG, " --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, with %d son(s))\n", created?"created":"recycled", (void*)addr, (void*)(addr+((block)?block->x64_size:0)), (block)?block->block:0, (block)?block->size:0, (block)?block->sons_size:0);
return block;
}
dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, dynablock_t** current)
{
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current);
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
dynablock_t *father = db->father?db->father:db;
uint32_t hash = X31_hash_code(father->x64_addr, father->x64_size);
if(hash!=father->hash) {
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size, hash, father->hash, father->sons_size, (void*)addr);
// no more current if it gets invalidated too
if(*current && father->x64_addr>=(*current)->x64_addr && (father->x64_addr+father->x64_size)<(*current)->x64_addr)
*current = NULL;
// Free father, it's now invalid!
FreeDynablock(father);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, addr, create, *current);
} else {
father->need_test = 0;
lockDB();
protectDBnolock((uintptr_t)father->x64_addr, father->x64_size);
// fill back jumptable
addJumpTableIfDefault64(father->x64_addr, father->block);
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block);
unlockDB();
}
}
return db;
}
dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr)
{
dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr);
int create = 1;
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
dynablock_t *father = db->father?db->father:db;
uint32_t hash = X31_hash_code(father->x64_addr, father->x64_size);
if(hash!=father->hash) {
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size, hash, father->hash, father->sons_size, (void*)addr);
// Free father, it's now invalid!
FreeDynablock(father);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
} else {
father->need_test = 0;
lockDB();
protectDBnolock((uintptr_t)father->x64_addr, father->x64_size);
// fill back jumptable
addJumpTableIfDefault64(father->x64_addr, father->block);
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block);
unlockDB();
}
}
return db;
}
+36
View File
@@ -0,0 +1,36 @@
#ifndef __DYNABLOCK_PRIVATE_H_
#define __DYNABLOCK_PRIVATE_H_
typedef struct dynablocklist_s dynablocklist_t;
typedef struct instsize_s {
unsigned int x64:4;
unsigned int nat:4;
} instsize_t;
typedef struct dynablock_s {
dynablocklist_t* parent;
void* block;
int size;
void* x64_addr;
uintptr_t x64_size;
uint32_t hash;
uint8_t need_test;
uint8_t done;
uint8_t gone;
uint8_t dummy;
int isize;
dynablock_t** sons; // sons (kind-of dummy dynablock...)
int sons_size;
dynablock_t* father; // set only in the case of a son
instsize_t* instsize;
} dynablock_t;
typedef struct dynablocklist_s {
uintptr_t text;
int textsz;
int maxsz; // maxblock size (for this block or previous block)
dynablock_t** direct; // direct mapping (waste of space, so the array is created at first write)
} dynablocklist_t;
#endif //__DYNABLOCK_PRIVATE_H_
+19 -19
View File
@@ -22,10 +22,10 @@
#endif
#ifdef DYNAREC
#ifdef ARM
void arm_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
void arm_epilog() EXPORTDYN;
void arm_epilog_fast() EXPORTDYN;
#ifdef ARM64
void arm64_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
void arm64_epilog() EXPORTDYN;
void arm64_epilog_fast() EXPORTDYN;
#endif
#endif
@@ -39,7 +39,7 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
if(!addr) {
x2-=8; // actual PC is 2 instructions ahead
dynablock_t* db = FindDynablockFromNativeAddress(x2);
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x86addr=%p)\n", x2, db, db?(void*)getX86Address(db, (uintptr_t)x2):NULL);
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x64addr=%p)\n", x2, db, db?(void*)getX64Address(db, (uintptr_t)x2):NULL);
}
#endif
dynablock_t* current = NULL;
@@ -47,17 +47,17 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
dynablock_t* block = DBGetBlock(emu, addr, 1, &current);
if(!block) {
// no block, let link table as is...
//tableupdate(arm_epilog, addr, table);
return arm_epilog;
//tableupdate(arm64_epilog, addr, table);
return arm64_epilog;
}
if(!block->done) {
// not finished yet... leave linker
//tableupdate(arm_linker, addr, table);
return arm_epilog;
return arm64_epilog;
}
if(!(jblock=block->block)) {
// null block, but done: go to epilog, no linker here
return arm_epilog;
return arm64_epilog;
}
//dynablock_t *father = block->father?block->father:block;
return jblock;
@@ -82,7 +82,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
}
}
#ifdef DYNAREC
if(!box86_dynarec)
if(!box64_dynarec)
#endif
EmuCall(emu, addr);
#ifdef DYNAREC
@@ -107,18 +107,18 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
dynarec_log(LOG_DEBUG, "%04d|Calling Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
Run(emu, 1);
} else {
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x86 instructions (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,block->father, emu);
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,block->father, emu);
CHECK_FLAGS(emu);
// block is here, let's run it!
#ifdef ARM
arm_prolog(emu, block->block);
#ifdef ARM64
arm64_prolog(emu, block->block);
#endif
}
if(emu->fork) {
int forktype = emu->fork;
emu->quit = 0;
emu->fork = 0;
emu = x86emu_fork(emu, forktype);
emu = x64emu_fork(emu, forktype);
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
ejb->emu = emu;
@@ -170,7 +170,7 @@ int DynaRun(x64emu_t* emu)
}
}
#ifdef DYNAREC
if(!box86_dynarec)
if(!box64_dynarec)
#endif
return Run(emu, 0);
#ifdef DYNAREC
@@ -186,17 +186,17 @@ int DynaRun(x64emu_t* emu)
dynarec_log(LOG_DEBUG, "%04d|Running Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
Run(emu, 1);
} else {
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x86 insts (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, block->father, emu);
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, block->father, emu);
// block is here, let's run it!
#ifdef ARM
arm_prolog(emu, block->block);
#ifdef ARM64
arm64_prolog(emu, block->block);
#endif
}
if(emu->fork) {
int forktype = emu->fork;
emu->quit = 0;
emu->fork = 0;
emu = x86emu_fork(emu, forktype);
emu = x64emu_fork(emu, forktype);
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
ejb->emu = emu;
+477
View File
@@ -0,0 +1,477 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include "debug.h"
#include "box64context.h"
#include "custommem.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "tools/bridge_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynablock.h"
#include "dynablock_private.h"
#include "dynarec_arm64.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "elfloader.h"
void printf_x64_instruction(zydis_dec_t* dec, instruction_x64_t* inst, const char* name) {
uint8_t *ip = (uint8_t*)inst->addr;
if(ip[0]==0xcc && ip[1]=='S' && ip[2]=='C') {
uintptr_t a = *(uintptr_t*)(ip+3);
if(a==0) {
dynarec_log(LOG_NONE, "%s%p: Exit x64emu%s\n", (box64_dynarec_dump>1)?"\e[1m":"", (void*)ip, (box64_dynarec_dump>1)?"\e[m":"");
} else {
dynarec_log(LOG_NONE, "%s%p: Native call to %p%s\n", (box64_dynarec_dump>1)?"\e[1m":"", (void*)ip, (void*)a, (box64_dynarec_dump>1)?"\e[m":"");
}
} else {
if(dec) {
dynarec_log(LOG_NONE, "%s%p: %s", (box64_dynarec_dump>1)?"\e[1m":"", ip, DecodeX64Trace(dec, inst->addr));
} else {
dynarec_log(LOG_NONE, "%s%p: ", (box64_dynarec_dump>1)?"\e[1m":"", ip);
for(int i=0; i<inst->size; ++i) {
dynarec_log(LOG_NONE, "%02X ", ip[i]);
}
dynarec_log(LOG_NONE, " %s", name);
}
// print Call function name if possible
if(ip[0]==0xE8 || ip[0]==0xE9) { // Call / Jmp
uintptr_t nextaddr = (uintptr_t)ip + 5 + *((int32_t*)(ip+1));
printFunctionAddr(nextaddr, "=> ");
} else if(ip[0]==0xFF) {
if(ip[1]==0x25) {
uintptr_t nextaddr = (uintptr_t)ip + 6 + *((int32_t*)(ip+2));
printFunctionAddr(nextaddr, "=> ");
}
}
// end of line and colors
dynarec_log(LOG_NONE, "%s\n", (box64_dynarec_dump>1)?"\e[m":"");
}
}
void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
if(dyn->next_sz == dyn->next_cap) {
dyn->next_cap += 16;
dyn->next = (uintptr_t*)realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
}
for(int i=0; i<dyn->next_sz; ++i)
if(dyn->next[i]==addr)
return;
dyn->next[dyn->next_sz++] = addr;
}
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
// get closest, but no addresses befores
uintptr_t best = 0;
int i = 0;
while((i<dyn->next_sz) && (best!=addr)) {
if(dyn->next[i]<addr) { // remove the address, it's before current address
memmove(dyn->next+i, dyn->next+i+1, (dyn->next_sz-i-1)*sizeof(uintptr_t));
--dyn->next_sz;
} else {
if((dyn->next[i]<best) || !best)
best = dyn->next[i];
++i;
}
}
return best;
}
#define PK(A) (*((uint8_t*)(addr+(A))))
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n)
{
if(!n)
return 1;
if(PK(0)==0x90)
return is_nops(dyn, addr+1, n-1);
if(n>1 && PK(0)==0x66) // if opcode start with 0x66, and there is more after, than is *can* be a NOP
return is_nops(dyn, addr+1, n-1);
if(n>2 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x00)
return is_nops(dyn, addr+3, n-3);
if(n>2 && PK(0)==0x8d && PK(1)==0x76 && PK(2)==0x00) // lea esi, [esi]
return is_nops(dyn, addr+3, n-3);
if(n>3 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x40 && PK(3)==0x00)
return is_nops(dyn, addr+4, n-4);
if(n>3 && PK(0)==0x8d && PK(1)==0x74 && PK(2)==0x26 && PK(3)==0x00)
return is_nops(dyn, addr+4, n-4);
if(n>4 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x44 && PK(3)==0x00 && PK(4)==0x00)
return is_nops(dyn, addr+5, n-5);
if(n>5 && PK(0)==0x8d && PK(1)==0xb6 && PK(2)==0x00 && PK(3)==0x00 && PK(4)==0x00 && PK(5)==0x00)
return is_nops(dyn, addr+6, n-6);
if(n>6 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x80 && PK(3)==0x00 && PK(4)==0x00 && PK(5)==0x00 && PK(6)==0x00)
return is_nops(dyn, addr+7, n-7);
if(n>6 && PK(0)==0x8d && PK(1)==0xb4 && PK(2)==0x26 && PK(3)==0x00 && PK(4)==0x00 && PK(5)==0x00 && PK(6)==0x00) // lea esi, [esi+0]
return is_nops(dyn, addr+7, n-7);
if(n>7 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x84 && PK(3)==0x00 && PK(4)==0x00 && PK(5)==0x00 && PK(6)==0x00 && PK(7)==0x00)
return is_nops(dyn, addr+8, n-8);
return 0;
}
// return size of next instuciton, -1 is unknown
// not all instrction are setup
int next_instruction(dynarec_arm_t *dyn, uintptr_t addr)
{
uint8_t opcode = PK(0);
uint8_t nextop;
switch (opcode) {
case 0x66:
opcode = PK(1);
switch(opcode) {
case 0x90:
return 2;
}
break;
case 0x81:
nextop = PK(1);
return fakeed(dyn, addr+2, 0, nextop)-addr + 4;
case 0x83:
nextop = PK(1);
return fakeed(dyn, addr+2, 0, nextop)-addr + 1;
case 0x84:
case 0x85:
case 0x88:
case 0x89:
case 0x8A:
case 0x8B:
case 0x8C:
case 0x8D:
case 0x8E:
case 0x8F:
nextop = PK(1);
return fakeed(dyn, addr+2, 0, nextop)-addr;
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:
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
case 0x98:
case 0x99:
case 0x9B:
case 0x9C:
case 0x9D:
case 0x9E:
case 0x9F:
return 1;
case 0xA0:
case 0xA1:
case 0xA2:
case 0xA3:
return 5;
case 0xB0:
case 0xB1:
case 0xB2:
case 0xB3:
case 0xB4:
case 0xB5:
case 0xB6:
case 0xB7:
return 2;
case 0xB8:
case 0xB9:
case 0xBA:
case 0xBB:
case 0xBC:
case 0xBD:
case 0xBE:
case 0xBF:
return 5;
case 0xFF:
nextop = PK(1);
switch((nextop>>3)&7) {
case 0: // INC Ed
case 1: //DEC Ed
case 2: // CALL Ed
case 4: // JMP Ed
case 6: // Push Ed
return fakeed(dyn, addr+2, 0, nextop)-addr;
}
break;
default:
break;
}
return -1;
}
#undef PK
int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n)
{
int i = 0;
while(i<n) {
int j=next_instruction(dyn, addr+i);
if(j<=0) return 0;
i+=j;
}
return (i==n)?1:0;
}
uint32_t needed_flags(dynarec_arm_t *dyn, int ninst, uint32_t setf, int recurse)
{
if(recurse == 10)
return X_PEND;
if(ninst == dyn->size)
return X_PEND; // no more instructions, or too many jmp loop, stop
uint32_t needed = dyn->insts[ninst].x64.use_flags;
if(needed) {
setf &= ~needed;
if(!setf) // all flags already used, no need to continue
return needed;
}
if(!needed && !dyn->insts[ninst].x64.set_flags && !dyn->insts[ninst].x64.jmp_insts) {
int start = ninst;
int end = ninst;
while(end<dyn->size && !dyn->insts[end].x64.use_flags && !dyn->insts[end].x64.set_flags && !dyn->insts[end].x64.jmp_insts)
++end;
needed = needed_flags(dyn, end, setf, recurse);
for(int i=start; i<end; ++i)
dyn->insts[i].x64.need_flags = needed;
return needed;
}
if(dyn->insts[ninst].x64.set_flags && (dyn->insts[ninst].x64.state_flags!=SF_MAYSET)) {
if((setf & ~dyn->insts[ninst].x64.set_flags) == 0)
return needed; // all done, gives all the flags needed
setf |= dyn->insts[ninst].x64.set_flags; // add new flags to continue
}
int jinst = dyn->insts[ninst].x64.jmp_insts;
if(dyn->insts[ninst].x64.jmp) {
dyn->insts[ninst].x64.need_flags = (jinst==-1)?X_PEND:needed_flags(dyn, jinst, setf, recurse+1);
if(dyn->insts[ninst].x64.use_flags) // conditionnal jump
dyn->insts[ninst].x64.need_flags |= needed_flags(dyn, ninst+1, setf, recurse);
} else
dyn->insts[ninst].x64.need_flags = needed_flags(dyn, ninst+1, setf, recurse);
if(dyn->insts[ninst].x64.state_flags==SF_MAYSET)
needed |= dyn->insts[ninst].x64.need_flags;
else
needed |= (dyn->insts[ninst].x64.need_flags & ~dyn->insts[ninst].x64.set_flags);
if(needed == (X_PEND|X_ALL))
needed = X_ALL;
return needed;
}
instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x64_size, int arm_size)
{
// x64 instruction is <16 bytes
int toadd;
if(x64_size>arm_size)
toadd = 1 + x64_size/15;
else
toadd = 1 + arm_size/15;
if((*size)+toadd>(*cap)) {
*cap = (*size)+toadd;
insts = (instsize_t*)realloc(insts, (*cap)*sizeof(instsize_t));
}
while(toadd) {
if(x64_size>15)
insts[*size].x64 = 15;
else
insts[*size].x64 = x64_size;
x64_size -= insts[*size].x64;
if(arm_size>15)
insts[*size].nat = 15;
else
insts[*size].nat = arm_size;
arm_size -= insts[*size].nat;
++(*size);
--toadd;
}
return insts;
}
// add a value to table64 (if needed) and gives back the imm19 to use in LDR_literal
int Table64(dynarec_arm_t *dyn, uint64_t val)
{
// find the value if already present
int idx = -1;
for(int i=0; i<dyn->table64size && (idx==-1); ++i)
if(dyn->table64[i] == val)
idx = i;
// not found, add it
if(idx==-1) {
idx = dyn->table64size++;
dyn->table64 = (uint64_t*)realloc(dyn->table64, dyn->table64size * sizeof(uint64_t));
dyn->table64[idx] = val;
}
// calculate offset
int delta = dyn->tablestart + idx*sizeof(uint64_t) - (uintptr_t)dyn->block;
return delta;
}
void arm_pass0(dynarec_arm_t* dyn, uintptr_t addr);
void arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
void arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
void arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
void* FillBlock64(dynablock_t* block, uintptr_t addr) {
if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end)
return NULL;
// init the helper
dynarec_arm_t helper = {0};
helper.start = addr;
arm_pass0(&helper, addr);
if(!helper.size) {
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
block->done = 1;
return (void*)block;
}
helper.cap = helper.size+3; // needs epilog handling
helper.insts = (instruction_arm64_t*)calloc(helper.cap, sizeof(instruction_arm64_t));
// pass 1, addresses, x64 jump addresses, flags
arm_pass1(&helper, addr);
// calculate barriers
uintptr_t start = helper.insts[0].x64.addr;
uintptr_t end = helper.insts[helper.size].x64.addr+helper.insts[helper.size].x64.size;
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x64.jmp) {
uintptr_t j = helper.insts[i].x64.jmp;
if(j<start || j>=end)
helper.insts[i].x64.jmp_insts = -1;
else {
// find jump address instruction
int k=-1;
for(int i2=0; i2<helper.size && k==-1; ++i2) {
if(helper.insts[i2].x64.addr==j)
k=i2;
}
if(k!=-1) // -1 if not found, mmm, probably wrong, exit anyway
helper.insts[k].x64.barrier = 1;
helper.insts[i].x64.jmp_insts = k;
}
}
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x64.set_flags && !helper.insts[i].x64.need_flags) {
helper.insts[i].x64.need_flags = needed_flags(&helper, i+1, helper.insts[i].x64.set_flags, 0);
if((helper.insts[i].x64.need_flags&X_PEND) && (helper.insts[i].x64.state_flags==SF_MAYSET))
helper.insts[i].x64.need_flags = X_ALL;
}
// pass 2, instruction size
arm_pass2(&helper, addr);
// ok, now allocate mapped memory, with executable flag on
int sz = helper.arm_size + helper.table64size*sizeof(uint64_t);
void* p = (void*)AllocDynarecMap(block, sz);
if(p==NULL) {
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %d) failed, cancelling block\n", block, sz);
free(helper.insts);
free(helper.next);
free(helper.table64);
return NULL;
}
helper.block = p;
helper.arm_start = (uintptr_t)p;
helper.tablestart = helper.arm_start + helper.arm_size;
if(helper.sons_size) {
helper.sons_x64 = (uintptr_t*)calloc(helper.sons_size, sizeof(uintptr_t));
helper.sons_arm = (void**)calloc(helper.sons_size, sizeof(void*));
}
// pass 3, emit (log emit arm opcode)
if(box64_dynarec_dump) {
dynarec_log(LOG_NONE, "%s%04d|Emitting %d bytes for %d x64 bytes", (box64_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.arm_size, helper.isize);
printFunctionAddr(helper.start, " => ");
dynarec_log(LOG_NONE, "%s\n", (box64_dynarec_dump>1)?"\e[m":"");
}
helper.arm_size = 0;
int oldtable64size = helper.table64size;
arm_pass3(&helper, addr);
if(sz!=(helper.arm_size + helper.table64size*8)) {
printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size+helper.table64size*8);
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);
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, "Table64 \t%d -> %d\n", oldtable64size*8, helper.table64size*8);
printf_log(LOG_NONE, " ------------\n");
}
// add table64 if needed
if(helper.table64size) {
memcpy(p+helper.arm_size, helper.table64, helper.table64size*8);
}
// all done...
__clear_cache(p, p+sz); // need to clear the cache before execution...
// keep size of instructions for signal handling
{
size_t cap = 1;
for(int i=0; i<helper.size; ++i)
cap += 1 + ((helper.insts[i].x64.size>helper.insts[i].size)?helper.insts[i].x64.size:helper.insts[i].size)/15;
size_t size = 0;
block->instsize = (instsize_t*)calloc(cap, sizeof(instsize_t));
for(int i=0; i<helper.size; ++i)
block->instsize = addInst(block->instsize, &size, &cap, helper.insts[i].x64.size, helper.insts[i].size/4);
block->instsize = addInst(block->instsize, &size, &cap, 0, 0); // add a "end of block" mark, just in case
}
// ok, free the helper now
free(helper.insts);
free(helper.next);
free(helper.table64);
block->size = sz;
block->isize = helper.size;
block->block = p;
block->need_test = 0;
//block->x64_addr = (void*)start;
block->x64_size = end-start;
if(box64_dynarec_largest<block->x64_size)
box64_dynarec_largest = block->x64_size;
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
// fill sons if any
dynablock_t** sons = NULL;
int sons_size = 0;
if(helper.sons_size) {
sons = (dynablock_t**)calloc(helper.sons_size, sizeof(dynablock_t*));
for (int i=0; i<helper.sons_size; ++i) {
int created = 1;
dynablock_t *son = AddNewDynablock(block->parent, helper.sons_x64[i], &created);
if(created) { // avoid breaking a working block!
son->block = helper.sons_arm[i];
son->x64_addr = (void*)helper.sons_x64[i];
son->x64_size = end-helper.sons_x64[i];
if(!son->x64_size) {printf_log(LOG_NONE, "Warning, son with null x64 size! (@%p / ARM=%p)", son->x64_addr, son->block);}
son->father = block;
son->done = 1;
sons[sons_size++] = son;
if(!son->parent)
son->parent = block->parent;
}
}
if(sons_size) {
block->sons = sons;
block->sons_size = sons_size;
} else
free(sons);
}
free(helper.sons_x64);
free(helper.sons_arm);
block->done = 1;
return (void*)block;
}
+2105
View File
File diff suppressed because it is too large. Load diff
+862
View File
@@ -0,0 +1,862 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.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_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "my_cpuid.h"
#include "emu/x87emu_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#define GETG \
gd = ((nextop&0x38)>>3)+(rex.r<<3) \
#define GETGX(a) \
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
a = sse_get_reg(dyn, ninst, x1, gd)
#define GETGX_empty(a) \
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
a = sse_get_reg_empty(dyn, ninst, x1, gd)
#define GETEX(a, D) \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3)); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0); \
a = fpu_get_scratch(dyn); \
VLDR128_U12(a, ed, fixedaddress); \
}
#define GETGM(a) \
gd = ((nextop&0x38)>>3); \
a = mmx_get_reg(dyn, ninst, x1, gd)
#define GETEM(a, D) \
if(MODREG) { \
a = mmx_get_reg(dyn, ninst, x1, (nextop&7)); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0); \
a = fpu_get_scratch_double(dyn); \
VLD1_64(a, ed); \
}
#define PUTEM(a) \
if(!MODREG) { \
VST1_64(a, ed); \
}
uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop, u8;
int32_t i32, i32_, j32;
uint8_t gd, ed;
uint8_t wback, wb2;
uint8_t eb1, eb2;
int v0, v1;
int q0, q1;
int d0;
int s0;
int fixedaddress;
MAYUSE(s0);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(d0);
MAYUSE(eb2);
MAYUSE(eb1);
MAYUSE(wb2);
MAYUSE(j32);
MAYUSE(i32);
MAYUSE(u8);
#if STEP == 3
//static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
#endif
switch(opcode) {
case 0x10:
INST_NAME("MOVUPS Gx,Ex");
nextop = F8;
GETG;
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg(dyn, ninst, x1, ed);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
VLDR128_U12(v0, ed, fixedaddress); // no alignment issue with ARMv8 NEON :)
}
break;
case 0x11:
INST_NAME("MOVUPS Ex,Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
}
break;
case 0x12:
nextop = F8;
if(MODREG) {
INST_NAME("MOVHLPS Gx,Ex");
GETGX(v0);
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOVeD(v0, 0, v1, 1);
} else {
INST_NAME("MOVLPS Gx,Ex");
GETGX(v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
VLD1_64(v0, 0, ed);
}
break;
case 0x13:
nextop = F8;
INST_NAME("MOVLPS Ex,Gx");
GETGX(v0);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOVeD(v1, 0, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
VST1_64(v0, 0, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
}
break;
case 0x14:
INST_NAME("UNPCKLPS Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VZIP1Q_32(v0, v0, q0);
break;
case 0x15:
INST_NAME("UNPCKHPS Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VZIP2Q_32(v0, v0, q0);
break;
case 0x16:
nextop = F8;
if(MODREG) {
INST_NAME("MOVLHPS Gx,Ex");
GETGX(v0);
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOVeD(v0, 1, v1, 0);
} else {
INST_NAME("MOVHPS Gx,Ex");
GETGX(v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
VLD1_64(v0, 1, ed);
}
break;
case 0x17:
nextop = F8;
INST_NAME("MOVHPS Ex,Gx");
GETGX(v0);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOVeD(v1, 0, v0, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
VST1_64(v0, 1, ed);
}
break;
case 0x1F:
INST_NAME("NOP (multibyte)");
nextop = F8;
FAKEED;
break;
case 0x28:
INST_NAME("MOVAPS Gx,Ex");
nextop = F8;
GETG;
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg(dyn, ninst, x1, ed);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
}
break;
case 0x29:
INST_NAME("MOVAPS Ex,Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
}
break;
case 0x2E:
// no special check...
case 0x2F:
if(opcode==0x2F) {INST_NAME("COMISS Gx, Ex");} else {INST_NAME("UCOMISS Gx, Ex");}
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGX(v0);
if(MODREG) {
s0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
} else {
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
}
FCMPS(v0, s0);
FCOMI(x1, x2);
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
GETFLAGS; \
nextop=F8; \
GETGD; \
if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
CSELxw(gd, ed, gd, YES); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0); \
Bcond(NO, +8); \
LDRxw_U12(gd, ed, fixedaddress); \
if(!rex.w) {MOVw_REG(gd, gd);} \
}
GOCOND(0x40, "CMOV", "Gd, Ed");
#undef GO
case 0x54:
INST_NAME("ANDPS Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VANDQ(v0, v0, q0);
break;
case 0x55:
INST_NAME("ANDNPS Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VBICQ(v0, q0, v0);
break;
case 0x56:
INST_NAME("ORPS Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VORRQ(v0, v0, q0);
break;
case 0x57:
INST_NAME("XORPS Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VEORQ(v0, v0, q0);
break;
case 0x58:
INST_NAME("ADDPS Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VFADDQS(v0, v0, q0);
break;
case 0x59:
INST_NAME("MULPS Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VFMULQS(v0, v0, q0);
break;
case 0x5A:
INST_NAME("CVTPS2PD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(q1);
FCVTL(q1, q0);
break;
case 0x5B:
INST_NAME("CVTDQ2PS Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX_empty(q1);
SCVTQFS(q1, q0);
break;
case 0x5C:
INST_NAME("SUBPS Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VFSUBQS(v0, v0, q0);
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
i32_ = F32S; \
BARRIER(2); \
JUMP(addr+i32_);\
GETFLAGS; \
if(dyn->insts) { \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i32_, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
Bcond(YES, i32); \
} \
}
GOCOND(0x80, "J", "Id");
#undef GO
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
GETFLAGS; \
nextop=F8; \
CSETw(x3, YES); \
if(MODREG) { \
if(rex.rex) { \
eb1= xRAX+(nextop&7)+(rex.b<<3); \
eb2 = 0; \
} else { \
ed = (nextop&7); \
eb2 = (ed>>2)*8; \
eb1 = xRAX+(ed&3); \
} \
BFIx(eb1, x3, eb2, 8); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, 0, 0); \
STRB_U12(x3, ed, fixedaddress); \
}
GOCOND(0x90, "SET", "Eb");
#undef GO
case 0xA2:
INST_NAME("CPUID");
MOVx_REG(x1, xRAX);
CALL_(my_cpuid, -1, 0);
break;
case 0xA3:
INST_NAME("BT Ed, Gd");
SETFLAGS(X_CF, SF_SET);
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
UBFXw(x1, gd, 5+rex.w, 3-rex.w); // r1 = (gd>>5);
ADDx_REG_LSL(x3, wback, x1, 2); //(&ed)+=r1*4;
LDRxw_U12(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
if(rex.w) {
ANDx_mask(x2, gd, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
ANDw_mask(x2, gd, 0, 0b00100); //mask=0x00000001f
}
LSRxw_REG(x4, ed, x2);
BFIw(xFlags, x4, F_CF, 1);
break;
case 0xA5:
nextop = F8;
INST_NAME("SHLD Ed, Gd, CL");
UXTBw(x3, xRCX);
SETFLAGS(X_ALL, SF_SET);
GETEDW(x4, x1, 0);
GETGD;
MOVxw_REG(x2, gd);
CALL_(rex.w?((void*)shld64):((void*)shld32), ed, x4);
WBACK;
break;
case 0xAB:
INST_NAME("BTS Ed, Gd");
SETFLAGS(X_CF, SF_SET);
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
UBFXw(x1, gd, 5+rex.w, 3-rex.w); // r1 = (gd>>5);
ADDx_REG_LSL(x3, wback, x1, 2); //(&ed)+=r1*4;
LDRxw_U12(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
if(rex.w) {
ANDx_mask(x2, gd, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
ANDw_mask(x2, gd, 0, 0b00100); //mask=0x00000001f
}
LSRxw_REG(x4, ed, x2);
if(rex.w) {
ANDSx_mask(x4, x4, 1, 0, 0); //mask=1
} else {
ANDSw_mask(x4, x4, 0, 0); //mask=1
}
BFIw(xFlags, x4, F_CF, 1);
MOV32w(x4, 1);
LSLxw_REG(x4, x4, x2);
EORxw_REG(x4, ed, x4);
CSELxw(ed, ed, x4, cNE);
if(wback) {
STRxw_U12(ed, wback, fixedaddress);
}
break;
case 0xAD:
nextop = F8;
INST_NAME("SHRD Ed, Gd, CL");
SETFLAGS(X_ALL, SF_SET);
UXTBw(x3, xRCX);
GETEDW(x4, x1, 0);
GETGD;
MOVxw_REG(x2, gd);
CALL_(rex.w?((void*)shrd64):((void*)shrd32), ed, x4);
WBACK;
break;
case 0xAE:
nextop = F8;
if((nextop&0xF8)==0xE8) {
INST_NAME("LFENCE");
} else
if((nextop&0xF8)==0xF0) {
INST_NAME("MFENCE");
} else
if((nextop&0xF8)==0xF8) {
INST_NAME("SFENCE");
} else {
switch((nextop>>3)&7) {
case 0:
INST_NAME("FXSAVE Ed");
fpu_purgecache(dyn, ninst, x1, x2, x3);
if(MODREG) {
DEFAULT;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(rex.w?((void*)fpu_fxsave64):((void*)fpu_fxsave32), -1);
}
break;
case 1:
INST_NAME("FXRSTOR Ed");
fpu_purgecache(dyn, ninst, x1, x2, x3);
if(MODREG) {
DEFAULT;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(rex.w?((void*)fpu_fxrstor64):((void*)fpu_fxrstor32), -1);
}
break;
case 2:
INST_NAME("LDMXCSR Md");
GETED(0);
STRw_U12(ed, xEmu, offsetof(x64emu_t, mxcsr));
break;
case 3:
INST_NAME("STMXCSR Md");
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
LDRw_U12(ed, xEmu, offsetof(x64emu_t, mxcsr));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
LDRw_U12(x4, xEmu, offsetof(x64emu_t, mxcsr));
STRw_U12(x4, ed, fixedaddress);
}
break;
default:
DEFAULT;
}
}
break;
case 0xAF:
INST_NAME("IMUL Gd, Ed");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
GETGD;
GETED(0);
if(rex.w) {
// 64bits imul
UFLAG_IF {
SMULH(x3, gd, ed);
MULx(gd, gd, ed);
UFLAG_OP1(x3);
UFLAG_RES(gd);
UFLAG_DF(x3, d_imul64);
} else {
MULxw(gd, gd, ed);
}
} else {
// 32bits imul
UFLAG_IF {
SMULL(gd, gd, ed);
UFLAG_RES(gd);
LSRx(x3, gd, 32);
UFLAG_OP1(x3);
UFLAG_DF(x3, d_imul32);
MOVw_REG(gd, gd);
} else {
MULxw(gd, gd, ed);
}
}
break;
case 0xB3:
INST_NAME("BTR Ed, Gd");
SETFLAGS(X_CF, SF_SET);
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
UBFXw(x1, gd, 5+rex.w, 3-rex.w); // r1 = (gd>>5);
ADDx_REG_LSL(x3, wback, x1, 2); //(&ed)+=r1*4;
LDRxw_U12(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
if(rex.w) {
ANDx_mask(x2, gd, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
ANDw_mask(x2, gd, 0, 0b00100); //mask=0x00000001f
}
LSRxw_REG(x4, ed, x2);
if(rex.w) {
ANDSx_mask(x4, x4, 1, 0, 0); //mask=1
} else {
ANDSw_mask(x4, x4, 0, 0); //mask=1
}
BFIw(xFlags, x4, F_CF, 1);
MOV32w(x4, 1);
LSLxw_REG(x4, x4, x2);
EORxw_REG(x4, ed, x4);
CSELxw(ed, ed, x4, cEQ);
if(wback) {
STRxw_U12(ed, wback, fixedaddress);
}
break;
case 0xB6:
INST_NAME("MOVZX Gd, Eb");
nextop = F8;
GETGD;
if(MODREG) {
if(rex.rex) {
eb1 = xRAX+(nextop&7)+(rex.b<<3);
eb2 = 0; \
} else {
ed = (nextop&7);
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
}
UBFXxw(gd, eb1, eb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, 0, 0);
LDRB_U12(gd, ed, fixedaddress);
}
break;
case 0xB7:
INST_NAME("MOVZX Gd, Ew");
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
UBFXxw(gd, ed, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
LDRH_U12(gd, ed, fixedaddress);
}
break;
case 0xBA:
nextop = F8;
switch((nextop>>3)&7) {
case 4:
INST_NAME("BT Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
gd = x2;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
u8 = F8;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);
u8 = F8;
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
LDRxw_U12(x1, wback, fixedaddress);
ed = x1;
}
u8&=rex.w?0x3f:0x1f;
if(u8) {
LSRxw(x1, ed, u8);
ed = x1;
}
BFIw(xFlags, ed, F_CF, 1);
break;
case 5:
INST_NAME("BTS Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
u8 = F8;
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);
u8 = F8;
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
LDRxw_U12(x1, wback, fixedaddress);
ed = x1;
}
LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));
BFIw(xFlags, x4, F_CF, 1);
TBNZ_MARK3(x4, 0); // bit already set, jump to next instruction
MOV32w(x4, 1);
EORxw_REG_LSL(ed, ed, x4, u8&(rex.w?0x3f:0x1f));
if(wback) {
STRxw_U12(ed, wback, fixedaddress);
}
MARK3;
break;
case 6:
INST_NAME("BTR Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
u8 = F8;
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);
u8 = F8;
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
LDRxw_U12(x1, wback, fixedaddress);
ed = x1;
}
LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));
BFIw(xFlags, x4, F_CF, 1);
TBZ_MARK3(x4, 0); // bit already clear, jump to next instruction
//MOVW(x14, 1); // already 0x01
EORxw_REG_LSL(ed, ed, x4, u8&(rex.w?0x3f:0x1f));
if(wback) {
STRxw_U12(ed, wback, fixedaddress);
}
MARK3;
break;
case 7:
INST_NAME("BTC Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
u8 = F8;
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);
u8 = F8;
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
LDRxw_U12(x1, wback, fixedaddress);
ed = x1;
}
LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));
BFIw(xFlags, x4, F_CF, 1);
MOV32w(x4, 1);
EORxw_REG_LSL(ed, ed, x4, u8&(rex.w?0x3f:0x1f));
if(wback) {
STRxw_U12(ed, wback, fixedaddress);
}
MARK3;
break;
default:
DEFAULT;
}
break;
case 0xBB:
INST_NAME("BTC Ed, Gd");
SETFLAGS(X_CF, SF_SET);
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
UBFXw(x1, gd, 5+rex.w, 3-rex.w); // r1 = (gd>>5);
ADDx_REG_LSL(x3, wback, x1, 2); //(&ed)+=r1*4;
LDRxw_U12(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
if(rex.w) {
ANDx_mask(x2, gd, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
ANDw_mask(x2, gd, 0, 0b00100); //mask=0x00000001f
}
LSRxw_REG(x4, ed, x2);
if(rex.w) {
ANDx_mask(x4, x4, 1, 0, 0); //mask=1
} else {
ANDw_mask(x4, x4, 0, 0); //mask=1
}
BFIw(xFlags, x4, F_CF, 1);
MOV32w(x4, 1);
LSLxw_REG(x4, x4, x2);
EORxw_REG(ed, ed, x4);
if(wback) {
STRxw_U12(ed, wback, fixedaddress);
}
break;
case 0xBC:
INST_NAME("BSF Gd, Ed");
SETFLAGS(X_ZF, SF_SET);
nextop = F8;
GETED(0);
GETGD;
TSTxw_REG(ed, ed);
B_MARK(cEQ);
RBITxw(x1, ed); // reverse
CLZxw(gd, x1); // x2 gets leading 0 == BSF
MARK;
CSETw(x1, cEQ); //ZF not set
BFIw(xFlags, x1, F_ZF, 1);
SET_DFNONE(x1);
break;
case 0xBD:
INST_NAME("BSR Gd, Ed");
SETFLAGS(X_ZF, SF_SET);
nextop = F8;
GETED(0);
GETGD;
TSTxw_REG(ed, ed);
B_MARK(cEQ);
CLZxw(gd, ed); // x2 gets leading 0
SUBxw_U12(gd, gd, rex.w?63:31);
NEGxw_REG(gd, gd); // complement
MARK;
CSETw(x1, cEQ); //ZF not set
BFIw(xFlags, x1, F_ZF, 1);
SET_DFNONE(x1);
break;
case 0xBE:
INST_NAME("MOVSX Gd, Eb");
nextop = F8;
GETGD;
if(MODREG) {
if(rex.rex) {
wback = xRAX+(nextop&7)+(rex.b<<3);
wb2 = 0;
} else {
wback = (nextop&7);
wb2 = (wback>>2)*8;
wback = xRAX+(wback&3);
}
SBFXxw(gd, wback, wb2, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 0xfff, 0, rex, 0, 0);
LDRSBxw_U12(gd, ed, fixedaddress);
}
break;
case 0xBF:
INST_NAME("MOVSX Gd, Ew");
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
SXTHxw(gd, ed);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
LDRSHxw_U12(gd, ed, fixedaddress);
}
break;
case 0xC6:
INST_NAME("SHUFPS Gx, Ex, Ib");
nextop = F8;
GETGX(v0);
if(!MODREG)
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 1);
u8 = F8;
d0 = fpu_get_scratch(dyn);
// first two elements from Gx
for(int i=0; i<2; ++i) {
VMOVeS(d0, i, v0, (u8>>(i*2)&3));
}
// second two from Ex
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
for(int i=2; i<4; ++i) {
VMOVeS(d0, i, v1, (u8>>(i*2)&3));
}
} else {
for(int i=2; i<4; ++i) {
ADDx_U12(x2, ed, (u8>>(i*2)&3)*4);
VLD1_32(d0, i, x2);
}
}
VMOVQ(v0, d0);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF: /* BSWAP reg */
INST_NAME("BSWAP Reg");
gd = xRAX+(opcode&7)+(rex.b<<3);
REVxw(gd, gd);
break;
default:
DEFAULT;
}
return addr;
}
+186
View File
@@ -0,0 +1,186 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.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_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop;
int32_t j32;
uint8_t gd, ed;
uint8_t wback;
int64_t i64;
int fixedaddress;
MAYUSE(j32);
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
// REX prefix before the F0 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
switch(opcode) {
case 0x33:
INST_NAME("XOR Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_segdata(dyn, addr, ninst, x4, _FS);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x81:
case 0x83:
nextop = F8;
grab_segdata(dyn, addr, ninst, x6, _FS);
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {INST_NAME("ADD Ed, Id");} else {INST_NAME("ADD Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
GETEDO(x6, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5);
WBACKO(x6);
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("OR Ed, Id");} else {INST_NAME("OR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
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: //ADC
if(opcode==0x81) {INST_NAME("ADC Ed, Id");} else {INST_NAME("ADC Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
GETEDO(x6, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
emit_adc32(dyn, ninst, rex, ed, x5, x3, x4);
WBACKO(x6);
break;
case 3: //SBB
if(opcode==0x81) {INST_NAME("SBB Ed, Id");} else {INST_NAME("SBB Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
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);
WBACKO(x6);
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("AND Ed, Id");} else {INST_NAME("AND Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
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: //SUB
if(opcode==0x81) {INST_NAME("SUB Ed, Id");} else {INST_NAME("SUB Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
GETEDO(x6, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5);
WBACKO(x6);
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("XOR Ed, Id");} else {INST_NAME("XOR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
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: //CMP
if(opcode==0x81) {INST_NAME("CMP Ed, Id");} else {INST_NAME("CMP Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
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);
} else
emit_cmp32_0(dyn, ninst, rex, ed, x3, x4);
break;
}
break;
case 0x89:
INST_NAME("MOV FS:Ed, Gd");
grab_segdata(dyn, addr, ninst, x4, _FS);
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
STRxw_REG(gd, ed, x4);
}
break;
case 0x8B:
INST_NAME("MOV Gd, FS:Ed");
grab_segdata(dyn, addr, ninst, x4, _FS);
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
LDRxw_REG(gd, ed, x4);
}
break;
case 0xC7:
INST_NAME("MOV FS:Ed, Id");
grab_segdata(dyn, addr, ninst, x4, _FS);
nextop=F8;
if(MODREG) { // reg <= i32
i64 = F32S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV64xw(ed, i64);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 4);
i64 = F32S;
MOV64xw(x3, i64);
STRxw_REG(x3, ed, x4);
}
break;
default:
DEFAULT;
}
return addr;
}
+783
View File
@@ -0,0 +1,783 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.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_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop, u8;
int32_t i32, j32;
int16_t i16;
uint16_t u16;
uint8_t gd, ed;
uint8_t wback, wb1;
int fixedaddress;
MAYUSE(u16);
MAYUSE(u8);
MAYUSE(j32);
while((opcode==0x2E) || (opcode==0x66)) // ignoring CS: or multiple 0x66
opcode = F8;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
// REX prefix before the F0 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
switch(opcode) {
case 0x01:
INST_NAME("ADD Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_add16(dyn, ninst, x1, x2, x4, x5);
EWBACK;
break;
case 0x03:
INST_NAME("ADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_add16(dyn, ninst, x1, x2, x3, x4);
GWBACK;
break;
case 0x05:
INST_NAME("ADD AX, Iw");
SETFLAGS(X_ALL, SF_PENDING);
i32 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_add16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
break;
case 0x09:
INST_NAME("OR Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_or16(dyn, ninst, x1, x2, x4, x2);
EWBACK;
break;
case 0x0B:
INST_NAME("OR Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_or16(dyn, ninst, x1, x2, x4, x3);
GWBACK;
break;
case 0x0D:
INST_NAME("OR AX, Iw");
SETFLAGS(X_ALL, SF_SET);
i32 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_or16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
break;
case 0x0F:
addr = dynarec64_660F(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0x11:
INST_NAME("ADC Ew, Gw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_adc16(dyn, ninst, x1, x2, x4, x5);
EWBACK;
break;
case 0x13:
INST_NAME("ADC Gw, Ew");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_adc16(dyn, ninst, x1, x2, x4, x3);
GWBACK;
break;
case 0x15:
INST_NAME("ADC AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
i32 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_adc16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
break;
case 0x19:
INST_NAME("SBB Ew, Gw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_sbb16(dyn, ninst, x1, x2, x4, x5);
EWBACK;
break;
case 0x1B:
INST_NAME("SBB Gw, Ew");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_sbb16(dyn, ninst, x1, x2, x4, x3);
GWBACK;
break;
case 0x1D:
INST_NAME("SBB AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
i16 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i16);
emit_sbb16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
break;
case 0x21:
INST_NAME("AND Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_and16(dyn, ninst, x1, x2, x4, x5);
EWBACK;
break;
case 0x23:
INST_NAME("AND Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_and16(dyn, ninst, x1, x2, x3, x4);
GWBACK;
break;
case 0x25:
INST_NAME("AND AX, Iw");
SETFLAGS(X_ALL, SF_SET);
i32 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_and16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
break;
case 0x29:
INST_NAME("SUB Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_sub16(dyn, ninst, x1, x2, x4, x5);
EWBACK;
break;
case 0x2B:
INST_NAME("SUB Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_sub16(dyn, ninst, x1, x2, x3, x4);
GWBACK;
break;
case 0x2D:
INST_NAME("SUB AX, Iw");
SETFLAGS(X_ALL, SF_SET);
i32 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_sub16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
break;
case 0x31:
INST_NAME("XOR Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_xor16(dyn, ninst, x1, x2, x4, x5);
EWBACK;
break;
case 0x33:
INST_NAME("XOR Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_xor16(dyn, ninst, x1, x2, x3, x4);
GWBACK;
break;
case 0x35:
INST_NAME("XOR AX, Iw");
SETFLAGS(X_ALL, SF_SET);
i32 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_xor16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
break;
case 0x39:
INST_NAME("CMP Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0x3B:
INST_NAME("CMP Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0x3D:
INST_NAME("CMP AX, Iw");
SETFLAGS(X_ALL, SF_SET);
i32 = F16;
UXTHw(x1, xRAX);
if(i32) {
MOV32w(x2, i32);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
} else {
emit_cmp16_0(dyn, ninst, x1, x3, x4);
}
break;
case 0x69:
INST_NAME("IMUL Gw,Ew,Iw");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
UFLAG_DF(x1, d_imul16);
GETSEW(x1, 2);
i32 = F16S;
MOV32w(x2, i32);
MULw(x2, x2, x1);
UFLAG_RES(x2);
gd=x2;
GWBACK;
break;
case 0x6B:
INST_NAME("IMUL Gw,Ew,Ib");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
UFLAG_DF(x1, d_imul16);
GETSEW(x1, 1);
i32 = F8S;
MOV32w(x2, i32);
MULw(x2, x2, x1);
UFLAG_RES(x2);
gd=x2;
GWBACK;
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);
GETEW(x1, (opcode==81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(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);
GETEW(x1, (opcode==81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
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);
GETEW(x1, (opcode==81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(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);
GETEW(x1, (opcode==81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(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);
GETEW(x1, (opcode==81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
emit_and16(dyn, ninst, x1, x5, 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);
GETEW(x1, (opcode==81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(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);
GETEW(x1, (opcode==81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
emit_xor16(dyn, ninst, x1, x5, 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);
GETEW(x1, (opcode==81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
MOV32w(x2, i16);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
} else
emit_cmp16_0(dyn, ninst, x1, x3, x4);
break;
}
break;
case 0x85:
INST_NAME("TEST Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETEW(x1, 0);
GETGW(x2);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
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);
if(ed!=gd) {
BFIx(ed, gd, 0, 16);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
STRH_U12(gd, ed, fixedaddress);
}
break;
case 0x8B:
INST_NAME("MOV Gw, Ew");
nextop = F8;
GETGD; // don't need GETGW neither
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
if(ed!=gd) {
BFIx(gd, ed, 0, 16);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
LDRH_U12(x1, ed, fixedaddress);
BFIx(gd, x1, 0, 16);
}
break;
case 0x90:
INST_NAME("NOP");
break;
case 0xA5:
if(rep) {
INST_NAME("REP MOVSW");
CBZx_NEXT(xRCX);
TBNZ_MARK2(xFlags, F_DF);
MARK; // Part with DF==0
LDRH_S9_postindex(x1, xRSI, 2);
STRH_S9_postindex(x1, xRDI, 2);
SUBx_U12(xRCX, xRCX, 1);
CBNZx_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
LDRH_S9_postindex(x1, xRSI, -2);
STRH_S9_postindex(x1, xRDI, -2);
SUBx_U12(xRCX, xRCX, 1);
CBNZx_MARK2(xRCX);
// done
} else {
INST_NAME("MOVSW");
GETDIR(x3, 2);
LDRH_U12(x1, xRSI, 0);
STRH_U12(x1, xRDI, 0);
ADDx_REG(xRSI, xRSI, x3);
ADDx_REG(xRDI, xRDI, x3);
}
break;
case 0xA9:
INST_NAME("TEST AX,Iw");
SETFLAGS(X_ALL, SF_SET);
u16 = F16;
MOV32w(x2, u16);
UBFXx(x1, xRAX, 0, 16);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0xB8:
case 0xB9:
case 0xBA:
case 0xBB:
case 0xBC:
case 0xBD:
case 0xBE:
case 0xBF:
INST_NAME("MOV Reg16, Iw");
u16 = F16;
MOV32w(x1, u16);
gd = xRAX+(opcode&7)+(rex.b<<3);
BFIx(gd, x1, 0, 16);
break;
case 0xC1:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ew, Ib");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(rol16, x1, x3);
EWBACK;
break;
case 1:
INST_NAME("ROR Ew, Ib");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(ror16, x1, x3);
EWBACK;
break;
case 2:
INST_NAME("RCL Ew, Ib");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(rcl16, x1, x3);
EWBACK;
break;
case 3:
INST_NAME("RCR Ew, Ib");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(rcr16, x1, x3);
EWBACK;
break;
case 4:
case 6:
INST_NAME("SHL Ew, Ib");
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, (u8&0x1f));
UFLAG_OP12(ed, x2)
LSLw_REG(ed, ed, x2);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl16);
break;
case 5:
INST_NAME("SHR Ed, Ib");
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, (u8&0x1f));
UFLAG_OP12(ed, x2)
LSRw_REG(ed, ed, x2);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr16);
break;
case 7:
INST_NAME("SAR Ed, Ib");
SETFLAGS(X_ALL, SF_PENDING);
GETSEW(x1, 0);
u8 = F8;
MOV32w(x2, (u8&0x1f));
UFLAG_OP12(ed, x2)
ASRw_REG(ed, ed, x2);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar16);
break;
}
break;
case 0xC7:
INST_NAME("MOV Ew, Iw");
nextop = F8;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
u16 = F16;
MOV32w(x1, u16);
BFIx(ed, x1, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 2);
u16 = F16;
MOV32w(x1, u16);
STRH_U12(x1, ed, fixedaddress);
}
break;
case 0xD1:
case 0xD3:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
if(opcode==0xD1) {
INST_NAME("ROL Ew, 1");
MOV32w(x2, 1);
} else {
INST_NAME("ROL Ew, CL");
ANDSw_mask(x2, xRCX, 0, 0b00100);
}
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 0);
CALL_(rol16, x1, x3);
EWBACK;
break;
case 1:
if(opcode==0xD1) {
INST_NAME("ROR Ew, 1");
MOV32w(x2, 1);
} else {
INST_NAME("ROR Ew, CL");
ANDSw_mask(x2, xRCX, 0, 0b00100);
}
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 0);
CALL_(ror16, x1, x3);
EWBACK;
break;
case 2:
if(opcode==0xD1) {INST_NAME("RCL Ew, 1"); } else { INST_NAME("RCL Ew, CL");}
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDSw_mask(x2, xRCX, 0, 0b00100);}
GETEW(x1, 0);
CALL_(rcl16, x1, x3);
EWBACK;
break;
case 3:
if(opcode==0xD1) {INST_NAME("RCR Ew, 1");} else {INST_NAME("RCR Ew, CL");}
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDSw_mask(x2, xRCX, 0, 0b00100);}
GETEW(x1, 0);
CALL_(rcr16, x1, x3);
EWBACK;
break;
case 4:
case 6:
if(opcode==0xD1) {
INST_NAME("SHL Ew, 1");
MOV32w(x4, 1);
} else {
INST_NAME("SHL Ew, CL");
ANDSw_mask(x4, xRCX, 0, 0b00100);
}
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 0);
UFLAG_OP12(ed, x4)
LSLw_REG(ed, ed, x4);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl16);
break;
case 5:
if(opcode==0xD1) {
INST_NAME("SHR Ew, 1");
MOV32w(x4, 1);
} else {
INST_NAME("SHR Ew, CL");
ANDSw_mask(x4, xRCX, 0, 0b00100);
}
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 0);
UFLAG_OP12(ed, x4)
LSRw_REG(ed, ed, x4);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr16);
break;
case 7:
if(opcode==0xD1) {
INST_NAME("SAR Ew, 1");
MOV32w(x4, 1);
} else {
INST_NAME("SAR Ew, CL");
ANDSw_mask(x4, xRCX, 0, 0b00100);
}
SETFLAGS(X_ALL, SF_PENDING);
GETSEW(x1, 0);
UFLAG_OP12(ed, x4)
ASRw_REG(ed, ed, x4);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar16);
break;
}
break;
case 0xF7:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
case 1:
INST_NAME("TEST Ew, Iw");
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, 2);
u16 = F16;
MOV32w(x2, u16);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 2:
INST_NAME("NOT Ew");
GETEW(x1, 0);
MVNw_REG(ed, ed);
EWBACK;
break;
case 3:
INST_NAME("NEG Ew");
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, 0);
emit_neg16(dyn, ninst, ed, x2, x4);
EWBACK;
break;
case 4:
INST_NAME("MUL AX, Ew");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x1, d_mul16);
GETEW(x1, 0);
UXTHw(x2, xRAX);
MULw(x1, x2, x1);
UFLAG_RES(x1);
BFIx(xRAX, x1, 0, 16);
BFXILx(xRDX, x1, 16, 16);
break;
case 5:
INST_NAME("IMUL AX, Ew");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x1, d_imul16);
GETSEW(x1, 0);
SXTHw(x2, xRAX);
MULw(x1, x2, x1);
UFLAG_RES(x1);
BFIx(xRAX, x1, 0, 16);
BFXILx(xRDX, x1, 16, 16);
break;
case 6:
INST_NAME("DIV Ew");
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, 0);
CALL(div16, -1);
break;
case 7:
INST_NAME("IDIV Ew");
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, 0);
CALL(idiv16, -1);
break;
}
break;
case 0xFF:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
INST_NAME("INC Ew");
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_SET);
GETEW(x1, 0);
emit_dec16(dyn, ninst, x1, x2, x4);
EWBACK;
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
+928
View File
@@ -0,0 +1,928 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.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_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
// Get EX as a quad
#define GETEX(a, D) \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3)); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, D); \
a = fpu_get_scratch(dyn); \
VLDR128_U12(a, ed, fixedaddress); \
}
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
#define GETGX(a) \
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
a = sse_get_reg(dyn, ninst, x1, gd)
#define GETGX_empty(a) \
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
a = sse_get_reg_empty(dyn, ninst, x1, gd)
uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop, u8;
int32_t i32, j32;
uint8_t gd, ed;
uint8_t wback, wb1;
uint8_t eb1, eb2;
int v0, v1;
int q0, q1;
int d0;
int fixedaddress;
MAYUSE(d0);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(j32);
#if 0//STEP == 3
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
#endif
switch(opcode) {
case 0x12:
INST_NAME("MOVLPD Gx, Eq");
nextop = F8;
GETGX(v0);
if(MODREG) {
// access register instead of memory is bad opcode!
DEFAULT;
return addr;
}
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
VLD1_64(v0, 0, ed);
break;
case 0x13:
INST_NAME("MOVLPD Eq, Gx");
nextop = F8;
GETGX(v0);
if(MODREG) {
// access register instead of memory is bad opcode!
DEFAULT;
return addr;
}
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
VST1_64(v0, 0, ed);
break;
case 0x14:
INST_NAME("UNPCKLPD Gx, Ex");
nextop = F8;
GETGX(v0);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOVeD(v0, 1, v1, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
VLD1_64(v0, 1, ed);
}
break;
case 0x15:
INST_NAME("UNPCKHPD Gx, Ex");
nextop = F8;
GETGX(v0);
VMOVeD(v0, 0, v0, 1);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOVeD(v0, 1, v1, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
v1 = fpu_get_scratch(dyn);
ADDx_U12(ed, ed, 8);
VLD1_64(v0, 1, ed);
}
break;
case 0x1F:
INST_NAME("NOP (multibyte)");
nextop = F8;
FAKEED;
break;
case 0x28:
INST_NAME("MOVAPD Gx,Ex");
nextop = F8;
GETG;
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg(dyn, ninst, x1, ed);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
}
break;
case 0x29:
INST_NAME("MOVAPD Ex,Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
}
break;
case 0x2E:
// no special check...
case 0x2F:
if(opcode==0x2F) {INST_NAME("COMISD Gx, Ex");} else {INST_NAME("UCOMISD Gx, Ex");}
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
FCMPD(v0, q0);
FCOMI(x1, x2);
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
GETFLAGS; \
nextop=F8; \
GETGD; \
if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0); \
LDRH_U12(x1, ed, fixedaddress); \
ed = x1; \
} \
Bcond(NO, +8); \
BFIx(gd, ed, 0, 16);
GOCOND(0x40, "CMOV", "Gw, Ew");
#undef GO
case 0x54:
INST_NAME("ANDPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VANDQ(v0, v0, q0);
break;
case 0x55:
INST_NAME("ANDNPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VBICQ(v0, q0, v0);
break;
case 0x56:
INST_NAME("ORPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VORRQ(v0, v0, q0);
break;
case 0x57:
INST_NAME("XORPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VEORQ(v0, v0, q0);
break;
case 0x5A:
INST_NAME("CVTPD2PS Gx, Ex");
nextop = F8;
GETEX(v1, 0);
GETGX_empty(v0);
FCVTXN(v0, v1);
break;
case 0x5B:
INST_NAME("CVTPS2DQ Gx, Ex");
nextop = F8;
GETEX(v1, 0);
GETGX_empty(v0);
#ifdef PRECISE_CVT
LDRH_U12(x1, xEmu, offsetof(x64emu_t, mxcsr));
UBFXx(x1, x1, 13, 2); // extract round requested
LSLx_REG(x1, x1, 3);
ADDx_U12(x1, x1, 8); // add the actual add+jump opcodes
// Construct a "switch case", with each case 2 instructions, so 8 bytes
BL(+4); // Branch with Link to next, so LR gets next PC address
ADDx_REG(xLR, xLR, x1);
B(xLR); // could use RET, but it's not really one
VFCVTNSQS(v0, v1); // 0: Nearest (even)
B_NEXT_nocond;
VFCVTMSQS(v0, v1); // 1: Toward -inf
B_NEXT_nocond;
VFCVTPSQS(v0, v1); // 2: Toward +inf
B_NEXT_nocond;
VFCVTZSQS(v0, v1); // 3: Toward 0
#else
VFCVTNSQS(v0, v1);
#endif
break;
case 0x60:
INST_NAME("PUNPCKLBW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VZIP1Q_8(v0, v0, q0);
break;
case 0x61:
INST_NAME("PUNPCKLWD Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VZIP1Q_16(v0, v0, q0);
break;
case 0x62:
INST_NAME("PUNPCKLDQ Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VZIP1Q_32(v0, v0, q0);
break;
case 0x64:
INST_NAME("PCMPGTB Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
VCMGTQ_8(v0, v0, v1);
break;
case 0x65:
INST_NAME("PCMPGTW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
VCMGTQ_16(v0, v0, v1);
break;
case 0x66:
INST_NAME("PCMPGTD Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
VCMGTQ_32(v0, v0, v1);
break;
case 0x68:
INST_NAME("PUNPCKHBW Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 1);
VZIP2Q_8(q0, q0, q1);
break;
case 0x69:
INST_NAME("PUNPCKHWD Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 1);
VZIP2Q_16(q0, q0, q1);
break;
case 0x6A:
INST_NAME("PUNPCKHDQ Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 1);
VZIP2Q_32(q0, q0, q1);
break;
case 0x6B:
INST_NAME("PACKSSDW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
SQXTN_16(v0, v0);
if(v0==v1) {
VMOVeD(v0, 1, v0, 0);
} else {
SQXTN2_16(v0, v1);
}
break;
case 0x6C:
INST_NAME("PUNPCKLQDQ Gx,Ex");
nextop = F8;
GETGX(v0);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOVeD(v0, 1, v1, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
VLD1_64(v0, 1, ed);
}
break;
case 0x6E:
INST_NAME("MOVD Gx, Ed");
nextop = F8;
GETG;
GETED(0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if(rex.w) {
FMOVDx(v0, ed);
} else {
VEORQ(v0, v0, v0); // RAZ vector
VMOVQSfrom(v0, 0, ed);
}
break;
case 0x6F:
INST_NAME("MOVDQA 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));
VMOVQ(v0, v1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
}
break;
case 0x70:
INST_NAME("PSHUFD Gx,Ex,Ib");
nextop = F8;
GETG;
i32 = -1;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if(MODREG) {
u8 = F8;
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
if(u8==0x4E) {
if(v0==v1) {
VSWP(v0, v0+1);
} else {
VMOVeD(v0, 0, v1, 1);
VMOVeD(v0, 1, v1, 0);
}
} else {
uint32_t swp[4] = {
(0)|(1<<8)|(2<<16)|(3<<24),
(4)|(5<<8)|(6<<16)|(7<<24),
(8)|(9<<8)|(10<<16)|(11<<24),
(12)|(13<<8)|(14<<16)|(15<<24)
};
d0 = fpu_get_scratch(dyn);
if(v0==v1) {
q1 = fpu_get_scratch(dyn);
VMOVQ(q1, v1);
} else
q1 = v1;
MOV32w(x2, swp[(u8>>(0*2))&3]);
MOV32w(x3, swp[(u8>>(1*2))&3]);
VMOVQSfrom(d0, 0, x2);
VMOVQSfrom(d0, 1, x3);
MOV32w(x2, swp[(u8>>(2*2))&3]);
MOV32w(x3, swp[(u8>>(3*2))&3]);
VMOVQSfrom(d0, 2, x2);
VMOVQSfrom(d0, 3, x3);
VTBLQ1_8(v0, v1, d0);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 1);
u8 = F8;
if (u8) {
for (int i=0; i<4; ++i) {
int32_t idx = (u8>>(i*2))&3;
if(idx!=i32) {
ADDx_U12(x2, ed, idx*4);
i32 = idx;
}
VLD1_32(v0, i, x2);
}
} else {
VLD1R_32(v0, ed);
}
}
break;
case 0x71:
nextop = F8;
switch((nextop>>3)&7) {
case 2:
INST_NAME("PSRLW Ex, Ib");
GETEX(q0, 1);
u8 = F8;
if(u8) {
if (u8>15) {
VEORQ(q0, q0, q0);
} else if(u8) {
VSHRQ_16(q0, q0, u8);
}
if(!MODREG) {
VSTR128_U12(q0, ed, fixedaddress);
}
}
break;
case 4:
INST_NAME("PSRAW Ex, Ib");
GETEX(q0, 1);
u8 = F8;
if(u8>15) u8=15;
if(u8) {
VSSHRQ_16(q0, q0, u8);
}
if(!MODREG) {
VSTR128_U12(q0, ed, fixedaddress);
}
break;
case 6:
INST_NAME("PSLLW Ex, Ib");
GETEX(q0, 1);
u8 = F8;
if(u8) {
if (u8>15) {
VEORQ(q0, q0, q0);
} else {
VSHLQ_16(q0, q0, u8);
}
if(!MODREG) {
VSTR128_U12(q0, ed, fixedaddress);
}
}
break;
default:
*ok = 0;
DEFAULT;
}
break;
case 0x72:
nextop = F8;
switch((nextop>>3)&7) {
case 2:
INST_NAME("PSRLD Ex, Ib");
GETEX(q0, 1);
u8 = F8;
if(u8) {
if (u8>31) {
VEORQ(q0, q0, q0);
} else if(u8) {
VSHRQ_32(q0, q0, u8);
}
if(!MODREG) {
VSTR128_U12(q0, ed, fixedaddress);
}
}
break;
case 4:
INST_NAME("PSRAD Ex, Ib");
GETEX(q0, 1);
u8 = F8;
if(u8>31) u8=31;
if(u8) {
VSSHRQ_32(q0, q0, u8);
}
if(!MODREG) {
VSTR128_U12(q0, ed, fixedaddress);
}
break;
case 6:
INST_NAME("PSLLD Ex, Ib");
GETEX(q0, 1);
u8 = F8;
if(u8) {
if (u8>31) {
VEORQ(q0, q0, q0);
} else {
VSHLQ_32(q0, q0, u8);
}
if(!MODREG) {
VSTR128_U12(q0, ed, fixedaddress);
}
}
break;
default:
DEFAULT;
}
break;
case 0x73:
nextop = F8;
switch((nextop>>3)&7) {
case 2:
INST_NAME("PSRLQ Ex, Ib");
GETEX(q0, 1);
u8 = F8;
if(u8) {
if (u8>63) {
VEORQ(q0, q0, q0);
} else if(u8) {
VSHRQ_64(q0, q0, u8);
}
if(!MODREG) {
VSTR128_U12(q0, ed, fixedaddress);
}
}
break;
case 3:
INST_NAME("PSRLDQ Ex, Ib");
GETEX(q0, 1);
u8 = F8;
if(u8) {
if(u8>15) {
VEORQ(q0, q0, q0);
} else {
q1 = fpu_get_scratch(dyn);
VEORQ(q1, q1, q1);
VEXTQ_8(q0, q0, q1, u8);
}
if(!MODREG) {
VSTR128_U12(q0, ed, fixedaddress);
}
}
break;
case 6:
INST_NAME("PSLLQ Ex, Ib");
GETEX(q0, 1);
u8 = F8;
if(u8) {
if (u8>63) {
VEORQ(q0, q0, q0);
} else {
VSHLQ_64(q0, q0, u8);
}
if(!MODREG) {
VSTR128_U12(q0, ed, fixedaddress);
}
}
break;
case 7:
INST_NAME("PSLLDQ Ex, Ib");
GETEX(q0, 1);
u8 = F8;
if(u8) {
if(u8>15) {
VEORQ(q0, q0, q0);
} else if(u8>0) {
q1 = fpu_get_scratch(dyn);
VEORQ(q1, q1, q1);
VEXTQ_8(q0, q1, q0, 16-u8);
}
if(!MODREG) {
VSTR128_U12(q0, ed, fixedaddress);
}
}
break;
default:
DEFAULT;
}
break;
case 0x7E:
INST_NAME("MOVD Ed,Gx");
nextop = F8;
GETGX(v0);
if(rex.w) {
if(MODREG) {
ed = xRAX + (nextop&7) + (rex.b<<3);
VMOVQDto(ed, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
}
} else {
if(MODREG) {
ed = xRAX + (nextop&7) + (rex.b<<3);
VMOVSto(ed, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VSTR32_U12(v0, ed, fixedaddress);
}
}
break;
case 0x7F:
INST_NAME("MOVDQA Ex,Gx");
nextop = F8;
GETGX(v0);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
}
break;
case 0xA3:
INST_NAME("BT Ew, Gw");
SETFLAGS(X_CF, SF_SET);
nextop = F8;
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
GETEW(x4, 0);
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
LSRw_REG(x1, ed, x2);
BFIw(xFlags, x1, F_CF, 1);
break;
case 0xA4:
case 0xA5:
nextop = F8;
if(opcode==0xA4) {
INST_NAME("SHLD Ew, Gw, Ib");
} else {
INST_NAME("SHLD Ew, Gw, CL");
UXTBw(x3, xRCX);
}
SETFLAGS(X_ALL, SF_SET);
GETEWW(x4, x1, (opcode==0xA4)?1:0);
GETGW(x2);
if(opcode==0xA4) {
u8 = F8;
MOV32w(x3, u8);
}
CALL_(shld16, x1, wback);
EWBACKW(x1);
break;
case 0xAB:
INST_NAME("BTS Ew, Gw");
SETFLAGS(X_CF, SF_SET);
nextop = F8;
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
GETEW(x4, 0);
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
LSRw_REG(x1, ed, x2);
BFIw(xFlags, x1, F_CF, 1);
ANDSw_mask(x1, x1, 0, 0); //mask=1
B_NEXT(cNE);
MOV32w(x1, 1);
LSLxw_REG(x1, x1, x2);
EORxw_REG(ed, ed, x1);
EWBACK;
break;
case 0xAC:
case 0xAD:
nextop = F8;
if(opcode==0xAC) {
INST_NAME("SHRD Ew, Gw, Ib");
} else {
INST_NAME("SHRD Ew, Gw, CL");
UXTBw(x3, xRCX);
}
SETFLAGS(X_ALL, SF_SET);
GETEWW(x4, x1, (opcode==0xAC)?1:0);
GETGW(x2);
if(opcode==0xAC) {
u8 = F8;
MOV32w(x3, u8);
}
CALL_(shrd16, x1, wback);
EWBACKW(x1);
break;
case 0xAF:
INST_NAME("IMUL Gw,Ew");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
UFLAG_DF(x1, d_imul16);
GETSEW(x1, 0);
GETSGW(x2);
MULw(x2, x2, x1);
UFLAG_RES(x2);
GWBACK;
break;
case 0xB3:
INST_NAME("BTR Ew, Gw");
SETFLAGS(X_CF, SF_SET);
nextop = F8;
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
GETEW(x4, 0);
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
LSRw_REG(x1, ed, x2);
BFIw(xFlags, x1, F_CF, 1);
ANDSw_mask(x1, x1, 0, 0); //mask=1
B_NEXT(cEQ);
MOV32w(x1, 1);
LSLxw_REG(x1, x1, x2);
EORxw_REG(ed, ed, x1);
EWBACK;
break;
case 0xBB:
INST_NAME("BTC Ew, Gw");
SETFLAGS(X_CF, SF_SET);
nextop = F8;
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
GETEW(x4, 0);
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
LSRw_REG(x1, ed, x2);
BFIw(xFlags, x1, F_CF, 1);
ANDw_mask(x1, x1, 0, 0); //mask=1
MOV32w(x1, 1);
LSLxw_REG(x1, x1, x2);
EORxw_REG(ed, ed, x1);
EWBACK;
break;
case 0xBC:
INST_NAME("BSF Ew,Gw");
SETFLAGS(X_ZF, SF_SET);
nextop = F8;
GETGD;
GETEW(x1, 0); // Get EW
TSTw_REG(x1, x1);
B_MARK(cEQ);
RBITw(x1, x1); // reverse
CLZw(x2, x1); // x2 gets leading 0 == BSF
BFIw(gd, x2, 0, 16);
MARK;
CSETw(x1, cEQ); //ZF not set
BFIw(xFlags, x1, F_ZF, 1);
SET_DFNONE(x1);
break;
case 0xBD:
INST_NAME("BSR Ew,Gw");
SETFLAGS(X_ZF, SF_SET);
nextop = F8;
GETGD;
GETEW(x1, 0); // Get EW
TSTw_REG(x1, x1); // Don't use CBZ here, as the flag is reused later
B_MARK(cEQ);
LSLw(x1, x1, 16); // put bits on top
CLZw(x2, x1); // x2 gets leading 0
SUBw_U12(x2, x2, 15);
NEGw_REG(x2, x2); // complement
BFIx(gd, x2, 0, 16);
MARK;
CSETw(x1, cEQ); //ZF not set
BFIw(xFlags, x1, F_ZF, 1);
SET_DFNONE(x1);
break;
case 0xBE:
INST_NAME("MOVSX Gw, Eb");
nextop = F8;
GETGD;
if(MODREG) {
if(rex.rex) {
ed = xRAX+(nextop&7)+(rex.b<<3);
eb1=ed;
eb2=0;
} else {
ed = (nextop&7);
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
}
SBFXw(x1, eb1, eb2, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, 0, 0);
LDRSBw_U12(x1, ed, fixedaddress);
}
BFIx(gd, x1, 0, 16);
break;
case 0xD4:
INST_NAME("PADDQ Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VADDQ_64(v0, v0, q0);
break;
case 0xD6:
INST_NAME("MOVQ Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
FMOVD(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
}
break;
case 0xDB:
INST_NAME("PAND Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VANDQ(v0, v0, q0);
break;
case 0xDF:
INST_NAME("PANDN Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VBICQ(v0, q0, v0);
break;
case 0xEB:
INST_NAME("POR Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VORRQ(v0, v0, q0);
break;
case 0xEF:
INST_NAME("PXOR Gx,Ex");
nextop = F8;
GETG;
if(MODREG && ((nextop&7)+(rex.b<<3)==gd)) {
// special case for PXOR Gx, Gx
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VEORQ(q0, q0, q0);
} else {
q0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(q1, 0);
VEORQ(q0, q0, q1);
}
break;
case 0xF4:
INST_NAME("PMULUDQ Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
q0 = fpu_get_scratch(dyn);
VUZP1Q_32(q0, v0, v0); //A3 A2 A1 A0 -> A3 A1 A2 A0
if(MODREG) {
q1 = fpu_get_scratch(dyn);
} else {
q1 = v1;
}
VUZP1Q_32(q1, v1, v1);
VUMULL_32(v0, q0, q1);
break;
case 0xF8:
INST_NAME("PSUBB Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VSUBQ_8(v0, v0, q0);
break;
case 0xF9:
INST_NAME("PSUBW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VSUBQ_16(v0, v0, q0);
break;
case 0xFA:
INST_NAME("PSUBD Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VSUBQ_32(v0, v0, q0);
break;
case 0xFB:
INST_NAME("PSUBQ Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VSUBQ_64(v0, v0, q0);
break;
case 0xFC:
INST_NAME("PADDB Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VADDQ_8(v0, v0, q0);
break;
case 0xFD:
INST_NAME("PADDW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VADDQ_16(v0, v0, q0);
break;
case 0xFE:
INST_NAME("PADDD Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VADDQ_32(v0, v0, q0);
break;
default:
DEFAULT;
}
return addr;
}
+102
View File
@@ -0,0 +1,102 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.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_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
int8_t i8;
int32_t i32, j32;
MAYUSE(j32);
MAYUSE(i32);
// REX prefix before the 67 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
switch(opcode) {
#define GO(NO, YES) \
BARRIER(2); \
JUMP(addr+i8);\
if(dyn->insts) { \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
Bcond(YES, i32); \
} \
}
case 0xE0:
INST_NAME("LOOPNZ (32bits)");
READFLAGS(X_ZF);
i8 = F8S;
MOVw_REG(x1, xRCX);
SUBSw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 32);
B_NEXT(cEQ); // ECX is 0, no LOOP
TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
GO(cNE, cEQ);
break;
case 0xE1:
INST_NAME("LOOPZ (32bits)");
READFLAGS(X_ZF);
i8 = F8S;
MOVw_REG(x1, xRCX);
SUBSw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 32);
B_NEXT(cEQ); // ECX is 0, no LOOP
TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
GO(cEQ, cNE);
break;
case 0xE2:
INST_NAME("LOOP (32bits)");
i8 = F8S;
MOVw_REG(x1, xRCX);
SUBSw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 32);
GO(cEQ, cNE);
break;
case 0xE3:
INST_NAME("JECXZ");
i8 = F8S;
MOVw_REG(x1, xRCX);
TSTw_REG(x1, x1);
GO(cNE, cEQ);
break;
#undef GO
default:
DEFAULT;
}
return addr;
}
+670
View File
@@ -0,0 +1,670 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.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_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "../tools/bridge_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_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)
{
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_or64:d_or32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
ORRxw_REG(s1, s1, s2);
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_ZF) {
TSTxw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIx(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, 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)
{
IFX(X_PEND) {
MOV64xw(s3, c);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_or64:d_or32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_PEND) {} else {MOV64xw(s3, c);}
ORRxw_REG(s1, s1, 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_ZF) {
TSTxw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIx(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit XOR32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
void emit_xor32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
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_xor64:d_xor32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
EORxw_REG(s1, s1, s2);
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_ZF) {
TSTxw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIx(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, 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)
{
IFX(X_PEND) {
MOV64xw(s3, c);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_xor64:d_xor32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_PEND) {} else {MOV64xw(s3, c);}
EORxw_REG(s1, s1, 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_ZF) {
TSTxw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIx(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit AND32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
void emit_and32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
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_and64:d_and32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_ZF) {
ANDSxw_REG(s1, s1, s2);
} else {
ANDxw_REG(s1, s1, s2);
}
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_ZF) {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIx(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, 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)
{
IFX(X_PEND) {
MOV64xw(s3, c);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_and64:d_and32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_PEND) {} else {MOV64xw(s3, c);}
IFX(X_ALL) {
ANDSxw_REG(s1, s1, s3);
} else {
ANDxw_REG(s1, s1, 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_ZF) {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIx(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit OR8 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_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_or8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
}
ORRw_REG(s1, s1, s2);
IFX(X_PEND) {
STRB_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_ZF) {
TSTw_REG(s1, s1);
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 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)
{
MOV32w(s3, c&0xff);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_or8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
ORRw_REG(s1, s1, s3);
IFX(X_PEND) {
STRB_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_ZF) {
TSTw_REG(s1, s1);
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 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_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
}
EORx_REG(s1, s1, s2);
IFX(X_PEND) {
STRB_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_ZF) {
TSTw_REG(s1, s1);
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 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)
{
MOV32w(s3, c&0xff);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
EORw_REG(s1, s1, s3);
IFX(X_PEND) {
STRB_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_ZF) {
TSTw_REG(s1, s1);
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 AND8 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_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_and8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
}
IFX(X_ZF) {
ANDSw_REG(s1, s1, s2);
} else {
ANDw_REG(s1, s1, s2);
}
IFX(X_PEND) {
STRB_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_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);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, 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)
{
MOV32w(s3, c&0xff);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_and8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_ZF) {
ANDSw_REG(s1, s1, s3);
} else {
ANDw_REG(s1, s1, s3);
}
IFX(X_PEND) {
STRB_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_ZF) {
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 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)
{
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_or16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
}
ORRw_REG(s1, s1, s2);
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);
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
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 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);
// }
//}
// 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)
{
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_xor16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
}
EORw_REG(s1, s1, s2);
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);
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
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 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);
// }
//}
// 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)
{
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_and16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
}
IFX(X_ALL) {
ANDSw_REG(s1, s1, s2);
} else {
ANDw_REG(s1, s1, s2);
}
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_PEND) {
STRB_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_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);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, 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);
// }
//}
+1856
View File
File diff suppressed because it is too large. Load diff
+461
View File
@@ -0,0 +1,461 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.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_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "../tools/bridge_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_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
void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
int32_t j32;
MAYUSE(j32);
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_shl64:d_shl32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(F_OF) {
CMPSxw_U12(s2, 0);
IFX(F_OF) {
Bcond(cNE, +8);
BFCx(xFlags, F_OF, 1);
}
IFX(X_PEND) {
Bcond(cNE, +8);
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);
LSRxw_REG(s4, s1, s4);
BFIw(xFlags, s4, F_CF, 1);
}
LSLxw_REG(s1, s1, s2);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
BFCx(xFlags, F_ZF, 1);
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
}
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);}
Bcond(cNE, 4+3*4);
BFCw(xFlags, F_OF, 1);
EORxw_REG(s4, s4, xFlags); // CF is set if OF is asked
BFIw(xFlags, s4, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32w(s3, c);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_shl64:d_shl32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(c==0) {
IFX(F_OF) {
BFCx(xFlags, F_OF, 1);
}
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
IFX(X_CF) {
LSRxw(s3, s1, (rex.w?64:32)-c);
BFIxw(xFlags, s3, F_CF, 1);
}
LSLxw(s1, s1, c);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
BFCx(xFlags, F_ZF, 1);
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
if(c==1) {
IFX(X_SF) {} else {LSRxw(s4, s1, (rex.w)?63:31);}
Bcond(cNE, +12);
EORxw_REG(s4, s4, xFlags); // CF is set if OF is asked
BFIw(xFlags, s4, F_OF, 1);
} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHR32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
int32_t j32;
MAYUSE(j32);
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_shr64:d_shr32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_ALL) {
CMPSxw_U12(s2, 0); //if(!c)
IFX(X_PEND) {
Bcond(cNE, +12);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
B_NEXT(cEQ);
}
IFX(X_CF) {
SUBxw_U12(s3, s2, 1);
LSRxw_REG(s3, s1, s3);
BFIw(xFlags, s3, 0, 1);
}
LSRxw_REG(s1, s1, s2);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
BFCx(xFlags, F_ZF, 1);
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
}
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
Bcond(cNE, 4+3*4);
if(rex.w) {
LSRx(s4, s1, 62);
} else {
LSRw(s4, s1, 30);
}
EORw_REG_LSR(s4, s4, s4, 1);
BFIw(xFlags, s4, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32w(s3, c);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_shr64:d_shr32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
IFX(X_CF) {
LSRxw_REG(s3, s1, c-1);
BFIw(xFlags, s3, 0, 1);
}
LSRxw(s1, s1, c);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
BFCx(xFlags, F_ZF, 1);
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
if(c==1) {
LSRxw(s4, s1, rex.w?62:30);
EORw_REG_LSR(s4, s4, s4, 1);
BFIw(xFlags, s4, F_OF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SAR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32w(s3, c);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_sar64:d_sar32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
ASRxw(s1, s1, c);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
TSTw_REG(s1, s1);
BFCx(xFlags, F_ZF, 1);
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
}
IFX(X_CF) {
ASRxw(s3, s1, c-1);
BFIw(xFlags, s3, 0, 1);
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32w(s3, c);
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_rol32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
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);
BFIw(xFlags, s3, F_OF, 1);
}
}
}
// emit ROR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
{
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;
}
RORxw(s1, s1, c);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF) {
LSRxw(s3, s1, rex.w?63:31);
BFIw(xFlags, s3, F_CF, 1);
}
IFX(X_OF) {
if(c==1) {
LSRxw(s3, s1, rex.w?62:30);
EORxw_REG_LSR(s3, s3, s3, 1);
BFIw(xFlags, s4, F_OF, 1);
}
}
}
// emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch
//void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4)
//{
// c&=0x1f;
// IFX(X_PEND) {
// MOVW(s3, c);
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// // same flags calc as shr32
// SET_DF(s4, d_shr32);
// } else IFX(X_ALL) {
// SET_DFNONE(s4);
// }
// if(!c) {
// IFX(X_PEND) {
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
// }
// return;
// }
// IFX(X_CF) {
// MOVS_REG_LSR_IMM5(s1, s1, c);
// } else {
// MOV_REG_LSR_IMM5(s1, s1, c);
// }
// IFX(X_ZF|X_CF) {
// BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0);
// }
// IFX(X_CF) {
// ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
// }
// IFX(X_ZF) {
// ORRS_REG_LSL_IMM5(s1, s1, s2, 32-c);
// } else {
// ORR_REG_LSL_IMM5(s1, s1, s2, 32-c);
// }
// IFX(X_PEND) {
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
// }
// IFX(X_ZF) {
// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
// }
// IFX(X_SF) {
// MOV_REG_LSR_IMM5(s3, s1, 31);
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_OF) {
// if(c==1) {
// MOV_REG_LSR_IMM5(s4, s1, 30);
// XOR_REG_LSR_IMM8(s4, s4, s4, 1);
// BFI(xFlags, s4, F_OF, 1);
// }
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// }
//}
//void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4)
//{
// c&=0x1f;
// IFX(X_PEND) {
// MOVW(s3, c);
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// // same flags computation as with shl32
// SET_DF(s4, d_shl32);
// } else IFX(X_ALL) {
// SET_DFNONE(s4);
// }
// if(c==0) {
// IFX(F_OF) {
// BFC(xFlags, F_OF, 1);
// }
// IFX(X_PEND) {
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
// }
// return;
// }
// IFX(X_CF) {
// MOV_REG_LSR_IMM5(s3, s1, 32-c);
// BFI(xFlags, s3, F_CF, 1);
// }
// IFX(X_OF) {
// MOVS_REG_LSL_IMM5(s1, s1, c);
// } else {
// MOV_REG_LSL_IMM5(s1, s1, c);
// }
// IFX(X_OF) {
// if(c==1) {
// UBFX(s3, s2, 0, 1);
// XOR_IMM8_COND(cCS, s3, s3, 1);
// BFI(xFlags, s3, F_OF, 1);
// } else {
// BFC(xFlags, F_OF, 1);
// }
// }
// IFX(X_ZF) {
// ORRS_REG_LSR_IMM5(s1, s1, s2, 32-c);
// } else {
// ORR_REG_LSR_IMM5(s1, s1, s2, 32-c);
// }
//
// IFX(X_PEND) {
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
// }
// IFX(X_ZF) {
// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
// BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
// }
// IFX(X_SF) {
// MOV_REG_LSR_IMM5(s3, s1, 31);
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// }
//}
+372
View File
@@ -0,0 +1,372 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.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_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "../tools/bridge_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_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)
{
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_cmp64:d_cmp32);
} else {
SET_DFNONE(s4);
}
IFX(X_AF) {
ORNxw_REG(s3, s2, s1); // s3 = ~op1 | op2
BICxw(s4, s2, s1); // s4 = ~op1 & op2
}
SUBSxw_REG(s5, s1, s2); // res = s1 - s2
IFX(X_PEND) {
STRxw_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_AF) {
ANDxw_REG(s3, s3, s5); // s3 = (~op1 | op2) & res
ORRxw_REG(s3, s3, s4); // s3 = (~op1 & op2) | ((~op1 | op2) & res)
LSRxw(s4, s3, 3);
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_ZF|X_CF|X_OF) {
MOV32w(s4, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
BICx(xFlags, xFlags, s4);
}
IFX(X_ZF) {
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
}
IFX(X_CF) {
// inverted carry
Bcond(cCS, +8);
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
}
IFX(X_OF) {
Bcond(cVC, +8);
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
}
IFX(X_SF) {
LSRxw(s3, s5, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s3, s4);
}
}
// emit CMP32 instruction, from cmp s1 , 0, using s3 and s4 as scratch
void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4)
{
IFX(X_PEND) {
MOV64xw(s4, 0);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s4, xEmu, offsetof(x64emu_t, op2));
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
SET_DF(s4, rex.w?d_cmp64:d_cmp32);
} else {
SET_DFNONE(s4);
}
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_ZF|X_CF|X_OF|X_AF) {
MOV32w(s4, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF)|(1<<F_AF));
BICw(xFlags, xFlags, s4);
}
IFX(X_ZF) {
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
}
IFX(X_CF) {
// inverted carry
Bcond(cCS, +8);
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit CMP16 instruction, from cmp s1 , s2, using s3 and s4 as scratch
void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_cmp16);
} else {
SET_DFNONE(s3);
}
SUBw_REG(s5, s1, s2); // res = s1 - s2
IFX(X_PEND) {
STRH_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
TSTw_mask(s5, 0, 15); //mask=0xffff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s4, s5, 15);
BFIw(xFlags, s4, F_SF, 1);
}
// 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 CMP16 instruction, from cmp s1 , #0, using s3 and s4 as scratch
void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
IFX(X_PEND) {
MOV32w(s3, 0);
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s3, xEmu, offsetof(x64emu_t, op2));
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
SET_DF(s3, d_cmp16);
} else {
SET_DFNONE(s3);
}
// bc = (res & (~d | s)) | (~d & s) = 0
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s4, s1, 15);
BFIw(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit CMP8 instruction, from cmp s1 , s2, using s3 and s4 as scratch
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_cmp8);
} else {
SET_DFNONE(s4);
}
IFX(X_ZF) {
SUBSw_REG(s5, s1, s2); // res = s1 - s2
} else {
SUBw_REG(s5, s1, s2); // res = s1 - s2
}
IFX(X_PEND) {
STRB_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s5, 7);
BFIw(xFlags, s3, F_SF, 1);
}
// 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 CMP8 instruction, from cmp s1 , 0, using s3 and s4 as scratch
void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
MOV32w(s4, 0);
STRB_U12(s4, xEmu, offsetof(x64emu_t, op2));
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
SET_DF(s3, d_cmp8);
} else {
SET_DFNONE(s4);
}
// bc = (res & (~d | s)) | (~d & s) = 0
IFX(X_CF | X_AF | X_ZF | X_OF) {
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 0b000111); //mask=000000ff
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 TEST32 instruction, from test s1 , s2, using s3 and s4 as scratch
void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
SET_DF(s3, rex.w?d_tst64:d_tst32);
} 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);
}
ANDSxw_REG(s3, s1, s2); // res = s1 & s2
IFX(X_PEND) {
STRxw_U12(s3, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
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);
}
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
ANDw_mask(s3, s3, 0b011011, 000010); // 0xE0
LSRw(s3, s3, 5);
MOV64x(s4, (uintptr_t)GetParityTab());
LDRw_REG_LSL2(s4, s4, s3);
ANDw_mask(s3, s1, 0, 0b000100); // 0x1f
LSRw_REG(s4, s4, s3);
MVNx_REG(s4, s4);
BFIw(xFlags, s4, F_PF, 1);
}
}
// emit TEST16 instruction, from test s1 , s2, using s3 and s4 as scratch
void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX(X_PEND) {
SET_DF(s3, d_tst16);
} else {
SET_DFNONE(s4);
}
IFX(X_OF) {
BFCw(xFlags, F_OF, 1);
}
IFX(X_CF) {
BFCw(xFlags, F_CF, 1);
}
ANDSw_REG(s5, s1, s2); // res = s1 & s2
IFX(X_PEND) {
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 TEST8 instruction, from test s1 , s2, using s3 and s4 as scratch
void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX(X_PEND) {
SET_DF(s3, d_tst8);
} else {
SET_DFNONE(s4);
}
IFX(X_OF) {
BFCw(xFlags, F_OF, 1);
}
IFX(X_CF) {
BFCw(xFlags, F_CF, 1);
}
ANDSw_REG(s5, s1, s2); // res = s1 & s2
IFX(X_PEND) {
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);
}
}
+379
View File
@@ -0,0 +1,379 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.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_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop;
int32_t j32;
uint8_t gd, ed;
uint8_t wback, wb2, gb1, gb2;
int64_t i64;
int fixedaddress;
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(wb2);
MAYUSE(j32);
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
// REX prefix before the F0 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
switch(opcode) {
case 0x00:
INST_NAME("LOCK ADD Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
if(rex.rex) {
wback = xRAX + (nextop&7) + (rex.b<<3);
wb2 = 0;
} else {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xRAX+(wback&3);
}
UBFXw(x1, wback, wb2*8, 8);
emit_add8(dyn, ninst, x1, x2, x4, x3);
BFIx(wback, x1, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 0);
MARKLOCK;
LDAXRB(x1, wback);
emit_add8(dyn, ninst, x1, x2, x4, x3);
STLXRB(x4, x1, wback);
CBNZx_MARKLOCK(x4);
}
break;
case 0x01:
INST_NAME("LOCK ADD Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_add32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
MARKLOCK;
LDAXRxw(x1, wback);
emit_add32(dyn, ninst, rex, x1, gd, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 0x0F:
nextop = F8;
switch(nextop) {
case 0xB1:
INST_NAME("LOCK CMPXCHG Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(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);
MOVxw_REG(ed, gd);
MARK2;
MOVxw_REG(xRAX, x1);
B_NEXT_nocond;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK3(cNE);
// Aligned version
MARKLOCK;
LDAXRxw(x1, wback);
ed = x1;
CMPSxw_REG(xRAX, ed);
B_MARK(cNE);
// EAX == Ed
STLXRxw(x4, gd, wback);
CBNZx_MARKLOCK(x4);
// done
B_MARK_nocond;
// Unaligned version
MARK3;
LDRxw_U12(x1, wback, 0);
LDAXRB(x3, wback); // dummy read, to arm the write...
ed = x1;
CMPSxw_REG(xRAX, ed);
B_MARK(cNE);
// EAX == Ed
STLXRB(x4, gd, wback);
CBNZx_MARK3(x4);
STRxw_U12(gd, wback, 0);
B_MARK_nocond;
MARK;
// Common part (and fallback for EAX != Ed)
UFLAG_IF {emit_cmp32(dyn, ninst, rex, xRAX, ed, x3, x4, x5);}
MOVxw_REG(xRAX, ed);
}
break;
case 0xC1:
INST_NAME("LOCK XADD Gd, Ed");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
MOVxw_REG(x1, ed);
MOVxw_REG(ed, gd);
MOVxw_REG(gd, x1);
emit_add32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE); // unaligned
MARKLOCK;
LDAXRxw(x1, wback);
ADDxw_REG(x4, x1, gd);
STLXRxw(x3, x4, wback);
CBNZx_MARKLOCK(x3);
B_MARK2_nocond;
MARK;
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8);
ADDxw_REG(x4, x1, gd);
STLXRB(x3, x4, wback);
CBNZx_MARK(x3);
STRxw_U12(x4, wback, 0);
MARK2;
IFX(X_ALL|X_PEND) {
MOVxw_REG(x2, x1);
emit_add32(dyn, ninst, rex, x2, gd, x3, x4);
}
MOVxw_REG(gd, x1);
}
break;
default:
DEFAULT;
}
break;
case 0x81:
case 0x83:
nextop = F8;
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
INST_NAME("LOCK ADD Ed, Id");
} else {
INST_NAME("LOCK ADD Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV64xw(x5, i64);
emit_add32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
MARKLOCK;
LDAXRxw(x1, wback);
emit_add32(dyn, ninst, rex, x1, x5, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
B_NEXT_nocond;
MARK; // unaligned! also, not enough
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
emit_add32(dyn, ninst, rex, x1, x5, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARK(x3);
STRxw_U12(x1, wback, 0); // put the whole value
}
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("LOCK OR Ed, Id");} else {INST_NAME("LOCK OR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV64xw(x5, i64);
emit_or32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
MARKLOCK;
LDAXRxw(x1, wback);
emit_or32(dyn, ninst, rex, x1, x5, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 2: //ADC
if(opcode==0x81) {INST_NAME("LOCK ADC Ed, Id");} else {INST_NAME("LOCK ADC Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV64xw(x5, i64);
emit_adc32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
MARKLOCK;
LDAXRxw(x1, wback);
emit_adc32(dyn, ninst, rex, x1, x5, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 3: //SBB
if(opcode==0x81) {INST_NAME("LOCK SBB Ed, Id");} else {INST_NAME("LOCK SBB Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV64xw(x5, i64);
emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
MARKLOCK;
LDAXRxw(x1, wback);
emit_sbb32(dyn, ninst, rex, x1, x5, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("LOCK AND Ed, Id");} else {INST_NAME("LOCK AND Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV64xw(x5, i64);
emit_and32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
MARKLOCK;
LDAXRxw(x1, wback);
emit_and32(dyn, ninst, rex, x1, x5, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("LOCK SUB Ed, Id");} else {INST_NAME("LOCK SUB Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV64xw(x5, i64);
emit_sub32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
MARKLOCK;
LDAXRxw(x1, wback);
emit_sub32(dyn, ninst, rex, x1, x5, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
B_NEXT_nocond;
MARK; // unaligned! also, not enough
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
emit_sub32(dyn, ninst, rex, x1, x5, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARK(x3);
STRxw_U12(x1, wback, 0); // put the whole value
}
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("LOCK XOR Ed, Id");} else {INST_NAME("LOCK XOR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV64xw(x5, i64);
emit_xor32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
MARKLOCK;
LDAXRxw(x1, wback);
emit_xor32(dyn, ninst, rex, x1, x5, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("(LOCK) CMP Ed, Id");} else {INST_NAME("(LOCK) CMP Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
GETED(0);
// No need to LOCK, this is readonly
if(opcode==0x81) i64 = F32S; else i64 = F8S;
if(i64) {
MOV64xw(x5, i64);
emit_cmp32(dyn, ninst, rex, ed, x5, x3, x4, x6);
} else {
emit_cmp32_0(dyn, ninst, rex, ed, x3, x4);
}
break;
}
break;
default:
DEFAULT;
}
return addr;
}
+239
View File
@@ -0,0 +1,239 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.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_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
// Get Ex as a double, not a quad (warning, x2 get used)
#define GETEX(a, D) \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3)); \
} else { \
a = fpu_get_scratch(dyn); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, D); \
VLDR64_U12(a, ed, fixedaddress); \
}
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
#define GETGX(a) gd = ((nextop&0x38)>>3)+(rex.r<<3); \
a = sse_get_reg(dyn, ninst, x1, gd)
uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
uint8_t wback;
int v0, v1;
int q0;
int d0, d1;
int fixedaddress;
#ifdef PRECISE_CVT
int j32;
MAYUSE(j32);
#endif
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(q0);
MAYUSE(v0);
MAYUSE(v1);
switch(opcode) {
case 0x10:
INST_NAME("MOVSD Gx, Ex");
nextop = F8;
GETG;
if(MODREG) {
ed = (nextop&7)+ (rex.b<<3);
v0 = sse_get_reg(dyn, ninst, x1, gd);
d0 = sse_get_reg(dyn, ninst, x1, ed);
VMOV(v0, d0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VLDR64_U12(v0, ed, fixedaddress); // upper part reseted
}
break;
case 0x11:
INST_NAME("MOVSD Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if(MODREG) {
ed = (nextop&7)+ (rex.b<<3);
d0 = sse_get_reg(dyn, ninst, x1, ed);
VMOV(d0, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
}
break;
case 0x2A:
INST_NAME("CVTSI2SD Gx, Ed");
nextop = F8;
GETGX(v0);
GETED(0);
d1 = fpu_get_scratch(dyn);
if(rex.w) {
SCVTFDx(d1, ed);
} else {
SCVTFDw(d1, ed);
}
VMOVeD(v0, 0, d1, 0);
break;
case 0x2C:
INST_NAME("CVTTSD2SI Gd, Ex");
nextop = F8;
GETGD;
GETEX(q0, 0);
FCVTZSxwD(gd, q0);
break;
case 0x2D:
INST_NAME("CVTSD2SI Gd, Ex");
nextop = F8;
GETGD;
GETEX(q0, 0);
#ifdef PRECISE_CVT
LDRH_U12(x1, xEmu, offsetof(x64emu_t, mxcsr));
UBFXx(x1, x1, 13, 2); // extract round requested
LSLx_REG(x1, x1, 3);
ADDx_U12(x1, x1, 8); // add the actual add+jump opcodes
// Construct a "switch case", with each case 2 instructions, so 8 bytes
BL(+4); // Branch with Link to next, so LR gets next PC address
ADDx_REG(xLR, xLR, x1);
B(xLR); // could use RET, but it's not really one
FCVTNSxwD(gd, q0); // 0: Nearest (even)
B_NEXT_nocond;
FCVTMSxwD(gd, q0); // 1: Toward -inf
B_NEXT_nocond;
FCVTPSxwD(gd, q0); // 2: Toward +inf
B_NEXT_nocond;
FCVTZSxwD(gd, q0); // 3: Toward 0
#else
FCVTNSxwD(gd, q0);
#endif
break;
case 0x51:
INST_NAME("SQRTSD Gx, Ex");
nextop = F8;
GETGX(v0);
d1 = fpu_get_scratch(dyn);
GETEX(d0, 0);
FSQRTD(d1, d0);
VMOVeD(v0, 0, d1, 0);
break;
case 0x58:
INST_NAME("ADDSD Gx, Ex");
nextop = F8;
GETGX(v0);
d1 = fpu_get_scratch(dyn);
GETEX(d0, 0);
FADDD(d1, v0, d0); // the high part of the vector is erased...
VMOVeD(v0, 0, d1, 0);
break;
case 0x59:
INST_NAME("MULSD Gx, Ex");
nextop = F8;
GETGX(v0);
d1 = fpu_get_scratch(dyn);
GETEX(d0, 0);
FMULD(d1, v0, d0);
VMOVeD(v0, 0, d1, 0);
break;
case 0x5A:
INST_NAME("CVTSD2SS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(d0, 0);
d1 = fpu_get_scratch(dyn);
FCVT_S_D(d1, d0);
VMOVeS(v0, 0, d1, 0);
break;
case 0x5C:
INST_NAME("SUBSD Gx, Ex");
nextop = F8;
GETGX(v0);
d1 = fpu_get_scratch(dyn);
GETEX(d0, 0);
FSUBD(d1, v0, d0);
VMOVeD(v0, 0, d1, 0);
break;
case 0x5D:
INST_NAME("MINSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(v1, 0);
// MINSD: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
d0 = fpu_get_scratch(dyn);
FMINNMD(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeD(v0, 0, d0, 0); // to not erase uper part
break;
case 0x5E:
INST_NAME("DIVSD Gx, Ex");
nextop = F8;
GETGX(v0);
d1 = fpu_get_scratch(dyn);
GETEX(d0, 0);
FDIVD(d1, v0, d0);
VMOVeD(v0, 0, d1, 0);
break;
case 0x5F:
INST_NAME("MAXSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(v1, 0);
// MAXSD: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
d0 = fpu_get_scratch(dyn);
FMAXNMD(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeD(v0, 0, d0, 0); // to not erase uper part
break;
case 0x7C:
INST_NAME("HADDPS Gx, Ex");
nextop = F8;
GETGX(v0);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
v1 = fpu_get_scratch(dyn);
VLDR128_U12(v1, ed, fixedaddress);
}
VFADDPQS(v0, v0, v1);
break;
default:
DEFAULT;
}
return addr;
}
+290
View File
@@ -0,0 +1,290 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.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_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
// Get Ex as a single, not a quad (warning, x2 get used)
#define GETEX(a, D) \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3)); \
} else { \
a = fpu_get_scratch(dyn); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
VLDR32_U12(a, ed, fixedaddress); \
}
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
#define GETGX(a) gd = ((nextop&0x38)>>3)+(rex.r<<3); \
a = sse_get_reg(dyn, ninst, x1, gd)
#define GETGX_empty(a) gd = ((nextop&0x38)>>3)+(rex.r<<3); \
a = sse_get_reg_empty(dyn, ninst, x1, gd)
uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed;
uint8_t wback;
int v0, v1;
int q0, q1;
int d0, d1;
int fixedaddress;
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(v0);
MAYUSE(v1);
switch(opcode) {
case 0x10:
INST_NAME("MOVSS Gx, Ex");
nextop = F8;
GETG;
if(MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, gd);
q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
VMOVeS(v0, 0, q0, 0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VLDR32_U12(v0, ed, fixedaddress);
}
break;
case 0x11:
INST_NAME("MOVSS Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
VMOVeS(q0, 0, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VSTR32_U12(v0, ed, fixedaddress);
}
break;
case 0x12:
INST_NAME("MOVSLDUP Gx, Ex");
nextop = F8;
if(MODREG) {
q1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
q1 = fpu_get_scratch(dyn);
VLDR128_U12(q1, ed, fixedaddress);
}
GETGX_empty(q0);
VTRNQ1_32(q0, q1, q1);
break;
case 0x16:
INST_NAME("MOVSHDUP Gx, Ex");
nextop = F8;
if(MODREG) {
q1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
q1 = fpu_get_scratch(dyn);
VLDR128_U12(q1, ed, fixedaddress);
}
GETGX_empty(q0);
VTRNQ2_32(q0, q1, q1);
break;
case 0x2A:
INST_NAME("CVTSI2SS Gx, Ed");
nextop = F8;
GETGX(v0);
GETED(0);
d1 = fpu_get_scratch(dyn);
if(rex.w) {
SCVTFSx(d1, ed);
} else {
SCVTFSw(d1, ed);
}
VMOVeS(v0, 0, d1, 0);
break;
case 0x2C:
INST_NAME("CVTTSS2SI Gd, Ex");
nextop = F8;
GETGD;
GETEX(d0, 0);
FCVTZSxwS(gd, d0);
break;
case 0x51:
INST_NAME("SQRTSS Gx, Ex");
nextop = F8;
GETGX(v0);
d1 = fpu_get_scratch(dyn);
GETEX(d0, 0);
FSQRTS(d1, d0);
VMOVeS(v0, 0, d1, 0);
break;
case 0x58:
INST_NAME("ADDSS Gx, Ex");
nextop = F8;
GETGX(v0);
d1 = fpu_get_scratch(dyn);
GETEX(d0, 0);
FADDS(d1, v0, d0); // the high part of the vector is erased...
VMOVeS(v0, 0, d1, 0);
break;
case 0x59:
INST_NAME("MULSS Gx, Ex");
nextop = F8;
GETGX(v0);
d1 = fpu_get_scratch(dyn);
GETEX(d0, 0);
FMULS(d1, v0, d0);
VMOVeS(v0, 0, d1, 0);
break;
case 0x5A:
INST_NAME("CVTSS2SD Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
d0 = fpu_get_scratch(dyn);
FCVT_D_S(d0, v1);
VMOVeD(v0, 0, d0, 0);
break;
case 0x5C:
INST_NAME("SUBSS Gx, Ex");
nextop = F8;
GETGX(v0);
d1 = fpu_get_scratch(dyn);
GETEX(d0, 0);
FSUBS(d1, v0, d0);
VMOVeS(v0, 0, d1, 0);
break;
case 0x5D:
INST_NAME("MINSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
// MINSS: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
d0 = fpu_get_scratch(dyn);
FMINNMS(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeS(v0, 0, d0, 0); // to not erase uper part
break;
case 0x5E:
INST_NAME("DIVSS Gx, Ex");
nextop = F8;
GETGX(v0);
d1 = fpu_get_scratch(dyn);
GETEX(d0, 0);
FDIVS(d1, v0, d0);
VMOVeS(v0, 0, d1, 0);
break;
case 0x5F:
INST_NAME("MAXSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
// MAXSS: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
d0 = fpu_get_scratch(dyn);
FMAXNMS(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeS(v0, 0, d0, 0); // to not erase uper part
break;
case 0x6F:
INST_NAME("MOVDQU Gx,Ex");// no alignment constraint on NEON here, so same as MOVDQA
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));
VMOVQ(v0, v1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
}
break;
case 0x7E:
INST_NAME("MOVQ Gx, Ex");
nextop = F8;
GETG;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
FMOVD(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
}
break;
case 0x7F:
INST_NAME("MOVDQU Ex,Gx");
nextop = F8;
GETG;
if(MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, gd);
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
VMOVQ(v1, v0);
} else {
v0 = sse_get_reg(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
}
break;
case 0xC2:
INST_NAME("CMPSS Gx, Ex, Ib");
nextop = F8;
GETGX(v0);
GETEX(v1, 1);
u8 = F8;
if((u8&7)==6){
FCMPS(v1, v0);
} else {
FCMPS(v0, v1);
}
switch(u8&7) {
case 0: CSETMw(x2, cEQ); break; // Equal
case 1: CSETMw(x2, cMI); break; // Less than
case 2: //CSETMw(x2, cLE); break; // Less or equal (or unordered on ARM64, not on x86...)
CSETMw(x2, cPL); CSINVw(x2, xZR, x2, cEQ); break; // so use a 2 step here, but 1st test inverted because 2nd step invert again
case 3: CSETMw(x2, cVS); break; // NaN
case 4: CSETMw(x2, cNE); break; // Not Equal (or unordered on ARM, not on X86...)
case 5: CSETMw(x2, cCS); break; // Greater or equal or unordered
case 6: CSETMw(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
case 7: CSETMw(x2, cVC); break; // not NaN
}
VMOVQSfrom(v0, 0, x2);
break;
default:
DEFAULT;
}
return addr;
}
+335
View File
@@ -0,0 +1,335 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <math.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "tools/bridge_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "emu/x87emu_private.h"
#include "x64trace.h"
#include "signals.h"
#include "dynarec_arm64.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
void arm_fstp(x64emu_t* emu, void* p)
{
if(ST0.q!=STld(0).ref)
D2LD(&ST0.d, p);
else
memcpy(p, &STld(0).ld, 10);
}
void arm_print_armreg(x64emu_t* emu, uintptr_t reg, uintptr_t n)
{
dynarec_log(LOG_DEBUG, "R%ld=0x%lx (%ld)\n", n, reg, reg);
}
void arm_f2xm1(x64emu_t* emu)
{
ST0.d = exp2(ST0.d) - 1.0;
}
void arm_fyl2x(x64emu_t* emu)
{
ST(1).d = log2(ST0.d)*ST(1).d;
}
void arm_ftan(x64emu_t* emu)
{
ST0.d = tan(ST0.d);
}
void arm_fpatan(x64emu_t* emu)
{
ST1.d = atan2(ST1.d, ST0.d);
}
void arm_fxtract(x64emu_t* emu)
{
int32_t tmp32s = (ST1.q&0x7ff0000000000000LL)>>52;
tmp32s -= 1023;
ST1.d /= exp2(tmp32s);
ST0.d = tmp32s;
}
void arm_fprem(x64emu_t* emu)
{
int32_t tmp32s = ST0.d / ST1.d;
ST0.d -= ST1.d * tmp32s;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = (tmp32s&1);
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
emu->sw.f.F87_C1 = ((tmp32s>>2)&1);
}
void arm_fyl2xp1(x64emu_t* emu)
{
ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
}
void arm_fsincos(x64emu_t* emu)
{
sincos(ST1.d, &ST1.d, &ST0.d);
}
void arm_frndint(x64emu_t* emu)
{
ST0.d = fpu_round(emu, ST0.d);
}
void arm_fscale(x64emu_t* emu)
{
ST0.d *= exp2(trunc(ST1.d));
}
void arm_fsin(x64emu_t* emu)
{
ST0.d = sin(ST0.d);
}
void arm_fcos(x64emu_t* emu)
{
ST0.d = cos(ST0.d);
}
void arm_fbld(x64emu_t* emu, uint8_t* ed)
{
fpu_fbld(emu, ed);
}
void arm_fild64(x64emu_t* emu, int64_t* ed)
{
int64_t tmp;
memcpy(&tmp, ed, sizeof(tmp));
ST0.d = tmp;
STll(0).ll = tmp;
STll(0).ref = ST0.q;
}
void arm_fbstp(x64emu_t* emu, uint8_t* ed)
{
fpu_fbst(emu, ed);
}
void arm_fistp64(x64emu_t* emu, int64_t* ed)
{
// used of memcpy to avoid aligments issues
if(STll(0).ref==ST(0).q) {
memcpy(ed, &STll(0).ll, sizeof(int64_t));
} else {
int64_t tmp;
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL) || !isfinite(ST0.d))
tmp = 0x8000000000000000LL;
else
tmp = fpu_round(emu, ST0.d);
memcpy(ed, &tmp, sizeof(tmp));
}
}
void arm_fistt64(x64emu_t* emu, int64_t* ed)
{
// used of memcpy to avoid aligments issues
int64_t tmp = ST0.d;
memcpy(ed, &tmp, sizeof(tmp));
}
void arm_fld(x64emu_t* emu, uint8_t* ed)
{
memcpy(&STld(0).ld, ed, 10);
LD2D(&STld(0), &ST(0).d);
STld(0).ref = ST0.q;
}
void arm_ud(x64emu_t* emu)
{
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
}
void arm_fsave(x64emu_t* emu, uint8_t* ed)
{
fpu_savenv(emu, (char*)ed, 0);
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
LD2D(p, &ST(i).d);
p+=10;
}
}
void arm_frstor(x64emu_t* emu, uint8_t* ed)
{
fpu_loadenv(emu, (char*)ed, 0);
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
D2LD(&ST(i).d, p);
p+=10;
}
}
void arm_fprem1(x64emu_t* emu)
{
// simplified version
int32_t tmp32s = round(ST0.d / ST1.d);
ST0.d -= ST1.d*tmp32s;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = (tmp32s&1);
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
emu->sw.f.F87_C1 = ((tmp32s>>2)&1);
}
#define XMM0 0
#define XMM8 16
#define X870 8
#define EMM0 8
#define SCRATCH0 24
// Get a FPU scratch reg
int fpu_get_scratch(dynarec_arm_t* dyn)
{
return SCRATCH0 + dyn->fpu_scratch++; // return an Sx
}
// Reset scratch regs counter
void fpu_reset_scratch(dynarec_arm_t* dyn)
{
dyn->fpu_scratch = 0;
}
// Get a x87 double reg
int fpu_get_reg_x87(dynarec_arm_t* dyn)
{
int i=X870;
while (dyn->fpuused[i]) ++i;
dyn->fpuused[i] = 1;
return i; // return a Dx
}
// Free a FPU double reg
void fpu_free_reg(dynarec_arm_t* dyn, int reg)
{
// TODO: check upper limit?
dyn->fpuused[reg] = 0;
}
// Get an MMX double reg
int fpu_get_reg_emm(dynarec_arm_t* dyn, int emm)
{
dyn->fpuused[EMM0 + emm] = 1;
return EMM0 + emm;
}
// Get an XMM quad reg
int fpu_get_reg_xmm(dynarec_arm_t* dyn, int xmm)
{
if(xmm>7) {
dyn->fpuused[XMM8 + xmm - 8] = 1;
return XMM8 + xmm - 8;
} else {
dyn->fpuused[XMM0 + xmm] = 1;
return XMM0 + xmm;
}
}
// Reset fpu regs counter
void fpu_reset_reg(dynarec_arm_t* dyn)
{
dyn->fpu_reg = 0;
for (int i=0; i<32; ++i)
dyn->fpuused[i]=0;
}
#define F8 *(uint8_t*)(addr++)
#define F32 *(uint32_t*)(addr+=4, addr-4)
#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
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity, int delta)
{
uint32_t tested = (1<<parity)-1;
if((nextop&0xC0)==0xC0)
return 0; // direct register, no parity...
if(!(nextop&0xC0)) {
if((nextop&7)==4) {
uint8_t sib = F8;
int sib_reg = (sib>>3)&7;
if((sib&0x7)==5) {
uint64_t tmp = F32S64;
if (sib_reg!=4) {
// if XXXXXX+reg<<N then check parity of XXXXX and N should be enough
return ((tmp&tested)==0 && (sib>>6)>=parity)?1:0;
} else {
// just a constant...
return (tmp&tested)?0:1;
}
} else {
if(sib_reg==4 && parity<3)
return 0; // simple [reg]
// don't try [reg1 + reg2<<N], unless reg1 is ESP
return ((sib&0x7)==4 && (sib>>6)>=parity)?1:0;
}
} else if((nextop&7)==5) {
uint64_t tmp = F32S64;
tmp+=addr+delta;
return (tmp&tested)?0:1;
} else {
return 0;
}
} else {
return 0; //Form [reg1 + reg2<<N + XXXXXX]
}
}
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
{
if((nextop&0xC0)==0xC0)
return addr;
if(!(nextop&0xC0)) {
if((nextop&7)==4) {
uint8_t sib = F8;
if((sib&0x7)==5) {
addr+=4;
}
} else if((nextop&7)==5) {
addr+=4;
}
} else {
if((nextop&7)==4) {
++addr;
}
if(nextop&0x80) {
addr+=4;
} else {
++addr;
}
}
return addr;
}
#undef F8
#undef F32
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn)
{
#define PK(a) *(uint8_t*)(addr+a)
#define PK32(a) *(int32_t*)(addr+a)
if(!addr)
return 0;
if(PK(0)==0xff && PK(1)==0x25) { // "absolute" jump, maybe the GOT (well, RIP relative in fact)
uintptr_t a1 = addr + 6 + (PK32(2)); // need to add a check to see if the address is from the GOT !
addr = *(uintptr_t*)a1;
}
if(addr<0x10000) // too low, that is suspicious
return 0;
onebridge_t *b = (onebridge_t*)(addr);
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver) {
// found !
if(retn) *retn = (b->C3==0xC2)?b->N:0;
if(calladdress) *calladdress = addr+1;
return 1;
}
return 0;
#undef PK32
#undef PK
}
+57
View File
@@ -0,0 +1,57 @@
#ifndef __DYNAREC_ARM_FUNCTIONS_H__
#define __DYNAREC_ARM_FUNCTIONS_H__
typedef struct x64emu_s x64emu_t;
void arm_fstp(x64emu_t* emu, void* p);
void arm_print_armreg(x64emu_t* emu, uintptr_t reg, uintptr_t n);
void arm_f2xm1(x64emu_t* emu);
void arm_fyl2x(x64emu_t* emu);
void arm_ftan(x64emu_t* emu);
void arm_fpatan(x64emu_t* emu);
void arm_fxtract(x64emu_t* emu);
void arm_fprem(x64emu_t* emu);
void arm_fyl2xp1(x64emu_t* emu);
void arm_fsincos(x64emu_t* emu);
void arm_frndint(x64emu_t* emu);
void arm_fscale(x64emu_t* emu);
void arm_fsin(x64emu_t* emu);
void arm_fcos(x64emu_t* emu);
void arm_fbld(x64emu_t* emu, uint8_t* ed);
void arm_fild64(x64emu_t* emu, int64_t* ed);
void arm_fbstp(x64emu_t* emu, uint8_t* ed);
void arm_fistp64(x64emu_t* emu, int64_t* ed);
void arm_fistt64(x64emu_t* emu, int64_t* ed);
void arm_fld(x64emu_t* emu, uint8_t* ed);
void arm_fsave(x64emu_t* emu, uint8_t* ed);
void arm_frstor(x64emu_t* emu, uint8_t* ed);
void arm_fprem1(x64emu_t* emu);
void arm_ud(x64emu_t* emu);
// Get an FPU scratch reg
int fpu_get_scratch(dynarec_arm_t* dyn);
// 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);
// Get an MMX double reg
int fpu_get_reg_emm(dynarec_arm_t* dyn, int emm);
// Get an XMM quad reg
int fpu_get_reg_xmm(dynarec_arm_t* dyn, 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);
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity, int delta);
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
// Is what pointed at addr a native call? And if yes, to what function?
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
#endif //__DYNAREC_ARM_FUNCTIONS_H__
+989
View File
@@ -0,0 +1,989 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.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_arm64.h"
#include "dynarec_arm64_private.h"
#include "dynablock_private.h"
#include "arm64_printer.h"
#include "../tools/bridge_private.h"
#include "custommem.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta)
{
uint8_t ret = x2;
uint8_t scratch = x2;
*fixaddress = 0;
if(hint>0) ret = hint;
if(hint>0 && hint<xRAX) scratch = hint;
int absmin = 0;
if(s) absmin=-absmax;
MAYUSE(scratch);
if(!(nextop&0xC0)) {
if((nextop&7)==4) {
uint8_t sib = F8;
int sib_reg = ((sib>>3)&7)+(rex.x<<3);
if((sib&0x7)==5) {
uint64_t tmp = F32S64;
if (sib_reg!=4) {
if(tmp && ((tmp<absmin) || (tmp>absmax) || (tmp&mask))) {
MOV64x(scratch, tmp);
ADDx_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
} else {
LSLx(ret, xRAX+sib_reg, (sib>>6));
*fixaddress = tmp;
}
} else {
MOV64x(ret, tmp);
}
} else {
if (sib_reg!=4) {
ADDx_REG_LSL(ret, xRAX+(sib&0x7)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
} else {
ret = xRAX+(sib&0x7)+(rex.b<<3);
}
}
} else if((nextop&7)==5) {
uint64_t tmp = F32S64;
MOV64x(ret, tmp);
GETIP(addr+delta);
ADDx_REG(ret, ret, xRIP);
} else {
ret = xRAX+(nextop&7)+(rex.b<<3);
}
} else {
int64_t i64;
uint8_t sib = 0;
int sib_reg = 0;
if((nextop&7)==4) {
sib = F8;
sib_reg = ((sib>>3)&7)+(rex.x<<3);
}
if(nextop&0x80)
i64 = F32S;
else
i64 = F8S;
if(i64==0 || ((i64>=absmin) && (i64<=absmax) && !(i64&mask))) {
*fixaddress = i64;
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDx_REG_LSL(ret, xRAX+(sib&0x07)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
} else {
ret = xRAX+(sib&0x07)+(rex.b<<3);
}
} else
ret = xRAX+(nextop&0x07)+(rex.b<<3);
} else {
int64_t sub = (i64<0)?1:0;
if(sub) i64 = -i64;
if(i64<0x1000) {
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDx_REG_LSL(scratch, xRAX+(sib&0x07)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
} else {
scratch = xRAX+(sib&0x07)+(rex.b<<3);
}
} else
scratch = xRAX+(nextop&0x07)+(rex.b<<3);
if(sub) {
SUBx_U12(ret, scratch, i64);
} else {
ADDx_U12(ret, scratch, i64);
}
} else {
MOV64x(scratch, i64);
if((nextop&7)==4) {
if (sib_reg!=4) {
if(sub) {
SUBx_REG(scratch, xRAX+(sib&0x07)+(rex.b<<3), scratch);
} else {
ADDx_REG(scratch, scratch, xRAX+(sib&0x07)+(rex.b<<3));
}
ADDx_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
} else {
PASS3(int tmp = xRAX+(sib&0x07)+(rex.b<<3));
if(sub) {
SUBx_REG(ret, tmp, scratch);
} else {
ADDx_REG(ret, tmp, scratch);
}
}
} else {
PASS3(int tmp = xRAX+(nextop&0x07)+(rex.b<<3));
if(sub) {
SUBx_REG(ret, tmp, scratch);
} else {
ADDx_REG(ret, tmp, scratch);
}
}
}
}
}
*ed = ret;
return addr;
}
/* setup r2 to address pointed by ED, r3 as scratch also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, int s)
{
uint8_t ret = x2;
uint8_t scratch = x3;
*fixaddress = 0;
if(hint>0) ret = hint;
if(scratch==ret) scratch = x2;
MAYUSE(scratch);
uint32_t m = nextop&0xC7;
uint32_t n = (m>>6)&3;
int32_t offset = 0;
int absmin = 0;
if(s) absmin = -absmax;
if(!n && m==6) {
offset = F16;
MOVZw(ret, offset);
} else {
switch(n) {
case 0: offset = 0; break;
case 1: offset = F8S; break;
case 2: offset = F16S; break;
}
if(offset && (offset>absmax || offset<absmin || (offset&mask))) {
*fixaddress = offset;
offset = 0;
}
switch(m&7) {
case 0: //R_BX + R_SI
UXTHx(ret, xRBX);
UXTHx(scratch, xRSI);
ADDx_REG(ret, ret, scratch);
break;
case 1: //R_BX + R_DI
UXTHx(ret, xRBX);
UXTHx(scratch, xRDI);
ADDx_REG(ret, ret, scratch);
break;
case 2: //R_BP + R_SI
UXTHx(ret, xRBP);
UXTHx(scratch, xRSI);
ADDx_REG(ret, ret, scratch);
break;
case 3: //R_BP + R_DI
UXTHx(ret, xRBP);
UXTHx(scratch, xRDI);
ADDx_REG(ret, ret, scratch);
break;
case 4: //R_SI
UXTHx(ret, xRSI);
break;
case 5: //R_DI
UXTHx(ret, xRDI);
break;
case 6: //R_BP
UXTHx(ret, xRBP);
break;
case 7: //R_BX
UXTHx(ret, xRBX);
break;
}
if(offset) {
if(offset<0 && offset>-0x1000) {
SUBx_U12(ret, ret, -offset);
} else if(offset>0 && offset<0x1000) {
ADDx_U12(ret, ret, offset);
} else {
MOV64x(scratch, offset);
ADDx_REG(ret, ret, scratch);
}
}
}
*ed = ret;
return addr;
}
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
{
MESSAGE(LOG_DUMP, "Jump to epilog\n");
if(reg) {
if(reg!=xRIP) {
MOVx_REG(xRIP, reg);
}
} else {
GETIP_(ip);
}
TABLE64(x2, (uintptr_t)arm64_epilog);
BR(x2);
}
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
{
MESSAGE(LOG_DUMP, "Jump to next\n");
if(reg) {
if(reg!=xRIP) {
MOVx_REG(xRIP, reg);
}
uintptr_t tbl = getJumpTable64();
MAYUSE(tbl);
TABLE64(x2, tbl);
UBFXx(x3, xRIP, 48, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, 32, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, 16, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, 0, JMPTABL_SHIFT);
LDRx_REG_LSL3(x3, x2, x3);
} else {
uintptr_t p = getJumpTableAddress64(ip);
MAYUSE(p);
TABLE64(x2, p);
GETIP_(ip);
LDRx_U12(x3, x2, 0);
}
if(reg!=x1) {
MOVx_REG(x1, xRIP);
}
#ifdef HAVE_TRACE
//MOVx(x2, 15); no access to PC reg
#endif
BR(x3);
}
void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
{
MESSAGE(LOG_DUMP, "Ret next\n");
POP1(xRIP);
uintptr_t tbl = getJumpTable64();
MOV64x(x2, tbl);
UBFXx(x3, xRIP, 48, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, 32, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, 16, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, 0, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
MOVx_REG(x1, xRIP);
BR(x2);
}
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
{
MESSAGE(LOG_DUMP, "Retn epilog\n");
POP1(xRIP);
if(n>0xfff) {
MOV32w(w1, n);
ADDx_REG(xRSP, xRSP, x1);
} else {
ADDx_U12(xRSP, xRSP, n);
}
uintptr_t tbl = getJumpTable64();
MOV64x(x2, tbl);
UBFXx(x3, xRIP, 48, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, 32, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, 16, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, 0, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
MOVx_REG(x1, xRIP);
BR(x2);
}
void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
{
MESSAGE(LOG_DUMP, "IRet epilog\n");
// POP IP
POP1(xRIP);
// POP CS
POP1(x2);
STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_CS]));
MOVZw(x1, 0);
STRx_U12(x1, xEmu, offsetof(x64emu_t, segs_serial[_CS]));
// POP EFLAGS
POP1(xFlags);
MOV32w(x1, 0x3F7FD7);
ANDx_REG(xFlags, xFlags, x1);
ORRx_mask(xFlags, xFlags, 1, 0b111111, 0);
SET_DFNONE(x1);
// Ret....
MOV64x(x2, (uintptr_t)arm64_epilog); // epilog on purpose, CS might have changed!
BR(x2);
}
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int savereg)
{
if(savereg==0)
savereg = 7;
if(saveflags) {
STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
}
fpu_pushcache(dyn, ninst, reg);
if(ret!=-2) {
STPx_S7_preindex(xEmu, savereg, xSP, -16); // ARM64 stack needs to be 16byte aligned
STPx_S7_offset(xRAX, xRCX, xEmu, offsetof(x64emu_t, regs[_AX])); // x9..x15, x16,x17,x18 those needs to be saved by caller
STPx_S7_offset(xRDX, xRBX, xEmu, offsetof(x64emu_t, regs[_DX])); // but x18 is R8 wich is lost, so it's fine to not save it?
STPx_S7_offset(xRSP, xRBP, xEmu, offsetof(x64emu_t, regs[_SP]));
STPx_S7_offset(xRSI, xRDI, xEmu, offsetof(x64emu_t, regs[_SI]));
STPx_S7_offset(xR8, xR9, xEmu, offsetof(x64emu_t, regs[_R8]));
}
TABLE64(reg, (uintptr_t)fnc);
BLR(reg);
if(ret>=0) {
MOVx_REG(ret, xEmu);
}
if(ret!=-2) {
LDPx_S7_postindex(xEmu, savereg, xSP, 16);
#define GO(A, B) if(ret==x##A) { \
LDRx_U12(x##B, xEmu, offsetof(x64emu_t, regs[_##B])); \
} else if(ret==x##B) { \
LDRx_U12(x##A, xEmu, offsetof(x64emu_t, regs[_##A])); \
} else { \
LDPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A])); \
}
GO(RAX, RCX);
GO(RDX, RBX);
GO(RSP, RBP);
GO(RSI, RDI);
GO(R8, R9);
#undef GO
}
fpu_popcache(dyn, ninst, reg);
if(saveflags) {
LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
}
SET_NODF();
}
void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int segment)
{
int32_t j32;
MAYUSE(j32);
MESSAGE(LOG_DUMP, "Get %s Offset\n", (segment==_FS)?"FS":"GS");
int t1 = x1, t2 = x4;
if(reg==t1) ++t1;
if(reg==t2) ++t2;
LDRw_U12(t2, xEmu, offsetof(x64emu_t, segs_serial[segment]));
LDRx_U12(reg, xEmu, offsetof(x64emu_t, segs_offs[segment]));
if(segment==_GS) {
CBNZw_MARKSEG(t2); // fast check
} else {
LDRx_U12(t1, xEmu, offsetof(x64emu_t, context));
LDRw_U12(t1, t1, offsetof(box64context_t, sel_serial));
SUBw_REG(t1, t1, t2);
CBZw_MARKSEG(t1);
}
MOVZw(x1, segment);
call_c(dyn, ninst, GetSegmentBaseEmu, t2, reg, 1, 0);
MARKSEG;
MESSAGE(LOG_DUMP, "----%s Offset\n", (segment==_FS)?"FS":"GS");
}
// x87 stuffs
static void x87_reset(dynarec_arm_t* dyn, int ninst)
{
#if STEP > 1
for (int i=0; i<8; ++i)
dyn->x87cache[i] = -1;
dyn->x87stack = 0;
#endif
}
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
{
#if STEP > 1
if(!dyn->x87stack)
return;
MESSAGE(LOG_DUMP, "\tSynch x87 Stackcount (%d)\n", dyn->x87stack);
int a = dyn->x87stack;
// Add x87stack to emu fpu_stack
LDRx_U12(scratch, xEmu, offsetof(x64emu_t, fpu_stack));
if(a>0) {
ADDx_U12(scratch, scratch, a);
} else {
SUBx_U12(scratch, scratch, -a);
}
STRx_U12(scratch, xEmu, offsetof(x64emu_t, fpu_stack));
// Sub x87stack to top, with and 7
LDRx_U12(scratch, xEmu, offsetof(x64emu_t, top));
if(a>0) {
SUBx_U12(scratch, scratch, a);
} else {
ADDx_U12(scratch, scratch, -a);
}
ADDx_U12(scratch, scratch, 7);
STRx_U12(scratch, xEmu, offsetof(x64emu_t, top));
// reset x87stack
dyn->x87stack = 0;
MESSAGE(LOG_DUMP, "\t------x87 Stackcount\n");
#endif
}
int x87_do_push(dynarec_arm_t* dyn, int ninst)
{
#if STEP > 1
dyn->x87stack+=1;
// move all regs in cache, and find a free one
int ret = -1;
for(int i=0; i<8; ++i)
if(dyn->x87cache[i]!=-1)
++dyn->x87cache[i];
else if(ret==-1) {
dyn->x87cache[i] = 0;
ret=dyn->x87reg[i]=fpu_get_reg_x87(dyn);
}
return ret;
#else
return 0;
#endif
}
void x87_do_push_empty(dynarec_arm_t* dyn, int ninst, int s1)
{
#if STEP > 1
dyn->x87stack+=1;
// move all regs in cache
for(int i=0; i<8; ++i)
if(dyn->x87cache[i]!=-1)
++dyn->x87cache[i];
if(s1)
x87_stackcount(dyn, ninst, s1);
#endif
}
void x87_do_pop(dynarec_arm_t* dyn, int ninst)
{
#if STEP > 1
dyn->x87stack-=1;
// move all regs in cache, poping ST0
for(int i=0; i<8; ++i)
if(dyn->x87cache[i]!=-1) {
--dyn->x87cache[i];
if(dyn->x87cache[i]==-1) {
fpu_free_reg(dyn, dyn->x87reg[i]);
dyn->x87reg[i] = -1;
}
}
#endif
}
static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
#if STEP > 1
int ret = 0;
for (int i=0; i<8 && !ret; ++i)
if(dyn->x87cache[i] != -1)
ret = 1;
if(!ret && !dyn->x87stack) // nothing to do
return;
MESSAGE(LOG_DUMP, "\tPurge x87 Cache and Synch Stackcount (%+d)\n", dyn->x87stack);
int a = dyn->x87stack;
if(a!=0) {
// reset x87stack
dyn->x87stack = 0;
// Add x87stack to emu fpu_stack
LDRx_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
if(a>0) {
ADDx_U12(s2, s2, a);
} else {
SUBx_U12(s2, s2, -a);
}
STRx_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
// Sub x87stack to top, with and 7
LDRx_U12(s2, xEmu, offsetof(x64emu_t, top));
// update tags (and top at the same time)
if(a>0) {
// new tag to fulls
MOVZw(s3, 0);
ADDx_U12(s1, xEmu, offsetof(x64emu_t, p_regs));
for (int i=0; i<a; ++i) {
SUBw_U12(s2, s2, 1);
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + st)&7
STRw_REG_LSL2(s3, s1, s2);
}
} else {
// empty tags
MOVZw(s3, 0b11);
ADDx_U12(s1, xEmu, offsetof(x64emu_t, p_regs));
for (int i=0; i<-a; ++i) {
STRw_REG_LSL2(s3, s1, s2);
ADDw_U12(s2, s2, 1);
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + st)&7
}
}
STRw_U12(s2, xEmu, offsetof(x64emu_t, top));
} else {
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
}
if(ret!=0) {
// --- set values
// prepare offset to fpu => s1
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
// Get top
// loop all cache entries
for (int i=0; i<8; ++i)
if(dyn->x87cache[i]!=-1) {
ADDw_U12(s3, s2, dyn->x87cache[i]);
ANDw_mask(s3, s3, 0b011111, 1); // (emu->top + st)&7
VSTR64_REG_LSL3(dyn->x87reg[i], s1, s3);
fpu_free_reg(dyn, dyn->x87reg[i]);
dyn->x87reg[i] = -1;
dyn->x87cache[i] = -1;
}
}
#endif
}
#ifdef HAVE_TRACE
static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
#if STEP > 1
x87_stackcount(dyn, ninst, s1);
int ret = 0;
for (int i=0; (i<8) && (!ret); ++i)
if(dyn->x87cache[i] != -1)
ret = 1;
if(!ret) // nothing to do
return;
// prepare offset to fpu => s1
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
// Get top
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
// loop all cache entries
for (int i=0; i<8; ++i)
if(dyn->x87cache[i]!=-1) {
ADDw_U12(s3, s2, dyn->x87cache[i]);
ANDw_mask(s3, s3, 0b011111, 1); // (emu->top + i)&7
VLDR64_REG_LSL3(dyn->x87reg[i], s1, s3);
}
#endif
}
#endif
int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
{
#if STEP > 1
// search in cache first
for (int i=0; i<8; ++i)
if(dyn->x87cache[i]==st)
return i;
MESSAGE(LOG_DUMP, "\tCreate x87 Cache for ST%d\n", st);
// get a free spot
int ret = -1;
for (int i=0; (i<8) && (ret==-1); ++i)
if(dyn->x87cache[i]==-1)
ret = i;
// found, setup and grab the value
dyn->x87cache[ret] = st;
dyn->x87reg[ret] = fpu_get_reg_x87(dyn);
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
int a = st - dyn->x87stack;
if(a) {
if(a<0) {
SUBw_U12(s2, s2, -a);
} else {
ADDw_U12(s2, s2, a);
}
ANDw_mask(s2, s2, 0b011111, 1);
}
VLDR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
return ret;
#else
return 0;
#endif
}
int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a)
{
#if STEP > 1
return dyn->x87reg[x87_get_cache(dyn, ninst, s1, s2, a)];
#else
return 0;
#endif
}
void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
{
#if STEP > 1
x87_stackcount(dyn, ninst, s1);
int ret = -1;
for (int i=0; (i<8) && (ret==-1); ++i)
if(dyn->x87cache[i] == st)
ret = i;
if(ret==-1) // nothing to do
return;
MESSAGE(LOG_DUMP, "\tRefresh x87 Cache for ST%d\n", st);
// prepare offset to fpu => s1
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
// Get top
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
// Update
if(st) {
ADDw_U12(s2, s2, st);
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + i)&7
}
VLDR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
MESSAGE(LOG_DUMP, "\t--------x87 Cache for ST%d\n", st);
#endif
}
void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
{
#if STEP > 1
x87_stackcount(dyn, ninst, s1);
int ret = -1;
for (int i=0; (i<8) && (ret==-1); ++i)
if(dyn->x87cache[i] == st)
ret = i;
if(ret==-1) // nothing to do
return;
MESSAGE(LOG_DUMP, "\tForget x87 Cache for ST%d\n", st);
// prepare offset to fpu => s1
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
// Get top
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
// Update
if(st) {
ADDw_U12(s2, s2, st);
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + i)&7
}
VLDR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
MESSAGE(LOG_DUMP, "\t--------x87 Cache for ST%d\n", st);
// and forget that cache
fpu_free_reg(dyn, dyn->x87reg[ret]);
dyn->x87cache[ret] = -1;
dyn->x87reg[ret] = -1;
#endif
}
void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
{
#if STEP > 1
// search in cache first
for (int i=0; i<8; ++i)
if(dyn->x87cache[i]==st) {
// refresh the value
MESSAGE(LOG_DUMP, "\tRefresh x87 Cache for ST%d\n", st);
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
int a = st - dyn->x87stack;
if(a<0) {
SUBw_U12(s2, s2, -a);
} else {
ADDw_U12(s2, s2, a);
}
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + i)&7
VLDR64_REG_LSL3(dyn->x87reg[i], s1, s2);
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
// ok
return;
}
// Was not in the cache? creating it....
MESSAGE(LOG_DUMP, "\tCreate x87 Cache for ST%d\n", st);
// get a free spot
int ret = -1;
for (int i=0; (i<8) && (ret==-1); ++i)
if(dyn->x87cache[i]==-1)
ret = i;
// found, setup and grab the value
dyn->x87cache[ret] = st;
dyn->x87reg[ret] = fpu_get_reg_x87(dyn);
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
int a = st - dyn->x87stack;
if(a<0) {
SUBw_U12(s2, s2, -a);
} else {
ADDw_U12(s2, s2, a);
}
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + i)&7
VLDR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
#endif
}
static int round_map[] = {0, 2, 1, 3}; // map x64 -> arm round flag
// Set rounding according to cw flags, return reg to restore flags
int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
LDRH_U12(s1, xEmu, offsetof(x64emu_t, cw));
UBFXx(s2, s1, 10, 2); // extract round...
MOV64x(s1, (uintptr_t)round_map);
LDRw_REG_LSL2(s2, s1, s2);
VMRS(s1); // get fpscr
MOVx_REG(s3, s1);
BFIx(s1, s2, 22, 2); // inject new round
VMSR(s1); // put new fpscr
return s3;
}
// Set rounding according to mxcsr flags, return reg to restore flags
int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
LDRH_U12(s1, xEmu, offsetof(x64emu_t, mxcsr));
UBFXx(s2, s1, 13, 2); // extract round...
MOV64x(s1, (uintptr_t)round_map);
LDRw_REG_LSL2(s2, s1, s2);
VMRS(s1); // get fpscr
MOVx_REG(s3, s1);
BFIx(s1, s2, 22, 2); // inject new round
VMSR(s1); // put new fpscr
return s3;
}
// Restore round flag
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1)
{
VMSR(s1); // put back fpscr
}
// MMX helpers
static void mmx_reset(dynarec_arm_t* dyn, int ninst)
{
#if STEP > 1
for (int i=0; i<8; ++i)
dyn->mmxcache[i] = -1;
#endif
}
// get neon register for a MMX reg, create the entry if needed
int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
{
#if STEP > 1
if(dyn->mmxcache[a]!=-1)
return dyn->mmxcache[a];
int ret = dyn->mmxcache[a] = fpu_get_reg_emm(dyn, a);
VLDR64_U12(ret, xEmu, offsetof(x64emu_t, mmx87[a]));
return ret;
#else
return 0;
#endif
}
// get neon register for a MMX reg, but don't try to synch it if it needed to be created
int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a)
{
#if STEP > 1
if(dyn->mmxcache[a]!=-1)
return dyn->mmxcache[a];
int ret = dyn->mmxcache[a] = fpu_get_reg_emm(dyn, a);
return ret;
#else
return 0;
#endif
}
// purge the MMX cache only(needs 3 scratch registers)
static void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
{
#if STEP > 1
int old = -1;
for (int i=0; i<8; ++i)
if(dyn->mmxcache[i]!=-1) {
if (old==-1) {
MESSAGE(LOG_DUMP, "\tPurge MMX Cache ------\n");
++old;
}
VSTR64_U12(dyn->mmxcache[i], xEmu, offsetof(x64emu_t, mmx87[i]));
fpu_free_reg(dyn, dyn->mmxcache[i]);
dyn->mmxcache[i] = -1;
}
if(old!=-1) {
MESSAGE(LOG_DUMP, "\t------ Purge MMX Cache\n");
}
#endif
}
#ifdef HAVE_TRACE
static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
{
#if STEP > 1
for (int i=0; i<8; ++i)
if(dyn->mmxcache[i]!=-1) {
VLDR64_U12(dyn->mmxcache[i], xEmu, offsetof(x64emu_t, mmx87[i]));
}
#endif
}
#endif
// SSE / SSE2 helpers
static void sse_reset(dynarec_arm_t* dyn, int ninst)
{
#if STEP > 1
for (int i=0; i<16; ++i)
dyn->ssecache[i] = -1;
#endif
}
// get neon register for a SSE reg, create the entry if needed
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
{
#if STEP > 1
if(dyn->ssecache[a]!=-1)
return dyn->ssecache[a];
int ret = dyn->ssecache[a] = fpu_get_reg_xmm(dyn, a);
VLDR128_U12(ret, xEmu, offsetof(x64emu_t, xmm[a]));
return ret;
#else
return 0;
#endif
}
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a)
{
#if STEP > 1
if(dyn->ssecache[a]!=-1)
return dyn->ssecache[a];
int ret = dyn->ssecache[a] = fpu_get_reg_xmm(dyn, a);
return ret;
#else
return 0;
#endif
}
// purge the SSE cache for XMM0..XMM7 (to use before function native call)
void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1)
{
#if STEP > 1
int old = -1;
for (int i=0; i<8; ++i)
if(dyn->ssecache[i]!=-1) {
if (old==-1) {
MESSAGE(LOG_DUMP, "\tPurge XMM0..7 Cache ------\n");
++old;
}
VSTR128_U12(dyn->ssecache[i], xEmu, offsetof(x64emu_t, xmm[i]));
fpu_free_reg(dyn, dyn->ssecache[i]);
dyn->ssecache[i] = -1;
}
if(old!=-1) {
MESSAGE(LOG_DUMP, "\t------ Purge XMM0..7 Cache\n");
}
#endif
}
// purge the SSE cache only
static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
{
#if STEP > 1
int old = -1;
for (int i=0; i<16; ++i)
if(dyn->ssecache[i]!=-1) {
if (old==-1) {
MESSAGE(LOG_DUMP, "\tPurge SSE Cache ------\n");
++old;
}
VSTR128_U12(dyn->ssecache[i], xEmu, offsetof(x64emu_t, xmm[i]));
fpu_free_reg(dyn, dyn->ssecache[i]);
dyn->ssecache[i] = -1;
}
if(old!=-1) {
MESSAGE(LOG_DUMP, "\t------ Purge SSE Cache\n");
}
#endif
}
#ifdef HAVE_TRACE
static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
{
#if STEP > 1
for (int i=0; i<16; ++i)
if(dyn->ssecache[i]!=-1) {
VSTR128_U12(dyn->ssecache[i], xEmu, offsetof(x64emu_t, xmm[i]));
}
#endif
}
#endif
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
{
#if STEP > 1
// only SSE regs needs to be push back to xEmu
int n=0;
for (int i=0; i<16; i++)
if(dyn->ssecache[i]!=-1)
++n;
if(!n)
return;
MESSAGE(LOG_DUMP, "\tPush XMM Cache (%d)------\n", n);
for (int i=0; i<16; ++i)
if(dyn->ssecache[i]!=-1) {
VSTR128_U12(dyn->ssecache[i], xEmu, offsetof(x64emu_t, xmm[i]));
}
MESSAGE(LOG_DUMP, "\t------- Push XMM Cache (%d)\n", n);
#endif
}
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1)
{
#if STEP > 1
// only SSE regs needs to be pop back from xEmu
int n=0;
for (int i=0; i<16; i++)
if(dyn->ssecache[i]!=-1)
++n;
if(!n)
return;
MESSAGE(LOG_DUMP, "\tPop XMM Cache (%d)------\n", n);
for (int i=0; i<16; ++i)
if(dyn->ssecache[i]!=-1) {
VLDR128_U12(dyn->ssecache[i], xEmu, offsetof(x64emu_t, xmm[i]));
}
MESSAGE(LOG_DUMP, "\t------- Pop XMM Cache (%d)\n", n);
#endif
}
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
x87_purgecache(dyn, ninst, s1, s2, s3);
mmx_purgecache(dyn, ninst, s1);
sse_purgecache(dyn, ninst, s1);
fpu_reset_reg(dyn);
}
#ifdef HAVE_TRACE
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
x87_reflectcache(dyn, ninst, s1, s2, s3);
if(trace_emm)
mmx_reflectcache(dyn, ninst, s1);
if(trace_xmm)
sse_reflectcache(dyn, ninst, s1);
}
#endif
void fpu_reset(dynarec_arm_t* dyn, int ninst)
{
x87_reset(dyn, ninst);
mmx_reset(dyn, ninst);
sse_reset(dyn, ninst);
fpu_reset_reg(dyn);
}
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
ANDw_mask(s3, s1, 0b011011, 0b000010); // mask=0xE0
LSRw(s3, s3, 5);
MOV64x(s4, (uintptr_t)GetParityTab());
LDRw_REG_LSL2(s4, s4, s3);
ANDw_mask(s3, s1, 0, 0b000100); //0x1f
LSRw_REG(s4, s4, s3);
MVNw_REG(s4, s4);
BFIw(xFlags, s4, F_PF, 1);
}
+944
View File
@@ -0,0 +1,944 @@
#ifndef __DYNAREC_ARM64_HELPER_H__
#define __DYNAREC_ARM64_HELPER_H__
// undef to get Close to SSE Float->int conversions
//#define PRECISE_CVT
#if STEP == 0
#include "dynarec_arm64_pass0.h"
#elif STEP == 1
#include "dynarec_arm64_pass1.h"
#elif STEP == 2
#include "dynarec_arm64_pass2.h"
#elif STEP == 3
#include "dynarec_arm64_pass3.h"
#endif
#include "debug.h"
#include "arm64_emitter.h"
#include "../emu/x64primop.h"
#define F8 *(uint8_t*)(addr++)
#define F8S *(int8_t*)(addr++)
#define F16 *(uint16_t*)(addr+=2, addr-2)
#define F16S *(int16_t*)(addr+=2, addr-2)
#define F32 *(uint32_t*)(addr+=4, addr-4)
#define F32S *(int32_t*)(addr+=4, addr-4)
#define F32S64 (uint64_t)(int64_t)F32S
#define F64 *(uint64_t*)(addr+=8, addr-8)
#define PK(a) *(uint8_t*)(addr+a)
#define PK16(a) *(uint16_t*)(addr+a)
#define PK32(a) *(uint32_t*)(addr+a)
#define PK64(a) *(uint64_t*)(addr+a)
#define PKip(a) *(uint8_t*)(ip+a)
// GETGD get x64 register in gd
#define GETGD gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3)
//GETED can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
#define GETED(D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
LDRxw_U12(x1, wback, fixedaddress); \
ed = x1; \
}
#define GETEDx(D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 3, rex, 0, D); \
LDRx_U12(x1, wback, fixedaddress); \
ed = x1; \
}
#define GETEDw(D) if((nextop&0xC0)==0xC0) { \
ed = xEAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 2, rex, 0, D); \
LDRw_U12(x1, wback, fixedaddress); \
ed = x1; \
}
//GETEDH can use hint for ed, and r1 or r2 for wback (depending on hint). wback is 0 if ed is xEAX..xEDI
#define GETEDH(hint, D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
LDRxw_U12(hint, wback, fixedaddress); \
ed = hint; \
}
//GETEDW can use hint for wback and ret for ed. wback is 0 if ed is xEAX..xEDI
#define GETEDW(hint, ret, D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
MOVxw_REG(ret, ed); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
ed = ret; \
LDRxw_U12(ed, wback, fixedaddress); \
}
// Write back ed in wback (if wback not 0)
#define WBACK if(wback) {STRxw_U12(ed, wback, fixedaddress);}
// Write back ed in wback (if wback not 0)
#define WBACKx if(wback) {STRx_U12(ed, wback, fixedaddress);}
// Write back ed in wback (if wback not 0)
#define WBACKw if(wback) {STRw_U12(ed, wback, fixedaddress);}
// Send back wb to either ed or wback
#define SBACK(wb) if(wback) {STRxw(wb, wback, fixedaddress);} else {MOVxw_REG(ed, wb);}
//GETEDO can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
#define GETEDO(O, D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, D); \
LDRxw_REG(x1, wback, O); \
ed = x1; \
}
#define WBACKO(O) if(wback) {STRxw_REG(ed, wback, O);}
//FAKEELike GETED, but doesn't get anything
#define FAKEED if(!MODREG) { \
addr = fakeed(dyn, addr, ninst, nextop); \
}
// GETGW extract x64 register in gd, that is i
#define GETGW(i) gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); UXTHw(i, gd); gd = i;
// GETGW extract x64 register in gd, that is i, Signed extented
#define GETSGW(i) gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); SXTHw(i, gd); gd = i;
//GETEWW will use i for ed, and can use w for wback.
#define GETEWW(w, i, D) if(MODREG) { \
wback = xRAX+(nextop&7)+(rex.b<<3);\
UXTHw(i, wback); \
ed = i; \
wb1 = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 0xfff<<1, (1<<1)-1, rex, 0, D); \
LDRH_U12(i, wback, fixedaddress); \
ed = i; \
wb1 = 1; \
}
//GETEW will use i for ed, and can use r3 for wback.
#define GETEW(i, D) if(MODREG) { \
wback = xRAX+(nextop&7)+(rex.b<<3);\
UXTHw(i, wback); \
ed = i; \
wb1 = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, (1<<1)-1, rex, 0, D); \
LDRH_U12(i, wback, fixedaddress); \
ed = i; \
wb1 = 1; \
}
//GETSEW will use i for ed, and can use r3 for wback. This is the Signed version
#define GETSEW(i, D) if(MODREG) { \
wback = xRAX+(nextop&7)+(rex.b<<3);\
SXTHw(i, wback); \
ed = i; \
wb1 = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, (1<<1)-1, rex, 0, D); \
LDRSHx_U12(i, wback, fixedaddress);\
ed = i; \
wb1 = 1; \
}
// Write ed back to original register / memory
#define EWBACK if(wb1) {STRH_U12(ed, wback, fixedaddress);} else {BFIx(wback, ed, 0, 16);}
// Write w back to original register / memory
#define EWBACKW(w) if(wb1) {STRH_U12(w, wback, fixedaddress);} else {BFIx(wback, w, 0, 16);}
// Write back gd in correct register
#define GWBACK BFIx((xRAX+((nextop&0x38)>>3)+(rex.r<<3)), gd, 0, 16);
//GETEB will use i for ed, and can use r3 for wback.
#define GETEB(i, D) if(MODREG) { \
if(rex.rex) { \
wback = xRAX+(nextop&7)+(rex.b<<3); \
wb2 = 0; \
} else { \
wback = (nextop&7); \
wb2 = (wback>>2)*8; \
wback = xRAX+(wback&3); \
} \
UBFXx(i, wback, wb2, 8); \
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, 0, D); \
LDRB_U12(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
}
//GETEBO will use i for ed, i is also Offset, and can use r3 for wback.
#define GETEBO(i) if((nextop&0xC0)==0xC0) { \
wback = (nextop&7); \
wb2 = (wback>>2); \
wback = xEAX+(wback&3); \
UBFXx(i, wback, wb2, 8);\
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0); \
ADD_REG_LSL_IMM5(wback, wback, i, 0); \
LDRB_IMM9(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
}
//GETSEB sign extend EB, will use i for ed, and can use r3 for wback.
#define GETSEB(i, D) if(MODREG) { \
if(rex.rex) { \
wback = xRAX+(nextop&7)+(rex.b<<3); \
wb2 = 0; \
} else { \
wback = (nextop&7); \
wb2 = (wback>>2)*8; \
wback = xRAX+(wback&3); \
} \
SBFXx(i, wback, wb2, 8); \
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, 0, D); \
LDRSBx_U12(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
}
// Write eb (ed) back to original register / memory
#define EBBACK if(wb1) {STRB_U12(ed, wback, fixedaddress);} else {BFIx(wback, ed, wb2, 8);}
//GETGB will use i for gd
#define GETGB(i) if(rex.rex) { \
gb1 = xRAX+((nextop&0x38)>>3)+(rex.r<<3); \
gb2 = 0; \
} else { \
gd = (nextop&0x38)>>3; \
gb2 = ((gd&4)>>2); \
gb1 = xRAX+(gd&3); \
} \
gd = i; \
UBFXx(gd, gb1, gb2, 8);
//GETSGB signe extend GB, will use i for gd
#define GETSGB(i) if(rex.rex) { \
gb1 = xRAX+((nextop&0x38)>>3)+(rex.r<<3); \
gb2 = 0; \
} else { \
gd = (nextop&0x38)>>3; \
gb2 = ((gd&4)>>2); \
gb1 = xRAX+(gd&3); \
} \
gd = i; \
SBFXx(gd, gb1, gb2, 8);
// Write gb (gd) back to original register / memory
#define GBBACK BFIx(gb1, gd, gb2, 8);
// Get Direction with size Z and based of F_DF flag, on register r ready for LDR/STR fetching
// F_DF is 1<<10, so 1 ROR 11*2 (so F_OF)
#define GETDIR(r, A) \
MOV32w(r, A); /* mask=1<<10 */ \
TSTw_mask(xFlags, 0b010110, 0); \
CNEGx(r, r, cNE)
// CALL will use x7 for the call address. Return value can be put in ret (unless ret is -1)
// R0 will not be pushed/popd if ret is -2
#define CALL(F, ret) call_c(dyn, ninst, F, x7, ret, 1, 0)
// CALL_ will use x7 for the call address. Return value can be put in ret (unless ret is -1)
// R0 will not be pushed/popd if ret is -2
#define CALL_(F, ret, reg) call_c(dyn, ninst, F, x7, ret, 1, reg)
// CALL_S will use x7 for the call address. Return value can be put in ret (unless ret is -1)
// R0 will not be pushed/popd if ret is -2. Flags are not save/restored
#define CALL_S(F, ret) call_c(dyn, ninst, F, x7, ret, 0, 0)
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = (uintptr_t)dyn->arm_size;}
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = (uintptr_t)dyn->arm_size;}
#define GETMARK2 ((dyn->insts)?dyn->insts[ninst].mark2:(dyn->arm_size+4))
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = (uintptr_t)dyn->arm_size;}
#define GETMARK3 ((dyn->insts)?dyn->insts[ninst].mark3:(dyn->arm_size+4))
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = (uintptr_t)dyn->arm_size;}
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = (uintptr_t)dyn->arm_size;}
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = (uintptr_t)dyn->arm_size;}
#define GETMARKLOCK ((dyn->insts)?dyn->insts[ninst].marklock:(dyn->arm_size+4))
// Branch to MARK if cond (use j32)
#define B_MARK(cond) \
j32 = GETMARK-(dyn->arm_size); \
Bcond(cond, j32)
// Branch to MARK unconditionnal (use j32)
#define B_MARK_nocond \
j32 = GETMARK-(dyn->arm_size); \
B(j32)
// Branch to MARK if reg is not 0 (use j32)
#define CBNZx_MARK(reg) \
j32 = GETMARK-(dyn->arm_size); \
CBNZx(reg, j32)
// Branch to MARK if reg is not 0 (use j32)
#define CBNZw_MARK(reg) \
j32 = GETMARK-(dyn->arm_size); \
CBNZw(reg, j32)
// Branch to MARK2 if cond (use j32)
#define B_MARK2(cond) \
j32 = GETMARK2-(dyn->arm_size); \
Bcond(cond, j32)
// Branch to MARK2 unconditionnal (use j32)
#define B_MARK2_nocond \
j32 = GETMARK2-(dyn->arm_size); \
B(j32)
// Branch to MARK2 if reg is not 0 (use j32)
#define CBNZx_MARK2(reg) \
j32 = GETMARK2-(dyn->arm_size); \
CBNZx(reg, j32)
// Test bit N of A and branch to MARK2 if set
#define TBNZ_MARK2(A, N) \
j32 = GETMARK2-(dyn->arm_size); \
TBNZ(A, N, j32)
// Branch to MARK3 if cond (use j32)
#define B_MARK3(cond) \
j32 = GETMARK3-(dyn->arm_size); \
Bcond(cond, j32)
// Branch to MARK3 unconditionnal (use j32)
#define B_MARK3_nocond \
j32 = GETMARK3-(dyn->arm_size); \
B(j32)
// Branch to MARK3 if reg is not 0 (use j32)
#define CBNZx_MARK3(reg) \
j32 = GETMARK3-(dyn->arm_size); \
CBNZx(reg, j32)
// Test bit N of A and branch to MARK3 if set
#define TBNZ_MARK3(A, N) \
j32 = GETMARK3-(dyn->arm_size); \
TBNZ(A, N, j32)
// Test bit N of A and branch to MARK3 if not set
#define TBZ_MARK3(A, N) \
j32 = GETMARK3-(dyn->arm_size); \
TBZ(A, N, j32)
// Branch to next instruction if cond (use j32)
#define B_NEXT(cond) \
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
Bcond(cond, j32)
// Branch to next instruction unconditionnal (use j32)
#define B_NEXT_nocond \
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0;\
B(j32)
// Branch to next instruction if reg is 0 (use j32)
#define CBZw_NEXT(reg) \
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
CBZw(reg, j32)
// Branch to next instruction if reg is 0 (use j32)
#define CBZx_NEXT(reg) \
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
CBZx(reg, j32)
// Branch to MARKSEG if cond (use j32)
#define B_MARKSEG(cond) \
j32 = GETMARKSEG-(dyn->arm_size); \
Bcond(cond, j32)
// Branch to MARKSEG if reg is 0 (use j32)
#define CBZw_MARKSEG(reg) \
j32 = GETMARKSEG-(dyn->arm_size); \
CBZw(reg, j32)
// Branch to MARKSEG if reg is not 0 (use j32)
#define CBNZw_MARKSEG(reg) \
j32 = GETMARKSEG-(dyn->arm_size); \
CBNZw(reg, j32)
// Branch to MARKLOCK if cond (use j32)
#define B_MARKLOCK(cond) \
j32 = GETMARKLOCK-(dyn->arm_size); \
Bcond(cond, j32)
// Branch to MARKLOCK if reg is not 0 (use j32)
#define CBNZx_MARKLOCK(reg) \
j32 = GETMARKLOCK-(dyn->arm_size); \
CBNZx(reg, j32)
#define IFX(A) if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(A)))
#define IFXX(A) if(dyn->insts && (dyn->insts[ninst].x64.need_flags==(A)))
#define IFX2X(A, B) if(dyn->insts && (dyn->insts[ninst].x64.need_flags==(A) || dyn->insts[ninst].x64.need_flags==(B) || dyn->insts[ninst].x64.need_flags==((A)|(B))))
#define IFXN(A, B) if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(A) && !(dyn->insts[ninst].x64.need_flags&(B))))
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
#define FCOM(s1, s2, s3) \
LDRH_U12(s3, xEmu, offsetof(x64emu_t, sw)); /*offset is 8bits right?*/\
MOV32w(s1, 0b01000111); \
BICw_REG_LSL(s3, s3, s1, 8); \
CSETw(s1, cMI); /* 1 if less than, 0 else */ \
MOV32w(s2, 0b01000101); /* unordered */ \
CSELw(s1, s2, s1, cVS); \
MOV32w(s2, 0b01000000); /* zero */ \
CSELw(s1, s2, s1, cEQ); \
/* greater than leave 0 */ \
ORRw_REG_LSL(s3, s3, s1, 8); \
STRH_U12(s3, xEmu, offsetof(x64emu_t, sw))
// Generate FCOMI with s1 and s2 scratch regs (the VCMP is already done)
#define FCOMI(s1, s2) \
IFX(X_CF|X_PF|X_ZF|X_PEND) { \
MOV32w(s2, 0b01000101); \
BICw_REG(xFlags, xFlags, s2); \
CSETw(s1, cMI); /* 1 if less than, 0 else */ \
/*s2 already set */ /* unordered */ \
CSELw(s1, s2, s1, cVS); \
MOV32w(s2, 0b01000000); /* zero */ \
CSELw(s1, s2, s1, cEQ); \
/* greater than leave 0 */ \
ORRw_REG(xFlags, xFlags, s1); \
} \
SET_DFNONE(s1); \
IFX(X_OF|X_PEND) { \
BFCw(xFlags, F_OF, 1); \
} \
IFX(X_AF|X_PEND) { \
BFCw(xFlags, F_AF, 1); \
} \
IFX(X_SF|X_PEND) { \
BFCw(xFlags, F_SF, 1); \
} \
#define STORE_REG(A) STRx_U12(x##A, xEmu, offsetof(x64emu_t, regs[_##A]))
#define STORE_XEMU_REGS(A) \
STORE_REG(RAX); \
STORE_REG(RCX); \
STORE_REG(RDX); \
STORE_REG(RBX); \
STORE_REG(RSP); \
STORE_REG(RBP); \
STORE_REG(RSI); \
STORE_REG(RDI); \
STORE_REG(R8); \
STORE_REG(R9); \
STORE_REG(R10); \
STORE_REG(R11); \
STORE_REG(R12); \
STORE_REG(R13); \
STORE_REG(R14); \
STORE_REG(R15); \
STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); \
if(A) {STRx_U12(A, xEmu, offsetof(x64emu_t, ip));}
#define LOAD_REG(A) LDRx_U12(x##A, xEmu, offsetof(x64emu_t, regs[_##A]))
#define LOAD_XEMU_REGS(A) \
LOAD_REG(RAX); \
LOAD_REG(RCX); \
LOAD_REG(RDX); \
LOAD_REG(RBX); \
LOAD_REG(RSP); \
LOAD_REG(RBP); \
LOAD_REG(RSI); \
LOAD_REG(RDI); \
LOAD_REG(R8); \
LOAD_REG(R9); \
LOAD_REG(R10); \
LOAD_REG(R11); \
LOAD_REG(R12); \
LOAD_REG(R13); \
LOAD_REG(R14); \
LOAD_REG(R15); \
LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); \
if(A) {LDRx_U12(A, xEmu, offsetof(x64emu_t, ip));}
#define STORE_XEMU_MINIMUM(A) \
STORE_REG(RAX); \
STORE_REG(RCX); \
STORE_REG(RDX); \
STORE_REG(RBX); \
STORE_REG(RSP); \
STORE_REG(RBP); \
STORE_REG(RSI); \
STORE_REG(RDI); \
STORE_REG(R8); \
STORE_REG(R9); \
STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); \
if(A) {STRx_U12(A, xEmu, offsetof(x64emu_t, ip));}
#define STORE_XEMU_CALL(A) \
if(A) {STPx_S7_offset(xFlags, A, xEmu, offsetof(x64emu_t, eflags));} \
else {STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));}
#define LOAD_XEMU_CALL(A) \
if(A) {LDPx_S7_offset(xFlags, A, xEmu, offsetof(x64emu_t, eflags));} \
else {LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));}; \
if(A==xRIP) dyn->last_ip = 0
#define SET_DFNONE(S) if(!dyn->dfnone) {MOVZw(S, d_none); STRw_U12(S, xEmu, offsetof(x64emu_t, df)); dyn->dfnone=1;}
#define SET_DF(S, N) if((N)!=d_none) {MOVZw(S, (N)); STRw_U12(S, xEmu, offsetof(x64emu_t, df)); dyn->dfnone=0;} else SET_DFNONE(S)
#define SET_NODF() dyn->dfnone = 0
#define SET_DFOK() dyn->dfnone = 1
#ifndef READFLAGS
#define READFLAGS(A) \
if(((A)!=X_PEND) && dyn->state_flags!=SF_SET) { \
if(dyn->state_flags!=SF_PENDING) { \
LDRw_U12(x3, xEmu, offsetof(x64emu_t, df)); \
j32 = (GETMARKF)-(dyn->arm_size); \
CBZw(x3, j32); \
} \
CALL_(UpdateFlags, -1, 0); \
MARKF; \
dyn->state_flags = SF_SET; \
SET_DFOK(); \
}
#endif
#ifndef SETFLAGS
#define SETFLAGS(A, B) \
if(dyn->state_flags!=SF_SET && B==SF_SUBSET && (dyn->insts[ninst].x64.need_flags&(~((A)|X_PEND)))) \
READFLAGS(dyn->insts[ninst].x64.need_flags&(~(A))); \
dyn->state_flags = (B==SF_SUBSET)?SF_SET:B
#endif
#ifndef JUMP
#define JUMP(A)
#endif
#ifndef BARRIER
#define BARRIER(A)
#endif
#ifndef BARRIER_NEXT
#define BARRIER_NEXT(A)
#endif
#define UFLAG_OP1(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A1, xEmu, offsetof(x64emu_t, op1));STRxw_U12(A2, 0, offsetof(x64emu_t, op2));}
#define UFLAG_RES(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {SET_DF(r, A)}
#define UFLAG_IF if(dyn->insts && dyn->insts[ninst].x64.need_flags)
#ifndef DEFAULT
#define DEFAULT *ok = -1; BARRIER(2)
#endif
#ifndef NEW_BARRIER_INST
#define NEW_BARRIER_INST
#endif
#ifndef TABLE64
#define TABLE64(A, V)
#endif
#if STEP < 2
#define GETIP(A)
#define GETIP_(A)
#else
// put value in the Table64 even if not using it for now to avoid difference between Step2 and Step3. Needs to be optimized later...
#define GETIP(A) \
if(dyn->last_ip && ((A)-dyn->last_ip)<0x1000) { \
uint64_t _delta_ip = (A)-dyn->last_ip; \
dyn->last_ip += _delta_ip; \
if(_delta_ip) { \
ADDx_U12(xRIP, xRIP, _delta_ip); \
} \
} else { \
dyn->last_ip = (A); \
TABLE64(xRIP, dyn->last_ip); \
}
#define GETIP_(A) \
if(dyn->last_ip && ((A)-dyn->last_ip)<0x1000) { \
uint64_t _delta_ip = (A)-dyn->last_ip; \
if(_delta_ip) {ADDx_U12(xRIP, xRIP, _delta_ip);}\
} else { \
TABLE64(xRIP, (A)); \
}
#endif
#if STEP < 2
#define PASS2IF(A, B) if(A)
#elif STEP == 2
#define PASS2IF(A, B) if(A) dyn->insts[ninst].pass2choice = B; if(dyn->insts[ninst].pass2choice == B)
#else
#define PASS2IF(A, B) if(dyn->insts[ninst].pass2choice == B)
#endif
#define MODREG ((nextop&0xC0)==0xC0)
void arm64_epilog();
void* arm64_next(x64emu_t* emu, uintptr_t addr);
#ifndef STEPNAME
#define STEPNAME3(N,M) N##M
#define STEPNAME2(N,M) STEPNAME3(N,M)
#define STEPNAME(N) STEPNAME2(N, STEP)
#endif
#define arm_pass STEPNAME(arm_pass)
#define dynarec64_00 STEPNAME(dynarec64_00)
#define dynarec64_0F STEPNAME(dynarec64_0F)
#define dynarec64_64 STEPNAME(dynarec64_64)
#define dynarec64_65 STEPNAME(dynarec64_65)
#define dynarec64_66 STEPNAME(dynarec64_66)
#define dynarec64_67 STEPNAME(dynarec64_67)
#define dynarec64_D8 STEPNAME(dynarec64_D8)
#define dynarec64_D9 STEPNAME(dynarec64_D9)
#define dynarec64_DA STEPNAME(dynarec64_DA)
#define dynarec64_DB STEPNAME(dynarec64_DB)
#define dynarec64_DC STEPNAME(dynarec64_DC)
#define dynarec64_DD STEPNAME(dynarec64_DD)
#define dynarec64_DE STEPNAME(dynarec64_DE)
#define dynarec64_DF STEPNAME(dynarec64_DF)
#define dynarec64_F0 STEPNAME(dynarec64_F0)
#define dynarec64_660F STEPNAME(dynarec64_660F)
#define dynarec64_F20F STEPNAME(dynarec64_F20F)
#define dynarec64_F30F STEPNAME(dynarec64_F30F)
#define geted STEPNAME(geted_)
#define geted16 STEPNAME(geted16_)
#define jump_to_epilog STEPNAME(jump_to_epilog_)
#define jump_to_next STEPNAME(jump_to_next_)
#define ret_to_epilog STEPNAME(ret_to_epilog_)
#define retn_to_epilog STEPNAME(retn_to_epilog_)
#define iret_to_epilog STEPNAME(iret_to_epilog_)
#define call_c STEPNAME(call_c_)
#define grab_segdata STEPNAME(grab_segdata_)
#define emit_cmp8 STEPNAME(emit_cmp8)
#define emit_cmp16 STEPNAME(emit_cmp16)
#define emit_cmp32 STEPNAME(emit_cmp32)
#define emit_cmp8_0 STEPNAME(emit_cmp8_0)
#define emit_cmp16_0 STEPNAME(emit_cmp16_0)
#define emit_cmp32_0 STEPNAME(emit_cmp32_0)
#define emit_test8 STEPNAME(emit_test8)
#define emit_test16 STEPNAME(emit_test16)
#define emit_test32 STEPNAME(emit_test32)
#define emit_add32 STEPNAME(emit_add32)
#define emit_add32c STEPNAME(emit_add32c)
#define emit_add8 STEPNAME(emit_add8)
#define emit_add8c STEPNAME(emit_add8c)
#define emit_sub32 STEPNAME(emit_sub32)
#define emit_sub32c STEPNAME(emit_sub32c)
#define emit_sub8 STEPNAME(emit_sub8)
#define emit_sub8c STEPNAME(emit_sub8c)
#define emit_or32 STEPNAME(emit_or32)
#define emit_or32c STEPNAME(emit_or32c)
#define emit_xor32 STEPNAME(emit_xor32)
#define emit_xor32c STEPNAME(emit_xor32c)
#define emit_and32 STEPNAME(emit_and32)
#define emit_and32c STEPNAME(emit_and32c)
#define emit_or8 STEPNAME(emit_or8)
#define emit_or8c STEPNAME(emit_or8c)
#define emit_xor8 STEPNAME(emit_xor8)
#define emit_xor8c STEPNAME(emit_xor8c)
#define emit_and8 STEPNAME(emit_and8)
#define emit_and8c STEPNAME(emit_and8c)
#define emit_add16 STEPNAME(emit_add16)
#define emit_add16c STEPNAME(emit_add16c)
#define emit_sub16 STEPNAME(emit_sub16)
#define emit_sub16c STEPNAME(emit_sub16c)
#define emit_or16 STEPNAME(emit_or16)
#define emit_or16c STEPNAME(emit_or16c)
#define emit_xor16 STEPNAME(emit_xor16)
#define emit_xor16c STEPNAME(emit_xor16c)
#define emit_and16 STEPNAME(emit_and16)
#define emit_and16c STEPNAME(emit_and16c)
#define emit_inc32 STEPNAME(emit_inc32)
#define emit_inc16 STEPNAME(emit_inc16)
#define emit_inc8 STEPNAME(emit_inc8)
#define emit_dec32 STEPNAME(emit_dec32)
#define emit_dec16 STEPNAME(emit_dec16)
#define emit_dec8 STEPNAME(emit_dec8)
#define emit_adc32 STEPNAME(emit_adc32)
#define emit_adc32c STEPNAME(emit_adc32c)
#define emit_adc8 STEPNAME(emit_adc8)
#define emit_adc8c STEPNAME(emit_adc8c)
#define emit_adc16 STEPNAME(emit_adc16)
#define emit_adc16c STEPNAME(emit_adc16c)
#define emit_sbb32 STEPNAME(emit_sbb32)
#define emit_sbb32c STEPNAME(emit_sbb32c)
#define emit_sbb8 STEPNAME(emit_sbb8)
#define emit_sbb8c STEPNAME(emit_sbb8c)
#define emit_sbb16 STEPNAME(emit_sbb16)
#define emit_sbb16c STEPNAME(emit_sbb16c)
#define emit_neg32 STEPNAME(emit_neg32)
#define emit_neg16 STEPNAME(emit_neg16)
#define emit_neg8 STEPNAME(emit_neg8)
#define emit_shl32 STEPNAME(emit_shl32)
#define emit_shl32c STEPNAME(emit_shl32c)
#define emit_shr32 STEPNAME(emit_shr32)
#define emit_shr32c STEPNAME(emit_shr32c)
#define emit_sar32c STEPNAME(emit_sar32c)
#define emit_rol32c STEPNAME(emit_rol32c)
#define emit_ror32c STEPNAME(emit_ror32c)
#define emit_shrd32c STEPNAME(emit_shrd32c)
#define emit_shld32c STEPNAME(emit_shld32c)
#define emit_pf STEPNAME(emit_pf)
#define x87_do_push STEPNAME(x87_do_push)
#define x87_do_push_empty STEPNAME(x87_do_push_empty)
#define x87_do_pop STEPNAME(x87_do_pop)
#define x87_get_cache STEPNAME(x87_get_cache)
#define x87_get_st STEPNAME(x87_get_st)
#define x87_refresh STEPNAME(x87_refresh)
#define x87_forget STEPNAME(x87_forget)
#define x87_reget_st STEPNAME(x87_reget_st)
#define x87_stackcount STEPNAME(x87_stackcount)
#define x87_setround STEPNAME(x87_setround)
#define x87_restoreround STEPNAME(x87_restoreround)
#define sse_setround STEPNAME(sse_setround)
#define mmx_get_reg STEPNAME(mmx_get_reg)
#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty)
#define sse_get_reg STEPNAME(sse_get_reg)
#define sse_get_reg_empty STEPNAME(sse_get_reg_empty)
#define sse_purge07cache STEPNAME(sse_purge07cache)
#define fpu_pushcache STEPNAME(fpu_pushcache)
#define fpu_popcache STEPNAME(fpu_popcache)
#define fpu_reset STEPNAME(fpu_reset)
#define fpu_purgecache STEPNAME(fpu_purgecache)
#ifdef HAVE_TRACE
#define fpu_reflectcache STEPNAME(fpu_reflectcache)
#endif
/* setup r2 to address pointed by */
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta);
/* setup r2 to address pointed by */
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, int s);
// generic x64 helper
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
void ret_to_epilog(dynarec_arm_t* dyn, int ninst);
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n);
void iret_to_epilog(dynarec_arm_t* dyn, int ninst);
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg);
void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int segment);
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5);
void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4);
void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5);
void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5);
void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4, int s5);
void emit_or32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
void emit_or32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4);
void emit_xor32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
void emit_xor32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4);
void emit_and32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
void emit_and32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4);
void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
//void emit_add16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
//void emit_sub16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
//void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
//void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
//void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_inc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4);
void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_dec32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4);
void emit_dec16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
//void emit_adc32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4, int s5);
void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
//void emit_adc16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
//void emit_sbb32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4, int s5);
void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
//void emit_sbb16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_neg32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4);
void emit_neg16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
//void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
//void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
// x87 helper
// cache of the local stack counter, to avoid upadte at every call
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch);
// fpu push. Return the Dd value to be used
int x87_do_push(dynarec_arm_t* dyn, int ninst);
// fpu push. Do not allocate a cache register. Needs a scratch register to do x87stack synch (or 0 to not do it)
void x87_do_push_empty(dynarec_arm_t* dyn, int ninst, int s1);
// fpu pop. All previous returned Dd should be considered invalid
void x87_do_pop(dynarec_arm_t* dyn, int ninst);
// get cache index for a x87 reg, create the entry if needed
int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a);
// get vfpu register for a x87 reg, create the entry if needed
int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a);
// refresh a value from the cache ->emu (nothing done if value is not cached)
void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
// refresh a value from the cache ->emu and then forget the cache (nothing done if value is not cached)
void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
// refresh the cache value from emu
void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
// Set rounding according to cw flags, return reg to restore flags
int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
// Restore round flag
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1);
// Set rounding according to mxcsr flags, return reg to restore flags
int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
//MMX helpers
// get neon register for a MMX reg, create the entry if needed
int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a);
// get neon register for a MMX reg, but don't try to synch it if it needed to be created
int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
//SSE/SSE2 helpers
// get neon register for a SSE reg, create the entry if needed
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a);
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
// purge the XMM0..XMM7 cache (before function call)
void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1);
// common coproc helpers
// reset the cache
void fpu_reset(dynarec_arm_t* dyn, int ninst);
// purge the FPU cache (needs 3 scratch registers)
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
#ifdef HAVE_TRACE
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
#endif
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1);
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1);
uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog);
//uintptr_t dynarec64_65(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog);
uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
#if STEP < 2
#define PASS2(A)
#else
#define PASS2(A) A
#endif
#if STEP < 3
#define PASS3(A)
#else
#define PASS3(A) A
#endif
#if STEP < 3
#define MAYUSE(A) (void)A
#else
#define MAYUSE(A)
#endif
#define GOCOND(B, T1, T2) \
case B+0x0: \
INST_NAME(T1 "O " T2); \
GO( TSTw_mask(xFlags, 0b010101, 0) \
, cEQ, cNE, X_OF) \
break; \
case B+0x1: \
INST_NAME(T1 "NO " T2); \
GO( TSTw_mask(xFlags, 0b010101, 0) \
, cNE, cEQ, X_OF) \
break; \
case B+0x2: \
INST_NAME(T1 "C " T2); \
GO( TSTw_mask(xFlags, 0, 0) \
, cEQ, cNE, X_CF) \
break; \
case B+0x3: \
INST_NAME(T1 "NC " T2); \
GO( TSTw_mask(xFlags, 0, 0) \
, cNE, cEQ, X_CF) \
break; \
case B+0x4: \
INST_NAME(T1 "Z " T2); \
GO( TSTw_mask(xFlags, 0b011010, 0) \
, cEQ, cNE, X_ZF) \
break; \
case B+0x5: \
INST_NAME(T1 "NZ " T2); \
GO( TSTw_mask(xFlags, 0b011010, 0) \
, cNE, cEQ, X_ZF) \
break; \
case B+0x6: \
INST_NAME(T1 "BE " T2); \
GO( MOV32w(x1, (1<<F_CF)|(1<<F_ZF)); \
TSTw_REG(xFlags, x1) \
, cEQ, cNE, X_CF|X_ZF) \
break; \
case B+0x7: \
INST_NAME(T1 "NBE " T2); \
GO( MOV32w(x1, (1<<F_CF)|(1<<F_ZF)); \
TSTw_REG(xFlags, x1) \
, cNE, cEQ, X_CF|X_ZF) \
break; \
case B+0x8: \
INST_NAME(T1 "S " T2); \
GO( TSTw_mask(xFlags, 0b011001, 0) \
, cEQ, cNE, X_SF) \
break; \
case B+0x9: \
INST_NAME(T1 "NS " T2); \
GO( TSTw_mask(xFlags, 0b011001, 0) \
, cNE, cEQ, X_SF) \
break; \
case B+0xA: \
INST_NAME(T1 "P " T2); \
GO( TSTw_mask(xFlags, 0b011110, 0) \
, cEQ, cNE, X_PF) \
break; \
case B+0xB: \
INST_NAME(T1 "NP " T2); \
GO( TSTw_mask(xFlags, 0b011110, 0) \
, cNE, cEQ, X_PF) \
break; \
case B+0xC: \
INST_NAME(T1 "L " T2); \
GO( EORw_REG_LSL(x1, xFlags, xFlags, F_OF-F_SF); \
TSTw_mask(x1, 0b010101, 0) \
, cEQ, cNE, X_SF|X_OF) \
break; \
case B+0xD: \
INST_NAME(T1 "GE " T2); \
GO( EORw_REG_LSL(x1, xFlags, xFlags, F_OF-F_SF); \
TSTw_mask(x1, 0b010101, 0) \
, cNE, cEQ, X_SF|X_OF) \
break; \
case B+0xE: \
INST_NAME(T1 "LE " T2); \
GO( EORw_REG_LSL(x1, xFlags, xFlags, F_OF-F_SF); \
ORRw_REG_LSL(x1, x1, xFlags, F_OF-F_ZF); \
TSTw_mask(x1, 0b010101, 0) \
, cEQ, cNE, X_SF|X_OF|X_ZF) \
break; \
case B+0xF: \
INST_NAME(T1 "G " T2); \
GO( EORw_REG_LSL(x1, xFlags, xFlags, F_OF-F_SF); \
ORRw_REG_LSL(x1, x1, xFlags, F_OF-F_ZF); \
TSTw_mask(x1, 0b010101, 0) \
, cNE, cEQ, X_SF|X_OF|X_ZF) \
break
#endif //__DYNAREC_ARM64_HELPER_H__
+104
View File
@@ -0,0 +1,104 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.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 "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "custommem.h"
#ifndef STEP
#error No STEP defined
#endif
void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
{
int ok = 1;
int ninst = 0;
uintptr_t ip = addr;
int need_epilog = 1;
dyn->sons_size = 0;
// Clean up (because there are multiple passes)
dyn->state_flags = 0;
dyn->dfnone = 0;
dyn->last_ip = ip; // RIP is always set at start of block!
fpu_reset(dyn, ninst);
// ok, go now
INIT;
while(ok) {
if(dyn->insts && (ninst>dyn->size)) {dynarec_log(LOG_NONE, "Warning, too many inst treated (%d / %d)\n",ninst, dyn->size);}
ip = addr;
if(dyn->insts && (dyn->insts[ninst].x64.barrier==1)) {
dyn->last_ip = 0;
NEW_BARRIER_INST;
}
NEW_INST;
fpu_reset_scratch(dyn);
#ifdef HAVE_TRACE
if(my_context->dec && box64_dynarec_trace) {
if((trace_end == 0)
|| ((ip >= trace_start) && (ip < trace_end))) {
MESSAGE(LOG_DUMP, "TRACE ----\n");
fpu_reflectcache(dyn, ninst, x1, x2, x3);
GETIP(ip);
MOVx_REG(x1, xRIP);
STORE_XEMU_CALL(xRIP);
MOV32w(x2, 1);
CALL(PrintTrace, -1);
LOAD_XEMU_CALL(xRIP);
MESSAGE(LOG_DUMP, "----------\n");
}
}
#endif
addr = dynarec64_00(dyn, addr, ip, ninst, &ok, &need_epilog);
INST_EPILOG;
if(dyn->insts && dyn->insts[ninst+1].x64.barrier) {
fpu_purgecache(dyn, ninst, x1, x2, x3);
if(dyn->insts[ninst+1].x64.barrier!=2) {
dyn->state_flags = 0;
dyn->dfnone = 0;
}
}
if(!ok && !need_epilog && dyn->insts && (addr < (dyn->start+dyn->isize))) {
ok = 1;
}
if(!ok && !need_epilog && !dyn->insts && getProtection(addr+3))
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
uintptr_t next = get_closest_next(dyn, addr);
if(next && (
(((next-addr)<15) && is_nops(dyn, addr, next-addr))
||(((next-addr)<30) && is_instructions(dyn, addr, next-addr)) ))
{
dynarec_log(LOG_DEBUG, "Extend block %p, %p -> %p (ninst=%d)\n", dyn, (void*)addr, (void*)next, ninst);
ok = 1;
} else if(next && (next-addr)<30) {
dynarec_log(LOG_DEBUG, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7));
}
}
if(ok<0) {ok = 0; need_epilog=1;}
++ninst;
}
if(need_epilog) {
fpu_purgecache(dyn, ninst, x1, x2, x3);
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknow instruction
}
FINI;
MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d, %d sons)\n", dyn->size, dyn->sons_size);
}
+25
View File
@@ -0,0 +1,25 @@
#define INIT uintptr_t sav_addr=addr
#define FINI dyn->isize = addr-sav_addr
#define MESSAGE(A, ...)
#define SETFLAGS(A, B)
#define READFLAGS(A)
#define EMIT(A)
#define JUMP(A) add_next(dyn, (uintptr_t)A)
#define NEW_INST ++dyn->size
#define INST_EPILOG
#define INST_NAME(name)
#define DEFAULT \
--dyn->size; \
*ok = -1; \
if(box64_dynarec_log>=LOG_INFO) {\
dynarec_log(LOG_NONE, "%p: Dynarec stopped because of Opcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
(void*)ip, PKip(0), \
PKip(1), PKip(2), PKip(3), \
PKip(4), PKip(5), PKip(6), \
PKip(7), PKip(8), PKip(9), \
PKip(10),PKip(11),PKip(12), \
PKip(13),PKip(14)); \
printFunctionAddr(ip, " => "); \
dynarec_log(LOG_NONE, "\n"); \
}
+17
View File
@@ -0,0 +1,17 @@
#define INIT
#define FINI \
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 EMIT(A)
#define READFLAGS(A) dyn->insts[ninst].x64.use_flags = A
#define SETFLAGS(A,B) {dyn->insts[ninst].x64.set_flags = A; dyn->insts[ninst].x64.state_flags = B;}
#define JUMP(A) dyn->insts[ninst].x64.jmp = A
#define BARRIER(A) dyn->insts[ninst].x64.barrier = A
#define BARRIER_NEXT(A) if(ninst<dyn->size) dyn->insts[ninst+1].x64.barrier = A
#define NEW_INST \
dyn->insts[ninst].x64.addr = ip; \
if(ninst) dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr;
#define INST_EPILOG
#define INST_NAME(name)
+10
View File
@@ -0,0 +1,10 @@
#define INIT dyn->arm_size = 0
#define FINI if(ninst) {dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size);}
#define MESSAGE(A, ...)
#define EMIT(A) dyn->insts[ninst].size+=4; dyn->arm_size+=4
#define NEW_INST if(ninst) {dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size);}
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->arm_size;
#define INST_NAME(name)
#define NEW_BARRIER_INST if(ninst) ++dyn->sons_size
#define TABLE64(A, V) if((V)>0xffffffffLL) {Table64(dyn, (V)); EMIT(0);} else {MOV64x(A, V);}
+35
View File
@@ -0,0 +1,35 @@
#define INIT
#define FINI
#define EMIT(A) \
if(box64_dynarec_dump) {dynarec_log(LOG_NONE, "\t%08x\t%s\n", (uint32_t)(A), arm64_print(A, (uintptr_t)dyn->block));} \
*(uint32_t*)(dyn->block) = (uint32_t)(A); \
dyn->block += 4; dyn->arm_size += 4;\
dyn->insts[ninst].size2 += 4
#define MESSAGE(A, ...) if(box64_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
#define NEW_INST
#define INST_EPILOG
#define INST_NAME(name) \
if(box64_dynarec_dump) {\
printf_x64_instruction(my_context->dec, &dyn->insts[ninst].x64, name); \
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, state=%d/%d, set=%X, use=%X, need=%X%s\n", \
(box64_dynarec_dump>1)?"\e[32m":"", \
(void*)(dyn->arm_start+dyn->insts[ninst].address), \
dyn->insts[ninst].size/4, \
dyn->insts[ninst].x64.state_flags, \
dyn->state_flags, \
dyn->insts[ninst].x64.set_flags, \
dyn->insts[ninst].x64.use_flags, \
dyn->insts[ninst].x64.need_flags, \
(box64_dynarec_dump>1)?"\e[m":""); \
}
#define NEW_BARRIER_INST \
if(ninst) { \
dyn->sons_x64[dyn->sons_size] = (uintptr_t)ip; \
dyn->sons_arm[dyn->sons_size] = dyn->block; \
MESSAGE(LOG_DUMP, "----> potential Son here\n");\
++dyn->sons_size; \
}
#define TABLE64(A, V) if((V)>0xffffffffLL) {int val64offset = Table64(dyn, (V)); MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset);} else {MOV64x(A, V);}
+61
View File
@@ -0,0 +1,61 @@
#ifndef __DYNAREC_ARM_PRIVATE_H_
#define __DYNAREC_ARM_PRIVATE_H_
#include "dynarec_private.h"
typedef struct x64emu_s x64emu_t;
typedef struct instruction_arm_s {
instruction_x64_t x64;
uintptr_t address; // (start) address of the arm emited instruction
uintptr_t epilog; // epilog of current instruction (can be start of next, of barrier stuff)
int size; // size of the arm emited instruction
int size2; // size of the arm emited instrucion after pass2
uintptr_t mark, mark2, mark3;
uintptr_t markf;
uintptr_t markseg;
uintptr_t marklock;
int pass2choice;// value for choices that are fixed on pass2 for pass3
uintptr_t natcall;
int retn;
} instruction_arm64_t;
typedef struct dynarec_arm_s {
instruction_arm64_t *insts;
int32_t size;
int32_t cap;
uintptr_t start; // start of the block
uint32_t isize; // size in byte of x64 instructions included
void* block; // memory pointer where next instruction is emited
uintptr_t arm_start; // start of the arm code
int arm_size; // size of emitted arm code
int state_flags;// actual state for on-demand flags
uintptr_t last_ip; // last set IP in RIP (or NULL if unclean state)
int8_t x87cache[8];// cache status for the 8 x87 register behind the fpu stack
int8_t x87reg[8]; // reg used for x87cache entry
int8_t mmxcache[8];// cache status for the 8 MMX registers
int8_t ssecache[16];// cache status for the 16 SSE(2) registers
int8_t fpuused[32];// all 8..31 Q reg from fpu, used by x87, sse and mmx
int x87stack; // cache stack counter
int fpu_scratch;// scratch counter
int fpu_reg; // x87/sse/mmx reg counter
int dfnone; // if defered flags is already set to df_none
uint64_t *table64; // table of 64bits value
int table64size;// size of table (will be appended at end of executable code)
uintptr_t tablestart;
uintptr_t* next; // variable array of "next" jump address
int next_sz;
int next_cap;
uintptr_t* sons_x64; // the x64 address of potential dynablock sons
void** sons_arm; // the arm address of potential dynablock sons
int sons_size; // number of potential dynablock sons
} dynarec_arm_t;
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n);
int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
int Table64(dynarec_arm_t *dyn, uint64_t val); // add a value to etable64 (if needed) and gives back the imm19 to use in LDR_literal
#endif //__DYNAREC_ARM_PRIVATE_H_
+35
View File
@@ -0,0 +1,35 @@
#ifndef __DYNAREC_PRIVATE_H_
#define __DYNAREC_PRIVATE_H_
// all flags for the use_flags field
#define X_CF (1<<0)
#define X_PF (1<<1)
#define X_AF (1<<2)
#define X_ZF (1<<3)
#define X_SF (1<<4)
#define X_OF (1<<5)
#define X_ALL ((1<<6)-1)
#define X_PEND (0x1000)
// all state flags
#define SF_UNKNOWN 0
#define SF_SET 1
#define SF_PENDING 2
#define SF_MAYSET 3
#define SF_SUBSET 4
typedef struct instruction_x64_s {
uintptr_t addr; //address of the instruction
int32_t size; // size of the instruction
int barrier; // next instruction is a jump point, so no optim allowed
uintptr_t jmp; // offset to jump to, even if conditionnal (0 if not), no relative offset here
int jmp_insts; // instuction to jump to (-1 if out of the block)
uint32_t use_flags; // 0 or combination of X_?F
uint32_t set_flags; // 0 or combination of X_?F
uint32_t need_flags; // calculated
int state_flags; // One of SF_XXX state
} instruction_x64_t;
void printf_x64_instruction(zydis_dec_t* dec, instruction_x64_t* inst, const char* name);
#endif //__DYNAREC_PRIVATE_H_
+14 -6
View File
@@ -25,7 +25,6 @@
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
//#include "dynarec.h"
#include "box64stack.h"
#include "custommem.h"
#include "wine_tools.h"
@@ -293,7 +292,7 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
}
}
#ifdef DYNAREC
if(e->p_flags & PF_X) {
if(box64_dynarec && (e->p_flags & PF_X)) {
dynarec_log(LOG_DEBUG, "Add ELF eXecutable Memory %p:%p\n", dest, (void*)e->p_memsz);
addDBFromAddressRange((uintptr_t)dest, e->p_memsz);
}
@@ -334,7 +333,8 @@ int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
if(e->p_filesz) {
ssize_t r = -1;
#ifdef DYNAREC
unprotectDB((uintptr_t)dest, e->p_memsz);
if(box64_dynarec)
unprotectDB((uintptr_t)dest, e->p_memsz);
#endif
if((r=fread(dest, e->p_filesz, 1, f))!=1) {
printf_log(LOG_NONE, "Fail to (re)read PT_LOAD part #%d (dest=%p, size=%ld, return=%ld, feof=%d/ferror=%d/%s)\n", i, dest, e->p_filesz, r, feof(f), ferror(f), strerror(ferror(f)));
@@ -562,14 +562,22 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
*p += head->delta;
break;
case R_X86_64_COPY:
if(local_maplib)
if(!strcmp(symname, "stdin") || !strcmp(symname, "stdout") || !strcmp(symname, "stderr")) {
if(!strcmp(symname, "stdin"))
offs = (uintptr_t)&stdin;
else if(!strcmp(symname, "stdout"))
offs = (uintptr_t)&stdout;
else
offs = (uintptr_t)&stderr;
end = offs + 8;
} else if(local_maplib)
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head);
if(!offs)
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head);
if(offs) {
// add r_addend to p?
printf_log(LOG_DUMP, "Apply R_X86_64_COPY @%p with sym=%s, @%p size=%ld\n", p, symname, (void*)offs, sym->st_size);
memcpy(p, (void*)(offs+rela[i].r_addend), sym->st_size);
memmove(p, (void*)(offs+rela[i].r_addend), sym->st_size);
} else {
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply RELA R_X86_64_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
}
@@ -718,7 +726,7 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
return -1;
}
if(pltResolver==~0) {
pltResolver = AddBridge(my_context->system, vFE, PltResolver, 0);
pltResolver = AddBridge(my_context->system, vFE, PltResolver, 0, "PltResolver");
}
if(head->pltgot) {
*(uintptr_t*)(head->pltgot+head->delta+16) = pltResolver;
+1 -1
View File
@@ -72,7 +72,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
}
if(header.e_ident[EI_CLASS]!=ELFCLASS64) {
if(header.e_ident[EI_CLASS]==ELFCLASS32) {
printf_log(LOG_INFO, "This is a 64bits ELF! box64 can only run 64bits ELF!\n");
printf_log(LOG_INFO, "This is a 32bits ELF! box64 can only run 64bits ELF!\n");
} else {
printf_log(LOG_INFO, "Not a 64bits ELF (%d)\n", header.e_ident[EI_CLASS]);
}
+2
View File
@@ -14,12 +14,14 @@
#endif
#define GETED(D) oped=GetEd(emu, rex, nextop, D)
#define GETED32(D) oped=GetEd32O(emu, rex, nextop, D, 0)
#define GETED_OFFS(D, O) oped=GetEdO(emu, rex, nextop, D, O)
#define GETGD opgd=GetGd(emu, rex, nextop)
#define GETEB(D) oped=GetEb(emu, rex, nextop, D)
#define GETEB_OFFS(D, O) oped=GetEbO(emu, rex, nextop, D, O)
#define GETGB opgd=GetGb(emu, rex, nextop)
#define GETEW(D) oped=GetEw(emu, rex, nextop, D)
#define GETEW_OFFS(D, O) oped=GetEdO(emu, rex, nextop, D, O)
#define GETGW opgd=GetGw(emu, rex, nextop)
#define GETEX(D) opex=GetEx(emu, rex, nextop, D)
#define GETGX opgx=GetGx(emu, rex, nextop)
+12 -6
View File
@@ -45,13 +45,13 @@ uint32_t* GetParityTab()
void PushExit(x64emu_t* emu)
{
uintptr_t endMarker = AddCheckBridge(my_context->system, NULL, NULL, 0);
uintptr_t endMarker = AddCheckBridge(my_context->system, NULL, NULL, 0, "ExitEmulation");
Push(emu, endMarker);
}
void* GetExit()
{
return (void*)AddCheckBridge(my_context->system, NULL, NULL, 0);
return (void*)AddCheckBridge(my_context->system, NULL, NULL, 0, "ExitEmulation");
}
static void internalX64Setup(x64emu_t* emu, box64context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
@@ -62,7 +62,7 @@ static void internalX64Setup(x64emu_t* emu, box64context_t *context, uintptr_t s
emu->sbiidx[i] = &emu->regs[i];
emu->sbiidx[4] = &emu->zero;
emu->x64emu_parity_tab = x86emu_parity_tab;
emu->eflags.x32 = 0x202; // default flags?
emu->eflags.x64 = 0x202; // default flags?
// own stack?
emu->stack2free = (ownstack)?(void*)stack:NULL;
emu->init_stack = (void*)stack;
@@ -77,6 +77,7 @@ static void internalX64Setup(x64emu_t* emu, box64context_t *context, uintptr_t s
emu->segs[_GS] = default_gs;
// setup fpu regs
reset_fpu(emu);
emu->mxcsr = 0x1f80;
}
EXPORTDYN
@@ -367,7 +368,10 @@ const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip)
if (i%5==4) {
if(i==4) {
if(emu->df) {
strcat(buff, "FLAGS=??????\n");
#define FLAG_CHAR(f) (ACCESS_FLAG(F_##f##F)) ? #f : "?"
sprintf(tmp, "flags=%s%s%s%s%s%s\n", FLAG_CHAR(O), FLAG_CHAR(C), FLAG_CHAR(P), FLAG_CHAR(A), FLAG_CHAR(Z), FLAG_CHAR(S));
strcat(buff, tmp);
#undef FLAG_CHAR
} else {
#define FLAG_CHAR(f) (ACCESS_FLAG(F_##f##F)) ? #f : "-"
sprintf(tmp, "FLAGS=%s%s%s%s%s%s\n", FLAG_CHAR(O), FLAG_CHAR(C), FLAG_CHAR(P), FLAG_CHAR(A), FLAG_CHAR(Z), FLAG_CHAR(S));
@@ -398,10 +402,12 @@ void UnimpOpcode(x64emu_t* emu)
R_RIP = emu->old_ip;
int tid = syscall(SYS_gettid);
printf_log(LOG_NONE, "%04d|%p: Unimplemented Opcode (%02X) %02X %02X %02X %02X %02X %02X %02X %02X\n",
printf_log(LOG_NONE, "%04d|%p: Unimplemented Opcode (%02X) %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
tid, (void*)emu->old_ip, Peek(emu, -1),
Peek(emu, 0), Peek(emu, 1), Peek(emu, 2), Peek(emu, 3),
Peek(emu, 4), Peek(emu, 5), Peek(emu, 6), Peek(emu, 7));
Peek(emu, 4), Peek(emu, 5), Peek(emu, 6), Peek(emu, 7),
Peek(emu, 8), Peek(emu, 9), Peek(emu,10), Peek(emu,11),
Peek(emu,12), Peek(emu,13), Peek(emu,14));
emu->quit=1;
emu->error |= ERR_UNIMPL;
}
+19 -16
View File
@@ -10,11 +10,6 @@ typedef struct x64_ucontext_s x64_ucontext_t;
#define ERR_DIVBY0 2
#define ERR_ILLEGAL 4
#ifdef DYNAREC
#define CSTACK 32
#define CSTACKMASK 31
#endif
typedef struct forkpty_s {
void* amaster;
void* name;
@@ -23,10 +18,17 @@ typedef struct forkpty_s {
void* f; // forkpty function
} forkpty_t;
typedef union multiuint_s {
uint8_t u8;
uint16_t u16;
uint32_t u32;
uint64_t u64;
} multiuint_t;
typedef struct x64emu_s {
// cpu
reg64_t regs[16];
x86flags_t eflags;
x64flags_t eflags;
reg64_t ip;
uintptr_t old_ip;
// fpu / mmx
@@ -35,18 +37,19 @@ typedef struct x64emu_s {
x87flags_t sw;
uint32_t top; // top is part of sw, but it's faster to have it separatly
int fpu_stack;
uint32_t mxcsr;
fpu_round_t round;
fpu_ld_t fpu_ld[8]; // for long double emulation / 80bits fld fst
fpu_ll_t fpu_ll[8]; // for 64bits fild / fist sequence
fpu_p_reg_t p_regs[8];
// sse
sse_regs_t xmm[16];
uint32_t mxcsr;
// defered flags
int dummy1; // to align on 64bits with df
defered_flags_t df;
uint64_t op1;
uint64_t op2;
uint64_t res;
multiuint_t op1;
multiuint_t op2;
multiuint_t res;
uint32_t *x64emu_parity_tab; // helper
#ifdef HAVE_TRACE
uintptr_t prev2_ip;
@@ -54,7 +57,12 @@ typedef struct x64emu_s {
// segments
uint32_t segs[6]; // only 32bits value?
uintptr_t segs_offs[6]; // computed offset associate with segment
uint64_t segs_serial[6]; // are seg offset clean (not 0) or does they need to be re-computed (0)? For GS, serial need to be the same as context->sel_serial
uint32_t segs_serial[6]; // are seg offset clean (not 0) or does they need to be re-computed (0)? For GS, serial need to be the same as context->sel_serial
// parent context
box64context_t *context;
// cpu helpers
reg64_t zero;
reg64_t *sbiidx[16];
// emu control
int quit;
int error;
@@ -63,11 +71,6 @@ typedef struct x64emu_s {
int exit;
int quitonlongjmp; // quit if longjmp is called
int longjmp; // if quit because of longjmp
// parent context
box64context_t *context;
// cpu helpers
reg64_t zero;
reg64_t *sbiidx[16];
// scratch stack, used for alignement of double and 64bits ints on arm. 200 elements should be enough
uint64_t scratch[200];
// local stack, do be deleted when emu is freed
+10 -9
View File
@@ -93,20 +93,21 @@ void x64Int3(x64emu_t* emu)
int perr = 0;
uint32_t *pu32 = NULL;
const char *s = NULL;
{
Dl_info info;
if(dladdr((void*)addr, &info))
s = info.dli_sname;
}
if(!s) s = GetNativeName((void*)addr);
s = GetNativeName((void*)addr);
if(addr==(uintptr_t)PltResolver) {
snprintf(buff, 256, "%s", " ... ");
} else if(strstr(s, "__open")==s || strcmp(s, "open")==0) {
} else if(strstr(s, "__open")==s || !strcmp(s, "open") || !strcmp(s, "open ")) {
tmp = (char*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (int)(R_ESI), (int)(R_EDX));
perr = 1;
} else if(strstr(s, "my___printf_chk")) {
tmp = (char*)(R_RSI);
snprintf(buff, 255, "%04d|%p: Calling %s(%d, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, R_EDI, (tmp)?tmp:"(nil)", (void*)(R_RDX));
} else if(!strcmp(s, "sscanf")) {
tmp = (char*)(R_RSI);
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, (void*)R_RDI, (tmp)?tmp:"(nil)", (void*)(R_RDX));
} else {
snprintf(buff, 255, "%04d|%p: Calling %s (%016lX, %016lX, %016lX, ...)", tid, *(void**)(R_RSP), s, R_RDI, R_RSI, R_RDX);
snprintf(buff, 255, "%04d|%p: Calling %s(0x%lX, 0x%lX, 0x%lX, ...)", tid, *(void**)(R_RSP), s, R_RDI, R_RSI, R_RDX);
}
printf_log(LOG_NONE, "%s =>", buff);
pthread_mutex_unlock(&emu->context->mutex_trace);
@@ -135,7 +136,7 @@ void x64Int3(x64emu_t* emu)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
else if(perr==2 && R_EAX==0)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
printf_log(LOG_NONE, " return 0x%016lX%s%s\n", R_RAX, buff2, buff3);
printf_log(LOG_NONE, " return 0x%lX%s%s\n", R_RAX, buff2, buff3);
pthread_mutex_unlock(&emu->context->mutex_trace);
} else
w(emu, addr);
+20 -20
View File
@@ -310,7 +310,7 @@ uint64_t adc64(x64emu_t *emu, uint64_t d, uint64_t s)
CONDITIONAL_SET_FLAG(hi & 0x100000000L, F_CF);
CONDITIONAL_SET_FLAG(!res, F_ZF);
CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF);
CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
/* calculate the carry chain SEE NOTE AT TOP. */
@@ -393,13 +393,13 @@ uint64_t cmp64(x64emu_t *emu, uint64_t d, uint64_t s)
RESET_FLAGS(emu);
res = d - s;
CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF);
CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF);
CONDITIONAL_SET_FLAG(!res, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
/* calculate the borrow chain. See note at top */
bc = (res & (~d | s)) | (~d & s);
CONDITIONAL_SET_FLAG(bc & 0x8000000000000000L, F_CF);
CONDITIONAL_SET_FLAG(bc & 0x8000000000000000LL, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 62), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
return d;
@@ -573,7 +573,7 @@ uint32_t rcl32(x64emu_t *emu, uint32_t d, uint8_t s)
return res;
}
uint32_t rcl64(x64emu_t *emu, uint64_t d, uint8_t s)
uint64_t rcl64(x64emu_t *emu, uint64_t d, uint8_t s)
{
uint64_t res, cnt, mask, cf;
CHECK_FLAGS(emu);
@@ -583,10 +583,10 @@ uint32_t rcl64(x64emu_t *emu, uint64_t d, uint8_t s)
if ((cnt = s % 65) != 0) {
cf = (d >> (64 - cnt)) & 0x1;
res = (d << cnt);
mask = (1 << (cnt - 1)) - 1;
mask = (1LL << (cnt - 1)) - 1;
res |= (d >> (65 - cnt)) & mask;
if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
res |= 1 << (cnt - 1);
res |= 1LL << (cnt - 1);
}
CONDITIONAL_SET_FLAG(cf, F_CF);
CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 62) & 0x2)),
@@ -756,12 +756,12 @@ uint64_t rcr64(x64emu_t *emu, uint64_t d, uint8_t s)
ocf = ACCESS_FLAG(F_CF) != 0;
} else
cf = (d >> (cnt - 1)) & 0x1;
mask = (1 << (64 - cnt)) - 1;
mask = (1LL << (64 - cnt)) - 1;
res = (d >> cnt) & mask;
if (cnt != 1)
res |= (d << (65 - cnt));
if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
res |= 1 << (64 - cnt);
res |= 1LL << (64 - cnt);
}
CONDITIONAL_SET_FLAG(cf, F_CF);
if (cnt == 1) {
@@ -1033,17 +1033,17 @@ uint32_t shld32 (x64emu_t *emu, uint32_t d, uint32_t fill, uint8_t s)
uint64_t shld64 (x64emu_t *emu, uint64_t d, uint64_t fill, uint8_t s)
{
unsigned int cnt, res, cf;
uint64_t cnt, res, cf;
RESET_FLAGS(emu);
s = s&0x3f;
cnt = s % 64;
if (cnt > 0) {
res = (d << cnt) | (fill >> (64-cnt));
cf = d & (1 << (64 - cnt));
cf = d & (1LL << (64 - cnt));
CONDITIONAL_SET_FLAG(cf, F_CF);
CONDITIONAL_SET_FLAG(!res, F_ZF);
CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF);
CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
} else {
res = d;
@@ -1139,11 +1139,11 @@ uint64_t shrd64 (x64emu_t *emu, uint64_t d, uint64_t fill, uint8_t s)
s = s&0x3f;
cnt = s % 64;
if (cnt > 0) {
cf = d & (1 << (cnt - 1));
cf = d & (1LL << (cnt - 1));
res = (d >> cnt) | (fill << (64 - cnt));
CONDITIONAL_SET_FLAG(cf, F_CF);
CONDITIONAL_SET_FLAG(!res, F_ZF);
CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF);
CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
} else {
res = d;
@@ -1235,13 +1235,13 @@ uint64_t sbb64(x64emu_t *emu, uint64_t d, uint64_t s)
res = d - s - 1;
else
res = d - s;
CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF);
CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF);
CONDITIONAL_SET_FLAG(!res, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
/* calculate the borrow chain. See note at top */
bc = (res & (~d | s)) | (~d & s);
CONDITIONAL_SET_FLAG(bc & 0x8000000000000000L, F_CF);
CONDITIONAL_SET_FLAG(bc & 0x8000000000000000LL, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 62), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
return res;
@@ -1304,7 +1304,7 @@ void test64(x64emu_t *emu, uint64_t d, uint64_t s)
res = d & s;
CLEAR_FLAG(F_OF);
CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF);
CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF);
CONDITIONAL_SET_FLAG(res == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
/* AF == dont care */
@@ -1384,8 +1384,8 @@ void idiv32(x64emu_t *emu, uint32_t s)
SET_FLAG(F_ZF);
CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
R_EAX = (uint32_t)quot;
R_EDX = (uint32_t)mod;
R_RAX = (uint32_t)quot;
R_RDX = (uint32_t)mod;
}
void idiv64(x64emu_t *emu, uint64_t s)
@@ -1485,8 +1485,8 @@ void div32(x64emu_t *emu, uint32_t s)
SET_FLAG(F_ZF);
CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
R_EAX = (uint32_t)div;
R_EDX = (uint32_t)mod;
R_RAX = (uint32_t)div;
R_RDX = (uint32_t)mod;
}
void div64(x64emu_t *emu, uint64_t s)
+167 -167
View File
@@ -16,70 +16,70 @@ uint64_t adc64 (x64emu_t *emu, uint64_t d, uint64_t s);
static inline uint8_t add8(x64emu_t *emu, uint8_t d, uint8_t s)
{
emu->res = d + s;
emu->op1 = d;
emu->op2 = s;
emu->res.u16 = d + s;
emu->op1.u8 = d;
emu->op2.u8 = s;
emu->df = d_add8;
return (uint8_t)emu->res;
return emu->res.u8;
}
static inline uint16_t add16(x64emu_t *emu, uint16_t d, uint16_t s)
{
emu->res = d + s;
emu->op1 = d;
emu->op2 = s;
emu->res.u32 = d + s;
emu->op1.u16 = d;
emu->op2.u16 = s;
emu->df = d_add16;
return (uint16_t)emu->res;
return emu->res.u16;
}
static inline uint32_t add32(x64emu_t *emu, uint32_t d, uint32_t s)
{
emu->res = d + s;
emu->op1 = d;
emu->op2 = s;
emu->res.u64 = (uint64_t)d + s;
emu->op1.u32 = d;
emu->op2.u32 = s;
emu->df = d_add32;
return emu->res;
return emu->res.u32;
}
static inline uint64_t add64(x64emu_t *emu, uint64_t d, uint64_t s)
{
emu->res = d + s;
emu->op1 = d;
emu->op2 = s;
emu->res.u64 = d + s;
emu->op1.u64 = d;
emu->op2.u64 = s;
emu->df = d_add64;
return emu->res;
return emu->res.u64;
}
static inline uint8_t and8(x64emu_t *emu, uint8_t d, uint8_t s)
{
emu->res = d & s;
emu->res.u8 = d & s;
emu->df = d_and8;
return emu->res;
return emu->res.u8;
}
static inline uint16_t and16(x64emu_t *emu, uint16_t d, uint16_t s)
{
emu->res = d & s;
emu->res.u16 = d & s;
emu->df = d_and16;
return emu->res;
return emu->res.u16;
}
static inline uint32_t and32(x64emu_t *emu, uint32_t d, uint32_t s)
{
emu->res = d & s;
emu->res.u32 = d & s;
emu->df = d_and32;
return emu->res;
return emu->res.u32;
}
static inline uint64_t and64(x64emu_t *emu, uint64_t d, uint64_t s)
{
emu->res = d & s;
emu->res.u64 = d & s;
emu->df = d_and64;
return emu->res;
return emu->res.u64;
}
uint8_t cmp8 (x64emu_t *emu, uint8_t d, uint8_t s);
@@ -91,146 +91,146 @@ uint8_t das8 (x64emu_t *emu, uint8_t d);
static inline uint8_t dec8(x64emu_t *emu, uint8_t d)
{
emu->res = d - 1;
emu->op1 = d;
emu->res.u8 = d - 1;
emu->op1.u8 = d;
emu->df = d_dec8;
return (uint8_t)emu->res;
return emu->res.u8;
}
static inline uint16_t dec16(x64emu_t *emu, uint16_t d)
{
emu->res = d - 1;
emu->op1 = d;
emu->res.u16 = d - 1;
emu->op1.u16 = d;
emu->df = d_dec16;
return (uint16_t)emu->res;
return emu->res.u16;
}
static inline uint32_t dec32(x64emu_t *emu, uint32_t d)
{
emu->res = d - 1;
emu->op1 = d;
emu->res.u32 = d - 1;
emu->op1.u32 = d;
emu->df = d_dec32;
return emu->res;
return emu->res.u32;
}
static inline uint64_t dec64(x64emu_t *emu, uint64_t d)
{
emu->res = d - 1;
emu->op1 = d;
emu->res.u64 = d - 1;
emu->op1.u64 = d;
emu->df = d_dec64;
return emu->res;
return emu->res.u64;
}
static inline uint8_t inc8(x64emu_t *emu, uint8_t d)
{
emu->res = d + 1;
emu->op1 = d;
emu->res.u8 = d + 1;
emu->op1.u8 = d;
emu->df = d_inc8;
return (uint8_t)emu->res;
return emu->res.u8;
}
static inline uint16_t inc16(x64emu_t *emu, uint16_t d)
{
emu->res = d + 1;
emu->op1 = d;
emu->res.u16 = d + 1;
emu->op1.u16 = d;
emu->df = d_inc16;
return (uint16_t)emu->res;
return emu->res.u16;
}
static inline uint32_t inc32(x64emu_t *emu, uint32_t d)
{
if(emu->df == d_shr32) {
// workaround for some wine trickery
uint32_t cnt = emu->op2;
uint32_t cnt = emu->op2.u32;
if (cnt > 0) {
uint32_t cc = emu->op1 & (1 << (cnt - 1));
uint32_t cc = emu->op1.u32 & (1 << (cnt - 1));
CONDITIONAL_SET_FLAG(cc, F_CF);
}
}
emu->res = d + 1;
emu->op1 = d;
emu->res.u32 = d + 1;
emu->op1.u32 = d;
emu->df = d_inc32;
return emu->res;
return emu->res.u32;
}
static inline uint64_t inc64(x64emu_t *emu, uint64_t d)
{
if(emu->df == d_shr64) {
// workaround for some wine trickery
uint64_t cnt = emu->op2;
uint64_t cnt = emu->op2.u64;
if (cnt > 0) {
uint64_t cc = emu->op1 & (1L << (cnt - 1));
uint64_t cc = emu->op1.u64 & (1LL << (cnt - 1));
CONDITIONAL_SET_FLAG(cc, F_CF);
}
}
emu->res = d + 1;
emu->op1 = d;
emu->res.u64 = d + 1;
emu->op1.u64 = d;
emu->df = d_inc64;
return emu->res;
return emu->res.u64;
}
static inline uint8_t or8(x64emu_t *emu, uint8_t d, uint8_t s)
{
emu->res = d | s;
emu->res.u8 = d | s;
emu->df = d_or8;
return emu->res;
return emu->res.u8;
}
static inline uint16_t or16(x64emu_t *emu, uint16_t d, uint16_t s)
{
emu->res = d | s;
emu->res.u16 = d | s;
emu->df = d_or16;
/* set the carry flag to be bit 8 */
return emu->res;
return emu->res.u16;
}
static inline uint32_t or32(x64emu_t *emu, uint32_t d, uint32_t s)
{
emu->res = d | s;
emu->res.u32 = d | s;
emu->df = d_or32;
return emu->res;
return emu->res.u32;
}
static inline uint64_t or64(x64emu_t *emu, uint64_t d, uint64_t s)
{
emu->res = d | s;
emu->res.u64 = d | s;
emu->df = d_or64;
return emu->res;
return emu->res.u64;
}
static inline uint8_t neg8(x64emu_t *emu, uint8_t s)
{
emu->res = (uint8_t)-s;
emu->op1 = s;
emu->res.u8 = (uint8_t)-s;
emu->op1.u8 = s;
emu->df = d_neg8;
return emu->res;
return emu->res.u8;
}
static inline uint16_t neg16(x64emu_t *emu, uint16_t s)
{
emu->res = (uint16_t)-s;
emu->op1 = s;
emu->res.u16 = (uint16_t)-s;
emu->op1.u16 = s;
emu->df = d_neg16;
return emu->res;
return emu->res.u16;
}
static inline uint32_t neg32(x64emu_t *emu, uint32_t s)
{
emu->res = (uint32_t)-s;
emu->op1 = s;
emu->res.u32 = (uint32_t)-s;
emu->op1.u32 = s;
emu->df = d_neg32;
return emu->res;
return emu->res.u32;
}
static inline uint64_t neg64(x64emu_t *emu, uint64_t s)
{
emu->res = (uint64_t)-s;
emu->op1 = s;
emu->res.u64 = (uint64_t)-s;
emu->op1.u64 = s;
emu->df = d_neg64;
return emu->res;
return emu->res.u64;
}
static inline uint8_t not8(x64emu_t *emu, uint8_t s)
@@ -283,72 +283,72 @@ uint64_t sbb64 (x64emu_t *emu, uint64_t d, uint64_t s);
static inline uint8_t shl8(x64emu_t *emu, uint8_t d, uint8_t s)
{
emu->df = d_shl8;
emu->op1 = d;
emu->op1.u8 = d;
s &= 0x1f;
emu->op2 = s;
emu->res = d << s;
emu->op2.u8 = s;
emu->res.u8 = d << s;
return (uint8_t)emu->res;
return emu->res.u8;
}
static inline uint16_t shl16(x64emu_t *emu, uint16_t d, uint8_t s)
{
emu->df = d_shl16;
emu->op1 = d;
emu->op1.u16 = d;
s &= 0x1f;
emu->op2 = s;
emu->res = d << s;
return (uint16_t)emu->res;
emu->op2.u16 = s;
emu->res.u16 = d << s;
return emu->res.u16;
}
static inline uint32_t shl32(x64emu_t *emu, uint32_t d, uint8_t s)
{
emu->df = d_shl32;
emu->op1 = d;
emu->op1.u32 = d;
s &= 0x1f;
emu->op2 = s;
emu->res = d << s;
emu->op2.u32 = s;
emu->res.u32 = d << s;
return emu->res;
return emu->res.u32;
}
static inline uint64_t shl64(x64emu_t *emu, uint64_t d, uint8_t s)
{
emu->df = d_shl64;
emu->op1 = d;
emu->op1.u64 = d;
s &= 0x3f;
emu->op2 = s;
emu->res = d << s;
emu->op2.u64 = s;
emu->res.u64 = d << s;
return emu->res;
return emu->res.u64;
}
static inline uint8_t shr8(x64emu_t *emu, uint8_t d, uint8_t s)
{
emu->df = d_shr8;
emu->op1 = d;
emu->op1.u8 = d;
s &= 0x1f;
emu->op2 = s;
emu->res = d >> s;
emu->op2.u8 = s;
emu->res.u8 = d >> s;
return (uint8_t)emu->res;
return emu->res.u8;
}
static inline uint16_t shr16(x64emu_t *emu, uint16_t d, uint8_t s)
{
emu->df = d_shr16;
emu->op1 = d;
emu->op1.u16 = d;
s &= 0x1f;
emu->op2 = s;
emu->res = d >> s;
emu->op2.u16 = s;
emu->res.u16 = d >> s;
return (uint16_t)emu->res;
return emu->res.u16;
}
static inline uint32_t shr32(x64emu_t *emu, uint32_t d, uint8_t s)
@@ -356,13 +356,13 @@ static inline uint32_t shr32(x64emu_t *emu, uint32_t d, uint8_t s)
RESET_FLAGS(emu); // TODO: Defered this one?
emu->df = d_shr32;
emu->op1 = d;
emu->op1.u32 = d;
s &= 0x1f;
emu->op2 = s;
emu->res = d >> s;
emu->op2.u32 = s;
emu->res.u32 = d >> s;
return emu->res;
return emu->res.u32;
}
static inline uint64_t shr64(x64emu_t *emu, uint64_t d, uint8_t s)
@@ -370,97 +370,97 @@ static inline uint64_t shr64(x64emu_t *emu, uint64_t d, uint8_t s)
RESET_FLAGS(emu); // TODO: Defered this one?
emu->df = d_shr64;
emu->op1 = d;
emu->op1.u64 = d;
s &= 0x3f;
emu->op2 = s;
emu->res = d >> s;
emu->op2.u64 = s;
emu->res.u64 = d >> s;
return emu->res;
return emu->res.u64;
}
static inline uint8_t sar8(x64emu_t *emu, uint8_t d, uint8_t s)
{
emu->df = d_sar8;
emu->op1 = d;
emu->op1.u8 = d;
s &= 0x1f;
emu->op2 = s;
emu->res = (uint8_t)(((int8_t)d)>>s);
emu->op2.u8 = s;
emu->res.u8 = (uint8_t)(((int8_t)d)>>s);
return (uint8_t)emu->res;
return emu->res.u8;
}
static inline uint16_t sar16(x64emu_t *emu, uint16_t d, uint8_t s)
{
emu->df = d_sar16;
emu->op1 = d;
emu->op1.u16 = d;
s &= 0x1f;
emu->op2 = s;
emu->res = (uint16_t)(((int16_t)d)>>s);
emu->op2.u16 = s;
emu->res.u16 = (uint16_t)(((int16_t)d)>>s);
return (uint16_t)emu->res;
return emu->res.u16;
}
static inline uint32_t sar32(x64emu_t *emu, uint32_t d, uint8_t s)
{
emu->df = d_sar32;
emu->op1 = d;
emu->op1.u32 = d;
s &= 0x1f;
emu->op2 = s;
emu->res = (uint32_t)(((int32_t)d)>>s);
emu->op2.u32 = s;
emu->res.u32 = (uint32_t)(((int32_t)d)>>s);
return emu->res;
return emu->res.u32;
}
static inline uint64_t sar64(x64emu_t *emu, uint64_t d, uint8_t s)
{
emu->df = d_sar64;
emu->op1 = d;
emu->op1.u64 = d;
s &= 0x3f;
emu->op2 = s;
emu->res = (uint64_t)(((int64_t)d)>>s);
emu->op2.u64 = s;
emu->res.u64 = (uint64_t)(((int64_t)d)>>s);
return emu->res;
return emu->res.u64;
}
static inline uint8_t sub8(x64emu_t *emu, uint8_t d, uint8_t s)
{
emu->res = d - s;
emu->op1 = d;
emu->op2 = s;
emu->res.u8 = d - s;
emu->op1.u8 = d;
emu->op2.u8 = s;
emu->df = d_sub8;
return (uint8_t)emu->res;
return emu->res.u8;
}
static inline uint16_t sub16(x64emu_t *emu, uint16_t d, uint16_t s)
{
emu->res = d - s;
emu->op1 = d;
emu->op2 = s;
emu->res.u16 = d - s;
emu->op1.u16 = d;
emu->op2.u16 = s;
emu->df = d_sub16;
return (uint16_t)emu->res;
return emu->res.u16;
}
static inline uint32_t sub32(x64emu_t *emu, uint32_t d, uint32_t s)
{
emu->res = d - s;
emu->op1 = d;
emu->op2 = s;
emu->res.u32 = d - s;
emu->op1.u32 = d;
emu->op2.u32 = s;
emu->df = d_sub32;
return emu->res;
return emu->res.u32;
}
static inline uint64_t sub64(x64emu_t *emu, uint64_t d, uint64_t s)
{
emu->res = d - s;
emu->op1 = d;
emu->op2 = s;
emu->res.u64 = d - s;
emu->op1.u64 = d;
emu->op2.u64 = s;
emu->df = d_sub64;
return emu->res;
return emu->res.u64;
}
void test8 (x64emu_t *emu, uint8_t d, uint8_t s);
@@ -470,52 +470,52 @@ void test64 (x64emu_t *emu, uint64_t d, uint64_t s);
static inline uint8_t xor8(x64emu_t *emu, uint8_t d, uint8_t s)
{
emu->res = d ^ s;
emu->res.u8 = d ^ s;
emu->df = d_xor8;
return emu->res;
return emu->res.u8;
}
static inline uint16_t xor16(x64emu_t *emu, uint16_t d, uint16_t s)
{
emu->res = d ^ s;
emu->res.u16 = d ^ s;
emu->df = d_xor16;
return emu->res;
return emu->res.u16;
}
static inline uint32_t xor32(x64emu_t *emu, uint32_t d, uint32_t s)
{
emu->res = d ^ s;
emu->res.u32 = d ^ s;
emu->df = d_xor32;
return emu->res;
return emu->res.u32;
}
static inline uint64_t xor64(x64emu_t *emu, uint64_t d, uint64_t s)
{
emu->res = d ^ s;
emu->res.u64 = d ^ s;
emu->df = d_xor64;
return emu->res;
return emu->res.u64;
}
static inline void imul8(x64emu_t *emu, uint8_t s)
{
emu->df = d_imul8;
R_AX = emu->res = (int16_t)(int8_t)R_AL * (int8_t)s;
R_AX = emu->res.u16 = (int16_t)(int8_t)R_AL * (int8_t)s;
}
static inline void imul16_eax(x64emu_t *emu, uint16_t s)
{
emu->df = d_imul16;
emu->res = (int32_t)(int16_t)R_AX * (int16_t)s;
R_AX = (uint16_t)emu->res;
R_DX = (uint16_t)(emu->res >> 16);
emu->res.u32 = (int32_t)(int16_t)R_AX * (int16_t)s;
R_AX = (uint16_t)emu->res.u32;
R_DX = (uint16_t)(emu->res.u32 >> 16);
}
static inline uint16_t imul16(x64emu_t *emu, uint16_t op1, uint16_t op2)
{
emu->df = d_imul16;
emu->res = (int32_t)(int16_t)op1 * (int16_t)op2;
return (uint16_t)emu->res;
emu->res.u32 = (int32_t)(int16_t)op1 * (int16_t)op2;
return emu->res.u16;
}
static inline void imul32_direct(uint32_t *res_lo, uint32_t* res_hi,uint32_t d, uint32_t s)
@@ -531,17 +531,17 @@ static inline uint32_t imul32(x64emu_t *emu, uint32_t op1, uint32_t op2)
emu->df = d_imul32;
uint32_t _res, _op1;
imul32_direct(&_res,&_op1,op1,op2);
emu->res = _res;
emu->op1 = _op1;
return emu->res;
emu->res.u32 = _res;
emu->op1.u32 = _op1;
return emu->res.u32;
}
static inline void imul32_eax(x64emu_t *emu, uint32_t s)
{
emu->df = d_imul32;
imul32_direct(&R_EAX,&R_EDX,R_EAX,s);
emu->res = R_EAX;
emu->op1 = R_EDX;
emu->res.u32 = R_EAX;
emu->op1.u32 = R_EDX;
}
static inline void imul64_direct(uint64_t *res_lo, uint64_t* res_hi,uint64_t d, uint64_t s)
@@ -555,46 +555,46 @@ static inline void imul64_direct(uint64_t *res_lo, uint64_t* res_hi,uint64_t d,
static inline uint64_t imul64(x64emu_t *emu, uint64_t op1, uint64_t op2)
{
emu->df = d_imul64;
imul64_direct(&emu->res,&emu->op1,op1,op2);
return emu->res;
imul64_direct(&emu->res.u64,&emu->op1.u64,op1,op2);
return emu->res.u64;
}
static inline void imul64_rax(x64emu_t *emu, uint64_t s)
{
emu->df = d_imul64;
imul64_direct(&R_RAX,&R_RDX,R_RAX,s);
emu->res = R_RAX;
emu->op1 = R_RDX;
emu->res.u64 = R_RAX;
emu->op1.u64 = R_RDX;
}
static inline void mul8(x64emu_t *emu, uint8_t s)
{
emu->df = d_mul8;
R_AX = emu->res = (uint16_t)(R_AL) * s;
R_AX = emu->res.u16 = (uint16_t)(R_AL) * s;
}
static inline void mul16(x64emu_t *emu, uint16_t s)
{
emu->df = d_mul16;
emu->res = (uint32_t)R_AX * s;
R_AX = (uint16_t)emu->res;
R_DX = (uint16_t)(emu->res >> 16);
emu->res.u32 = (uint32_t)R_AX * s;
R_AX = (uint16_t)emu->res.u32;
R_DX = (uint16_t)(emu->res.u32 >> 16);
}
static inline void mul32_eax(x64emu_t *emu, uint32_t s)
{
emu->df = d_mul32;
uint64_t res = (uint64_t)R_EAX * s;
emu->res = R_EAX = (uint32_t)res;
emu->op1 = R_EDX = (uint32_t)(res >> 32);
emu->res.u32 = R_EAX = (uint32_t)res;
emu->op1.u32 = R_EDX = (uint32_t)(res >> 32);
}
static inline void mul64_rax(x64emu_t *emu, uint64_t s)
{
emu->df = d_mul64;
__int128 res = (__int128)R_RAX * s;
emu->res = R_RAX = (uint64_t)res;
emu->op1 = R_RDX = (uint64_t)(res >> 64);
emu->res.u64 = R_RAX = (uint64_t)res;
emu->op1.u64 = R_RDX = (uint64_t)(res >> 64);
}
void idiv8 (x64emu_t *emu, uint8_t s);
+551 -36
View File
@@ -21,7 +21,7 @@
#include "bridge.h"
#include "signals.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#include "../dynarec/arm64_lock.h"
#endif
#include "modrm.h"
@@ -33,11 +33,13 @@ int Run(x64emu_t *emu, int step)
uint8_t opcode;
uint8_t nextop;
reg64_t *oped, *opgd;
uint8_t tmp8u;
uint8_t tmp8u, tmp8u2;
int8_t tmp8s;
uint32_t tmp32u;
uint64_t tmp64u;
uint16_t tmp16u;
int32_t tmp32s;
uint32_t tmp32u, tmp32u2;
int64_t tmp64s;
uint64_t tmp64u, tmp64u2, tmp64u3;
rex_t rex;
int rep; // 0 none, 1=F2 prefix, 2=F3 prefix
int unimp = 0;
@@ -246,14 +248,21 @@ x64emurun:
break;
case 0x66: /* 16bits prefix */
if(Run66(emu, rex)) {
if(Run66(emu, rex, rep)) {
unimp = 1;
goto fini;
}
if(emu->quit)
goto fini;
break;
case 0x67: /* reduce EASize prefix */
if(Run67(emu, rex)) {
unimp = 1;
goto fini;
}
if(emu->quit)
goto fini;
break;
case 0x68: /* Push Id */
Push(emu, F32S64);
break;
@@ -270,6 +279,20 @@ x64emurun:
else
GD->dword[0] = imul32(emu, ED->dword[0], tmp64u);
break;
case 0x6A: /* Push Ib */
tmp64s = F8S;
Push(emu, (uint64_t)tmp64s);
break;
case 0x6B: /* IMUL Gd,Ed,Ib */
nextop = F8;
GETED(1);
GETGD;
tmp64s = F8S;
if(rex.w)
GD->q[0] = imul64(emu, ED->q[0], (uint64_t)tmp64s);
else
GD->q[0] = imul32(emu, ED->dword[0], (uint32_t)tmp64s);
break;
GOCOND(0x70
, tmp8s = F8S; CHECK_FLAGS(emu);
@@ -355,31 +378,63 @@ x64emurun:
else
test32(emu, ED->dword[0], GD->dword[0]);
break;
case 0x86: /* XCHG Eb,Gb */
nextop = F8;
#ifdef DYNAREC
GETEB(0);
GETGB;
if((nextop&0xC0)==0xC0) { // reg / reg: no lock
tmp8u = GB;
GB = EB->byte[0];
EB->byte[0] = tmp8u;
} else {
do {
tmp8u = arm64_lock_read_b(EB);
} while(arm64_lock_write_b(EB, GB));
GB = tmp8u;
}
// dynarec use need it's own mecanism
#else
GETEB(0);
GETGB;
if((nextop&0xC0)!=0xC0)
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
tmp8u = GB;
GB = EB->byte[0];
EB->byte[0] = tmp8u;
if((nextop&0xC0)!=0xC0)
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0x87: /* XCHG Ed,Gd */
nextop = F8;
#ifdef DYNAREC
GET_ED;
GETED(0);
GETGD;
if((nextop&0xC0)==0xC0) {
tmp32u = GD.dword[0];
GD.dword[0] = ED->dword[0];
ED->dword[0] = tmp32u;
} else {
if(((uintptr_t)ED)&3)
{
// not aligned, dont't try to "LOCK"
tmp32u = ED->dword[0];
ED->dword[0] = GD.dword[0];
GD.dword[0] = tmp32u;
if(rex.w) {
tmp64u = GD->q[0];
GD->q[0] = ED->q[0];
ED->q[0] = tmp64u;
} else {
// XCHG is supposed to automaticaly LOCK memory bus
GD.dword[0] = arm_lock_xchg(ED, GD.dword[0]);
tmp32u = GD->dword[0];
GD->q[0] = ED->dword[0];
ED->q[0] = tmp32u;
}
} else {
if(rex.w) {
GD->q[0] = arm64_lock_xchg(ED, GD->q[0]);
} else {
do {
tmp32u = arm64_lock_read_d(ED);
} while(arm64_lock_write_d(ED, GD->dword[0]));
GD->q[0] = tmp32u;
}
}
#else
GETED(0);
GETGD;
if((nextop&0xC0)!=0xC0)
if(!MODREG)
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
if(rex.w) {
tmp64u = GD->q[0];
@@ -387,10 +442,13 @@ x64emurun:
ED->q[0] = tmp64u;
} else {
tmp32u = GD->dword[0];
GD->dword[0] = ED->dword[0];
ED->dword[0] = tmp32u;
GD->q[0] = ED->dword[0];
if(MODREG)
ED->q[0] = tmp32u;
else
ED->dword[0] = tmp32u;
}
if((nextop&0xC0)!=0xC0)
if(!MODREG)
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
@@ -414,7 +472,12 @@ x64emurun:
ED->dword[0] = GD->dword[0];
}
break;
case 0x8A: /* MOV Gb,Eb */
nextop = F8;
GETEB(0);
GETGB;
GB = EB->byte[0];
break;
case 0x8B: /* MOV Gd,Ed */
nextop = F8;
GETED(0);
@@ -432,25 +495,206 @@ x64emurun:
if(rex.w)
GD->q[0] = (uint64_t)ED;
else
GD->dword[0] = (uint32_t)(uintptr_t)ED; // RAZ upper part?
GD->q[0] = (uint32_t)(uintptr_t)ED;
break;
case 0x8F: /* POP Ed */
nextop = F8;
if(MODREG) {
emu->regs[(nextop&7)+(rex.b<<3)].q[0] = Pop(emu);
} else {
tmp64u = Pop(emu); // this order allows handling POP [ESP] and variant
GETED(0);
R_ESP -= sizeof(void*); // to prevent issue with SEGFAULT
ED->q[0] = tmp64u;
R_ESP += sizeof(void*);
}
break;
case 0x90: /* NOP */
break;
case 0x98: /* CWDE */
if(rex.w)
emu->regs[_AX].sq[0] = emu->regs[_AX].sdword[0];
else
else {
emu->regs[_AX].sdword[0] = emu->regs[_AX].sword[0];
emu->regs[_AX].dword[1] = 0;
}
break;
case 0x99: /* CDQ */
if(rex.w)
R_RDX=(R_RAX & 0x8000000000000000L)?0xFFFFFFFFFFFFFFFFL:0x0000000000000000L;
R_RDX=(R_RAX & 0x8000000000000000LL)?0xFFFFFFFFFFFFFFFFLL:0x0000000000000000LL;
else
R_RDX=(R_EAX & 0x80000000)?0xFFFFFFFFFFFFFFFFL:0x0000000000000000L;
R_RDX=(R_EAX & 0x80000000)?0x00000000FFFFFFFFLL:0x0000000000000000LL;
break;
case 0x9B: /* FWAIT */
break;
case 0x9C: /* PUSHF */
CHECK_FLAGS(emu);
Push(emu, emu->eflags.x64);
break;
case 0x9D: /* POPF */
emu->eflags.x64 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
RESET_FLAGS(emu);
break;
case 0xA4: /* MOVSB */
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
tmp64u = (rep)?R_RCX:1L;
while(tmp64u) {
*(uint8_t*)R_RDI = *(uint8_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
--tmp64u;
}
if(rep)
R_RCX = tmp64u;
break;
case 0xA5: /* (REP) MOVSD */
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
tmp64u = (rep)?R_RCX:1L;
if(rex.w) {
tmp8s *= 8;
while(tmp64u) {
--tmp64u;
*(uint64_t*)R_RDI = *(uint64_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
}
} else {
tmp8s *= 4;
while(tmp64u) {
--tmp64u;
*(uint32_t*)R_RDI = *(uint32_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
}
}
if(rep)
R_RCX = tmp64u;
break;
case 0xA6: /* (REPZ/REPNE) CMPSB */
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
switch(rep) {
case 1:
tmp64u = R_RCX;
while(tmp64u) {
--tmp64u;
tmp8u = *(uint8_t*)R_RDI;
tmp8u2 = *(uint8_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
if(tmp8u==tmp8u2)
break;
}
if(R_RCX) cmp8(emu, tmp8u2, tmp8u);
R_RCX = tmp64u;
break;
case 2:
tmp64u = R_RCX;
while(tmp64u) {
--tmp64u;
tmp8u = *(uint8_t*)R_RDI;
tmp8u2 = *(uint8_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
if(tmp8u!=tmp8u2)
break;
}
if(R_RCX) cmp8(emu, tmp8u2, tmp8u);
R_RCX = tmp64u;
break;
default:
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
tmp8u = *(uint8_t*)R_RDI;
tmp8u2 = *(uint8_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
cmp8(emu, tmp8u2, tmp8u);
}
break;
case 0xA7: /* (REPZ/REPNE) CMPSD */
if(rex.w)
tmp8s = ACCESS_FLAG(F_DF)?-8:+8;
else
tmp8s = ACCESS_FLAG(F_DF)?-4:+4;
switch(rep) {
case 1:
tmp64u = R_RCX;
if(rex.w) {
while(tmp64u) {
--tmp64u;
tmp64u3 = *(uint64_t*)R_RDI;
tmp64u2 = *(uint64_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
if(tmp64u3==tmp64u2)
break;
}
if(R_RCX) cmp64(emu, tmp64u2, tmp64u3);
} else {
while(tmp64u) {
--tmp64u;
tmp32u = *(uint32_t*)R_RDI;
tmp32u2 = *(uint32_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
if(tmp32u==tmp32u2)
break;
}
if(R_RCX) cmp32(emu, tmp32u2, tmp32u);
}
R_RCX = tmp64u;
break;
case 2:
tmp64u = R_RCX;
if(rex.w) {
while(tmp64u) {
--tmp64u;
tmp64u3 = *(uint64_t*)R_RDI;
tmp64u2 = *(uint64_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
if(tmp64u3!=tmp64u2)
break;
}
if(R_RCX) cmp64(emu, tmp64u2, tmp64u3);
} else {
while(tmp64u) {
--tmp64u;
tmp32u = *(uint32_t*)R_RDI;
tmp32u2 = *(uint32_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
if(tmp32u!=tmp32u2)
break;
}
if(R_RCX) cmp32(emu, tmp32u2, tmp32u);
}
R_RCX = tmp64u;
break;
default:
if(rex.w) {
tmp8s = ACCESS_FLAG(F_DF)?-8:+8;
tmp64u = *(uint64_t*)R_RDI;
tmp64u2 = *(uint64_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
cmp64(emu, tmp64u2, tmp64u);
} else {
tmp8s = ACCESS_FLAG(F_DF)?-4:+4;
tmp32u = *(uint32_t*)R_RDI;
tmp32u2 = *(uint32_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
cmp32(emu, tmp32u2, tmp32u);
}
}
break;
case 0xA8: /* TEST AL, Ib */
test8(emu, R_AL, F8);
break;
case 0xA9: /* TEST EAX, Id */
if(rex.w)
test64(emu, R_RAX, F32S64);
@@ -458,6 +702,17 @@ x64emurun:
test32(emu, R_EAX, F32);
break;
case 0xAA: /* (REP) STOSB */
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
tmp64u = (rep)?R_RCX:1L;
while(tmp64u) {
*(uint8_t*)R_RDI = R_AL;
R_RDI += tmp8s;
--tmp64u;
}
if(rep)
R_RCX = tmp64u;
break;
case 0xAB: /* (REP) STOSD */
if(rex.w)
tmp8s = ACCESS_FLAG(F_DF)?-8:+8;
@@ -479,7 +734,148 @@ x64emurun:
if(rep)
R_RCX = tmp64u;
break;
case 0xAC: /* LODSB */
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
tmp64u = (rep)?R_RCX:1L;
while(tmp64u) {
R_AL = *(uint8_t*)R_RSI;
R_RSI += tmp8s;
--tmp64u;
}
if(rep)
R_RCX = tmp64u;
break;
case 0xAD: /* (REP) LODSD */
if(rex.w)
tmp8s = ACCESS_FLAG(F_DF)?-8:+8;
else
tmp8s = ACCESS_FLAG(F_DF)?-4:+4;
tmp64u = (rep)?R_RCX:1L;
if((rex.w))
while(tmp64u) {
R_RAX = *(uint64_t*)R_RSI;
R_RSI += tmp8s;
--tmp64u;
}
else
while(tmp64u) {
R_RAX = *(uint32_t*)R_RSI;
R_RSI += tmp8s;
--tmp64u;
}
if(rep)
R_RCX = tmp64u;
break;
case 0xAE: /* (REPZ/REPNE) SCASB */
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
switch(rep) {
case 1:
tmp64u = R_RCX;
while(tmp64u) {
--tmp64u;
tmp8u = *(uint8_t*)R_RDI;
R_RDI += tmp8s;
if(R_AL==tmp8u)
break;
}
if(R_RCX) cmp8(emu, R_AL, tmp8u);
R_RCX = tmp64u;
break;
case 2:
tmp64u = R_RCX;
while(tmp64u) {
--tmp64u;
tmp8u = *(uint8_t*)R_RDI;
R_EDI += tmp8s;
if(R_AL!=tmp8u)
break;
}
if(R_RCX) cmp8(emu, R_AL, tmp8u);
R_RCX = tmp64u;
break;
default:
cmp8(emu, R_AL, *(uint8_t*)R_RDI);
R_RDI += tmp8s;
}
break;
case 0xAF: /* (REPZ/REPNE) SCASD */
if(rex.w)
tmp8s = ACCESS_FLAG(F_DF)?-8:+8;
else
tmp8s = ACCESS_FLAG(F_DF)?-4:+4;
switch(rep) {
case 1:
tmp64u = R_RCX;
if(rex.w) {
while(tmp64u) {
--tmp64u;
tmp64u2 = *(uint64_t*)R_RDI;
R_RDI += tmp8s;
if(R_RAX==tmp64u2)
break;
}
if(R_RCX) cmp64(emu, R_RAX, tmp64u2);
} else {
while(tmp64u) {
--tmp64u;
tmp32u = *(uint32_t*)R_RDI;
R_RDI += tmp8s;
if(R_EAX==tmp32u)
break;
}
if(R_RCX) cmp32(emu, R_EAX, tmp32u);
}
R_RCX = tmp64u;
break;
case 2:
tmp64u = R_RCX;
if(rex.w) {
while(tmp64u) {
--tmp64u;
tmp64u2 = *(uint64_t*)R_RDI;
R_RDI += tmp8s;
if(R_RAX!=tmp64u2)
break;
}
if(R_RCX) cmp64(emu, R_RAX, tmp64u2);
} else {
while(tmp64u) {
--tmp64u;
tmp32u = *(uint32_t*)R_RDI;
R_RDI += tmp8s;
if(R_EAX!=tmp32u)
break;
}
if(R_RCX) cmp32(emu, R_EAX, tmp32u);
}
R_RCX = tmp64u;
break;
default:
if(rex.w)
cmp64(emu, R_RAX, *(uint64_t*)R_RDI);
else
cmp32(emu, R_EAX, *(uint32_t*)R_RDI);
R_RDI += tmp8s;
}
break;
case 0xB0: /* MOV AL,Ib */
case 0xB1: /* MOV CL,Ib */
case 0xB2: /* MOV DL,Ib */
case 0xB3: /* MOV BL,Ib */
if(rex.rex)
emu->regs[(opcode&7)+(rex.b<<3)].byte[0] = F8;
else
emu->regs[opcode&3].byte[0] = F8;
break;
case 0xB4: /* MOV AH,Ib */
case 0xB5: /* ... */
case 0xB6:
case 0xB7:
if(rex.rex)
emu->regs[(opcode&7)+(rex.b<<3)].byte[0] = F8;
else
emu->regs[opcode&3].byte[1] = F8;
break;
case 0xB8: /* MOV EAX,Id */
case 0xB9: /* MOV ECX,Id */
case 0xBA: /* MOV EDX,Id */
@@ -494,6 +890,21 @@ x64emurun:
emu->regs[(opcode&7)+(rex.b<<3)].q[0] = F32;
break;
case 0xC0: /* GRP2 Eb,Ib */
nextop = F8;
GETEB(1);
tmp8u = F8/* & 0x1f*/; // masking done in each functions
switch((nextop>>3)&7) {
case 0: EB->byte[0] = rol8(emu, EB->byte[0], tmp8u); break;
case 1: EB->byte[0] = ror8(emu, EB->byte[0], tmp8u); break;
case 2: EB->byte[0] = rcl8(emu, EB->byte[0], tmp8u); break;
case 3: EB->byte[0] = rcr8(emu, EB->byte[0], tmp8u); break;
case 4:
case 6: EB->byte[0] = shl8(emu, EB->byte[0], tmp8u); break;
case 5: EB->byte[0] = shr8(emu, EB->byte[0], tmp8u); break;
case 7: EB->byte[0] = sar8(emu, EB->byte[0], tmp8u); break;
}
break;
case 0xC1: /* GRP2 Ed,Ib */
nextop = F8;
GETED(1);
@@ -556,7 +967,21 @@ x64emurun:
else
ED->dword[0] = F32;
break;
case 0xC8: /* ENTER Iw,Ib */
tmp16u = F16;
tmp8u = (F8) & 0x1f;
tmp64u = R_RBP;
Push(emu, R_RBP);
R_RBP = R_RSP;
if (tmp8u) {
for (tmp8u2 = 1; tmp8u2 < tmp8u; tmp8u2++) {
tmp64u -= sizeof(void*);
Push(emu, *((uintptr_t*)tmp64u));
}
Push(emu, R_RBP);
}
R_RSP -= tmp16u;
break;
case 0xC9: /* LEAVE */
R_RSP = R_RBP;
R_RBP = Pop(emu);
@@ -567,6 +992,22 @@ x64emurun:
if(emu->quit) goto fini;
break;
case 0xD0: /* GRP2 Eb,1 */
case 0xD2: /* GRP2 Eb,CL */
nextop = F8;
GETEB(0);
tmp8u = (opcode==0xD0)?1:R_CL;
switch((nextop>>3)&7) {
case 0: EB->byte[0] = rol8(emu, EB->byte[0], tmp8u); break;
case 1: EB->byte[0] = ror8(emu, EB->byte[0], tmp8u); break;
case 2: EB->byte[0] = rcl8(emu, EB->byte[0], tmp8u); break;
case 3: EB->byte[0] = rcr8(emu, EB->byte[0], tmp8u); break;
case 4:
case 6: EB->byte[0] = shl8(emu, EB->byte[0], tmp8u); break;
case 5: EB->byte[0] = shr8(emu, EB->byte[0], tmp8u); break;
case 7: EB->byte[0] = sar8(emu, EB->byte[0], tmp8u); break;
}
break;
case 0xD1: /* GRP2 Ed,1 */
case 0xD3: /* GRP2 Ed,CL */
nextop = F8;
@@ -609,6 +1050,17 @@ x64emurun:
}
break;
case 0xD7: /* XLAT */
R_AL = *(uint8_t*)(R_RBX + R_AL);
break;
case 0xD8: /* x87 opcodes */
if(RunD8(emu, rex)) {
unimp = 1;
goto fini;
}
if(emu->quit)
goto fini;
break;
case 0xD9: /* x87 opcodes */
if(RunD9(emu, rex)) {
unimp = 1;
@@ -617,7 +1069,14 @@ x64emurun:
if(emu->quit)
goto fini;
break;
case 0xDA: /* x87 opcodes */
if(RunDA(emu, rex)) {
unimp = 1;
goto fini;
}
if(emu->quit)
goto fini;
break;
case 0xDB: /* x87 opcodes */
if(RunDB(emu, rex)) {
unimp = 1;
@@ -627,6 +1086,15 @@ x64emurun:
goto fini;
break;
case 0xDD: /* x87 opcodes */
if(RunDD(emu, rex)) {
unimp = 1;
goto fini;
}
if(emu->quit)
goto fini;
break;
case 0xDF: /* x87 opcodes */
if(RunDF(emu, rex)) {
unimp = 1;
@@ -731,27 +1199,74 @@ x64emurun:
test32(emu, ED->dword[0], tmp32u);
break;
case 2: /* NOT Ed */
ED->dword[0] = not32(emu, ED->dword[0]);
if(MODREG)
ED->q[0] = not32(emu, ED->dword[0]);
else
ED->dword[0] = not32(emu, ED->dword[0]);
break;
case 3: /* NEG Ed */
ED->dword[0] = neg32(emu, ED->dword[0]);
if(MODREG)
ED->q[0] = neg32(emu, ED->dword[0]);
else
ED->dword[0] = neg32(emu, ED->dword[0]);
break;
case 4: /* MUL EAX,Ed */
mul32_eax(emu, ED->dword[0]);
emu->regs[_AX].dword[1] = 0;
break;
case 5: /* IMUL EAX,Ed */
imul32_eax(emu, ED->dword[0]);
emu->regs[_AX].dword[1] = 0;
break;
case 6: /* DIV Ed */
div32(emu, ED->dword[0]);
emu->regs[_AX].dword[1] = 0;
emu->regs[_DX].dword[1] = 0;
break;
case 7: /* IDIV Ed */
idiv32(emu, ED->dword[0]);
emu->regs[_AX].dword[1] = 0;
emu->regs[_DX].dword[1] = 0;
break;
}
}
break;
case 0xF8: /* CLC */
CHECK_FLAGS(emu);
CLEAR_FLAG(F_CF);
break;
case 0xF9: /* STC */
CHECK_FLAGS(emu);
SET_FLAG(F_CF);
break;
case 0xFA: /* CLI */
CLEAR_FLAG(F_IF); //not really handled...
break;
case 0xFB: /* STI */
SET_FLAG(F_IF);
break;
case 0xFC: /* CLD */
CLEAR_FLAG(F_DF);
break;
case 0xFD: /* STD */
SET_FLAG(F_DF);
break;
case 0xFE: /* GRP 5 Eb */
nextop = F8;
GETEB(0);
switch((nextop>>3)&7) {
case 0: /* INC Eb */
ED->byte[0] = inc8(emu, ED->byte[0]);
break;
case 1: /* DEC Ed */
ED->byte[0] = dec8(emu, ED->byte[0]);
break;
default:
unimp = 1;
goto fini;
}
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
GETED(0);
@@ -760,13 +1275,13 @@ x64emurun:
if(rex.w)
ED->q[0] = inc64(emu, ED->q[0]);
else
ED->dword[0] = inc32(emu, ED->dword[0]);
ED->q[0] = inc32(emu, ED->dword[0]);
break;
case 1: /* DEC Ed */
if(rex.w)
ED->q[0] = dec64(emu, ED->q[0]);
else
ED->dword[0] = dec32(emu, ED->dword[0]);
ED->q[0] = dec32(emu, ED->dword[0]);
break;
case 2: /* CALL NEAR Ed */
tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);
+690 -5
View File
@@ -22,7 +22,7 @@
#include "bridge.h"
#include "signals.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#include "../dynarec/arm64_lock.h"
#endif
#include "modrm.h"
@@ -32,10 +32,12 @@ int Run0F(x64emu_t *emu, rex_t rex)
uint8_t opcode;
uint8_t nextop;
uint8_t tmp8u;
int8_t tmp8s;
int32_t tmp32s, tmp32s2;
uint32_t tmp32u;
uint32_t tmp32u, tmp32u2;
uint64_t tmp64u, tmp64u2;
reg64_t *oped, *opgd;
sse_regs_t *opex, *opgx;
sse_regs_t *opex, *opgx, eax1;
mmx87_regs_t *opem, *opgm;
opcode = F8;
@@ -46,18 +48,75 @@ int Run0F(x64emu_t *emu, rex_t rex)
x64Syscall(emu);
break;
case 0x10: /* MOVUPS Gx,Ex */
nextop = F8;
GETEX(0);
GETGX;
memcpy(GX, EX, 16); // unaligned, so carreful
break;
case 0x11: /* MOVUPS Ex,Gx */
nextop = F8;
GETEX(0);
GETGX;
memcpy(EX, GX, 16); // unaligned, so carreful
break;
case 0x12:
nextop = F8;
GETEX(0);
GETGX;
if((nextop&0xC0)==0xC0) /* MOVHLPS Gx,Ex */
GX->q[0] = EX->q[1];
else
GX->q[0] = EX->q[0]; /* MOVLPS Gx,Ex */
break;
case 0x13: /* MOVLPS Ex,Gx */
nextop = F8;
GETEX(0);
GETGX;
EX->q[0] = GX->q[0];
break;
case 0x14: /* UNPCKLPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->ud[3] = EX->ud[1];
GX->ud[2] = GX->ud[1];
GX->ud[1] = EX->ud[0];
break;
case 0x15: /* UNPCKHPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->ud[0] = GX->ud[2];
GX->ud[1] = EX->ud[2];
GX->ud[2] = GX->ud[3];
GX->ud[3] = EX->ud[3];
break;
case 0x16: /* MOVHPS Gx,Ex */
nextop = F8; /* MOVLHPS Gx,Ex (Ex==reg) */
GETEX(0);
GETGX;
GX->q[1] = EX->q[0];
break;
case 0x17: /* MOVHPS Ex,Gx */
nextop = F8;
GETEX(0);
GETGX;
EX->q[0] = GX->q[1];
break;
case 0x1F: /* NOP (multi-byte) */
nextop = F8;
GETED(0);
break;
case 0x28: /* MOVAPS Gx,Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->q[0] = EX->q[0];
GX->q[1] = EX->q[1];
break;
case 0x29: /* MOVAPS Ex,Gx */
nextop = F8;
GETEX(0);
@@ -65,6 +124,69 @@ int Run0F(x64emu_t *emu, rex_t rex)
EX->q[0] = GX->q[0];
EX->q[1] = GX->q[1];
break;
case 0x2A: /* CVTPI2PS Gx, Em */
nextop = F8;
GETEM(0);
GETGX;
GX->f[0] = EM->sd[0];
GX->f[1] = EM->sd[1];
break;
case 0x2B: /* MOVNTPS Ex,Gx */
nextop = F8;
GETEX(0);
GETGX;
EX->q[0] = GX->q[0];
EX->q[1] = GX->q[1];
break;
case 0x2C: /* CVTTPS2PI Gm, Ex */
nextop = F8;
GETEX(0);
GETGM;
GM->sd[1] = EX->f[1];
GM->sd[0] = EX->f[0];
break;
case 0x2D: /* CVTPS2PI Gm, Ex */
// rounding should be done; and indefinite integer should also be assigned if overflow or NaN/Inf
nextop = F8;
GETEX(0);
GETGM;
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GM->sd[1] = floorf(EX->f[1]+0.5f);
GM->sd[0] = floorf(EX->f[0]+0.5f);
break;
case ROUND_Down:
GM->sd[1] = floorf(EX->f[1]);
GM->sd[0] = floorf(EX->f[0]);
break;
case ROUND_Up:
GM->sd[1] = ceilf(EX->f[1]);
GM->sd[0] = ceilf(EX->f[0]);
break;
case ROUND_Chop:
GM->sd[1] = EX->f[1];
GM->sd[0] = EX->f[0];
break;
}
break;
case 0x2E: /* UCOMISS Gx, Ex */
// same for now
case 0x2F: /* COMISS Gx, Ex */
RESET_FLAGS(emu);
nextop = F8;
GETEX(0);
GETGX;
if(isnan(GX->f[0]) || isnan(EX->f[0])) {
SET_FLAG(F_ZF); SET_FLAG(F_PF); SET_FLAG(F_CF);
} else if(isgreater(GX->f[0], EX->f[0])) {
CLEAR_FLAG(F_ZF); CLEAR_FLAG(F_PF); CLEAR_FLAG(F_CF);
} else if(isless(GX->f[0], EX->f[0])) {
CLEAR_FLAG(F_ZF); CLEAR_FLAG(F_PF); SET_FLAG(F_CF);
} else {
SET_FLAG(F_ZF); CLEAR_FLAG(F_PF); CLEAR_FLAG(F_CF);
}
CLEAR_FLAG(F_OF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF);
break;
GOCOND(0x40
@@ -72,10 +194,129 @@ int Run0F(x64emu_t *emu, rex_t rex)
GETED(0);
GETGD;
CHECK_FLAGS(emu);
, if(rex.w) {GD->q[0] = ED->q[0]; } else {GD->dword[0] = ED->dword[0];}
,
, if(rex.w) {GD->q[0] = ED->q[0]; } else {GD->q[0] = ED->dword[0];}
, if(!rex.w) GD->dword[1] = 0;
) /* 0x40 -> 0x4F CMOVxx Gd,Ed */ // conditional move, no sign
case 0x50: /* MOVMSKPS Gd, Ex */
nextop = F8;
GETEX(0);
GETGD;
GD->dword[0] = 0;
for(int i=0; i<4; ++i)
GD->dword[0] |= ((EX->ud[i]>>31)&1)<<i;
break;
case 0x51: /* SQRTPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
GX->f[i] = sqrtf(EX->f[i]);
break;
case 0x52: /* RSQRTPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
GX->f[i] = 1.0f/sqrtf(EX->f[i]);
break;
case 0x53: /* RCPPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
GX->f[i] = 1.0f/EX->f[i];
break;
case 0x54: /* ANDPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
GX->ud[i] &= EX->ud[i];
break;
case 0x55: /* ANDNPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
GX->ud[i] = (~GX->ud[i]) & EX->ud[i];
break;
case 0x56: /* ORPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
GX->ud[i] |= EX->ud[i];
break;
case 0x57: /* XORPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
GX->ud[i] ^= EX->ud[i];
break;
case 0x58: /* ADDPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
GX->f[i] += EX->f[i];
break;
case 0x59: /* MULPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
GX->f[i] *= EX->f[i];
break;
case 0x5A: /* CVTPS2PD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->d[1] = EX->f[1];
GX->d[0] = EX->f[0];
break;
case 0x5B: /* CVTDQ2PS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->f[0] = EX->sd[0];
GX->f[1] = EX->sd[1];
GX->f[2] = EX->sd[2];
GX->f[3] = EX->sd[3];
break;
case 0x5C: /* SUBPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
GX->f[i] -= EX->f[i];
break;
case 0x5D: /* MINPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i) {
if (isnan(GX->f[i]) || isnan(EX->f[i]) || isless(EX->f[i], GX->f[i]))
GX->f[i] = EX->f[i];
}
break;
case 0x5E: /* DIVPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
GX->f[i] /= EX->f[i];
break;
case 0x5F: /* MAXPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i) {
if (isnan(GX->f[i]) || isnan(EX->f[i]) || isgreater(EX->f[i], GX->f[i]))
GX->f[i] = EX->f[i];
}
break;
case 0x60: /* PUNPCKLBW Gm, Em */
nextop = F8;
GETEM(0);
@@ -270,7 +511,86 @@ int Run0F(x64emu_t *emu, rex_t rex)
tmp32u = R_EAX;
my_cpuid(emu, tmp32u);
break;
case 0xA3: /* BT Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GETED(0);
GETGD;
tmp8u = GD->byte[0];
if(!MODREG)
{
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
}
break;
case 0xA4: /* SHLD Ed,Gd,Ib */
case 0xA5: /* SHLD Ed,Gd,CL */
nextop = F8;
GETED((nextop==0xA4)?1:0);
GETGD;
if(opcode==0xA4)
tmp8u = F8;
else
tmp8u = R_CL;
if(rex.w)
ED->q[0] = shld64(emu, ED->q[0], GD->q[0], tmp8u);
else
ED->q[0] = shld32(emu, ED->dword[0], GD->dword[0], tmp8u);
break;
case 0xAB: /* BTS Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GETED(0);
GETGD;
tmp8u = GD->byte[0];
if(!MODREG)
{
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else {
ED->q[0] |= (1LL<<tmp8u);
CLEAR_FLAG(F_CF);
}
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else {
ED->dword[0] |= (1<<tmp8u);
CLEAR_FLAG(F_CF);
}
if(MODREG)
ED->dword[1] = 0;
}
break;
case 0xAC: /* SHRD Ed,Gd,Ib */
case 0xAD: /* SHRD Ed,Gd,CL */
nextop = F8;
GETED((nextop==0xAC)?1:0);
GETGD;
tmp8u = (opcode==0xAC)?(F8):R_CL;
if(rex.w)
ED->q[0] = shrd64(emu, ED->q[0], GD->q[0], tmp8u);
else
ED->q[0] = shrd32(emu, ED->dword[0], GD->dword[0], tmp8u);
break;
case 0xAE: /* Grp Ed (SSE) */
nextop = F8;
if((nextop&0xF8)==0xE8) {
@@ -284,6 +604,24 @@ int Run0F(x64emu_t *emu, rex_t rex)
}
GETED(0);
switch((nextop>>3)&7) {
case 0: /* FXSAVE Ed */
if(rex.w)
fpu_fxsave64(emu, ED);
else
fpu_fxsave32(emu, ED);
break;
case 1: /* FXRSTOR Ed */
if(rex.w)
fpu_fxrstor64(emu, ED);
else
fpu_fxrstor32(emu, ED);
break;
case 2: /* LDMXCSR Md */
emu->mxcsr = ED->dword[0];
break;
case 3: /* STMXCSR Md */
ED->dword[0] = emu->mxcsr;
break;
default:
return 1;
}
@@ -297,6 +635,68 @@ int Run0F(x64emu_t *emu, rex_t rex)
else
GD->dword[0] = imul32(emu, GD->dword[0], ED->dword[0]);
break;
case 0xB0: /* CMPXCHG Eb,Gb */
nextop = F8;
GETEB(0);
GETGB;
cmp8(emu, R_AL, EB->byte[0]);
if(ACCESS_FLAG(F_ZF)) {
EB->byte[0] = GB;
} else {
R_AL = EB->byte[0];
}
break;
case 0xB1: /* CMPXCHG Ed,Gd */
nextop = F8;
GETED(0);
GETGD;
if(rex.w) {
cmp64(emu, R_RAX, ED->q[0]);
if(ACCESS_FLAG(F_ZF)) {
ED->q[0] = GD->q[0];
} else {
R_RAX = ED->q[0];
}
} else {
cmp32(emu, R_EAX, ED->dword[0]);
if(ACCESS_FLAG(F_ZF)) {
if(MODREG)
ED->q[0] = GD->dword[0];
else
ED->dword[0] = GD->dword[0];
} else {
R_RAX = ED->dword[0];
}
}
break;
case 0xB3: /* BTR Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GETED(0);
GETGD;
tmp8u = GD->byte[0];
if(!MODREG)
{
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
ED->q[0] ^= (1LL<<tmp8u);
} else
CLEAR_FLAG(F_CF);
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
if(MODREG)
ED->dword[1] = 0;
}
break;
case 0xB6: /* MOVZX Gd,Eb */
nextop = F8;
@@ -311,6 +711,187 @@ int Run0F(x64emu_t *emu, rex_t rex)
GD->q[0] = EW->word[0];
break;
case 0xBA:
nextop = F8;
switch((nextop>>3)&7) {
case 4: /* BT Ed,Ib */
CHECK_FLAGS(emu);
GETED(1);
tmp8u = F8;
if(!MODREG)
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
}
break;
case 5: /* BTS Ed, Ib */
CHECK_FLAGS(emu);
GETED(1);
tmp8u = F8;
if(!MODREG)
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
} else {
ED->q[0] ^= (1LL<<tmp8u);
CLEAR_FLAG(F_CF);
}
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
} else {
ED->dword[0] ^= (1<<tmp8u);
CLEAR_FLAG(F_CF);
}
}
break;
case 6: /* BTR Ed, Ib */
CHECK_FLAGS(emu);
GETED(1);
tmp8u = F8;
if(!MODREG)
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
ED->q[0] ^= (1LL<<tmp8u);
} else
CLEAR_FLAG(F_CF);
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
}
break;
case 7: /* BTC Ed, Ib */
CHECK_FLAGS(emu);
GETED(1);
tmp8u = F8;
if(!MODREG)
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
ED->q[0] ^= (1LL<<tmp8u);
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
}
break;
default:
return 1;
}
break;
case 0xBB: /* BTC Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GETED(0);
GETGD;
tmp8u = GD->byte[0];
if(!MODREG)
{
if(rex.w)
ED=(reg64_t*)(((uint64_t*)(ED))+(tmp8u>>6));
else
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
ED->q[0] ^= (1LL<<tmp8u);
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
if(MODREG)
ED->dword[1] = 0;
}
break;
case 0xBC: /* BSF Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GETED(0);
GETGD;
if(rex.w) {
tmp64u = ED->q[0];
if(tmp64u) {
CLEAR_FLAG(F_ZF);
tmp8u = 0;
while(!(tmp64u&(1LL<<tmp8u))) ++tmp8u;
GD->q[0] = tmp8u;
} else {
SET_FLAG(F_ZF);
}
} else {
tmp32u = ED->dword[0];
if(tmp32u) {
CLEAR_FLAG(F_ZF);
tmp8u = 0;
while(!(tmp32u&(1<<tmp8u))) ++tmp8u;
GD->q[0] = tmp8u;
} else {
SET_FLAG(F_ZF);
}
}
break;
case 0xBD: /* BSR Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GETED(0);
GETGD;
if(rex.w) {
tmp64u = ED->q[0];
if(tmp64u) {
CLEAR_FLAG(F_ZF);
tmp8u = 63;
while(!(tmp64u&(1LL<<tmp8u))) --tmp8u;
GD->q[0] = tmp8u;
} else {
SET_FLAG(F_ZF);
}
} else {
tmp32u = ED->dword[0];
if(tmp32u) {
CLEAR_FLAG(F_ZF);
tmp8u = 31;
while(!(tmp32u&(1<<tmp8u))) --tmp8u;
GD->q[0] = tmp8u;
} else {
SET_FLAG(F_ZF);
}
}
break;
case 0xBE: /* MOVSX Gd,Eb */
nextop = F8;
GETEB(0);
@@ -333,6 +914,110 @@ int Run0F(x64emu_t *emu, rex_t rex)
GD->dword[1] = 0;
}
break;
case 0xC0: /* XADD Gb,Eb */
nextop = F8;
GETEB(0);
GETGB;
tmp8u = add8(emu, EB->byte[0], GB);
GB = EB->byte[0];
EB->byte[0] = tmp8u;
break;
case 0xC1: /* XADD Gd,Ed */
nextop = F8;
GETED(0);
GETGD;
if(rex.w) {
tmp64u = add64(emu, ED->q[0], GD->q[0]);
GD->q[0] = ED->q[0];
ED->q[0] = tmp64u;
} else {
tmp32u = add32(emu, ED->dword[0], GD->dword[0]);
GD->q[0] = ED->dword[0];
if(MODREG)
ED->q[0] = tmp32u;
else
ED->dword[0] = tmp32u;
}
break;
case 0xC2: /* CMPPS Gx, Ex, Ib */
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
for(int i=0; i<4; ++i) {
tmp8s = 0;
switch(tmp8u&7) {
case 0: tmp8s=(GX->f[i] == EX->f[i]); break;
case 1: tmp8s=isless(GX->f[i], EX->f[i]); break;
case 2: tmp8s=islessequal(GX->f[i], EX->f[i]); break;
case 3: tmp8s=isnan(GX->f[i]) || isnan(EX->f[i]); break;
case 4: tmp8s=(GX->f[i] != EX->f[i]); break;
case 5: tmp8s=isnan(GX->f[i]) || isnan(EX->f[i]) || isgreaterequal(GX->f[i], EX->f[i]); break;
case 6: tmp8s=isnan(GX->f[i]) || isnan(EX->f[i]) || isgreater(GX->f[i], EX->f[i]); break;
case 7: tmp8s=!isnan(GX->f[i]) && !isnan(EX->f[i]); break;
}
GX->ud[i]=(tmp8s)?0xffffffff:0;
}
break;
case 0xC6: /* SHUFPS Gx, Ex, Ib */
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
for(int i=0; i<2; ++i) {
eax1.ud[i] = GX->ud[(tmp8u>>(i*2))&3];
}
for(int i=2; i<4; ++i) {
eax1.ud[i] = EX->ud[(tmp8u>>(i*2))&3];
}
GX->q[0] = eax1.q[0];
GX->q[1] = eax1.q[1];
break;
case 0xC7: /* CMPXCHG8B Eq */
CHECK_FLAGS(emu);
nextop = F8;
GETED(0);
if(rex.w) {
tmp64u = ED->q[0];
tmp64u2= ED->q[1];
if(R_RAX == tmp64u && R_RDX == tmp64u2) {
SET_FLAG(F_ZF);
ED->q[0] = R_EBX;
ED->q[1] = R_ECX;
} else {
CLEAR_FLAG(F_ZF);
R_RAX = tmp64u;
R_RDX = tmp64u2;
}
} else {
tmp32u = ED->dword[0];
tmp32u2= ED->dword[1];
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
SET_FLAG(F_ZF);
ED->dword[0] = R_EBX;
ED->dword[1] = R_ECX;
} else {
CLEAR_FLAG(F_ZF);
R_RAX = tmp32u;
R_RDX = tmp32u2;
}
}
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF: /* BSWAP reg */
tmp8u = (opcode&7)+(rex.b<<3);
if(rex.w)
emu->regs[tmp8u].q[0] = __builtin_bswap64(emu->regs[tmp8u].q[0]);
else
emu->regs[tmp8u].q[0] = __builtin_bswap32(emu->regs[tmp8u].dword[0]);
break;
case 0xD1: /* PSRLW Gm,Em */
nextop = F8;
+61 -4
View File
@@ -19,10 +19,6 @@
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
//#include "signals.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
#include "modrm.h"
@@ -33,6 +29,9 @@ int Run64(x64emu_t *emu, rex_t rex)
uint8_t tmp8u;
int16_t tmp16s;
uint16_t tmp16u;
int32_t tmp32s;
uint32_t tmp32u;
uint64_t tmp64u;
reg64_t *oped, *opgd;
uintptr_t tlsdata = GetFSBaseEmu(emu);
@@ -46,6 +45,64 @@ int Run64(x64emu_t *emu, rex_t rex)
switch(opcode) {
case 0x33: /* XOR Gd,Ed */
nextop = F8;
GETED_OFFS(0, tlsdata);
GETGD;
if(rex.w)
GD->q[0] = xor64(emu, GD->q[0], ED->q[0]);
else
GD->q[0] = xor32(emu, GD->dword[0], ED->dword[0]);
break;
case 0x81: /* GRP Ed,Id */
case 0x83: /* GRP Ed,Ib */
nextop = F8;
GETED_OFFS((opcode==0x81)?4:1, tlsdata);
if(opcode==0x81) {
tmp32s = F32S;
} else {
tmp32s = F8S;
}
if(rex.w) {
tmp64u = (uint64_t)tmp32s;
switch((nextop>>3)&7) {
case 0: ED->q[0] = add64(emu, ED->q[0], tmp64u); break;
case 1: ED->q[0] = or64(emu, ED->q[0], tmp64u); break;
case 2: ED->q[0] = adc64(emu, ED->q[0], tmp64u); break;
case 3: ED->q[0] = sbb64(emu, ED->q[0], tmp64u); break;
case 4: ED->q[0] = and64(emu, ED->q[0], tmp64u); break;
case 5: ED->q[0] = sub64(emu, ED->q[0], tmp64u); break;
case 6: ED->q[0] = xor64(emu, ED->q[0], tmp64u); break;
case 7: cmp64(emu, ED->q[0], tmp64u); break;
}
} else {
tmp32u = (uint32_t)tmp32s;
if(MODREG)
switch((nextop>>3)&7) {
case 0: ED->q[0] = add32(emu, ED->dword[0], tmp32u); break;
case 1: ED->q[0] = or32(emu, ED->dword[0], tmp32u); break;
case 2: ED->q[0] = adc32(emu, ED->dword[0], tmp32u); break;
case 3: ED->q[0] = sbb32(emu, ED->dword[0], tmp32u); break;
case 4: ED->q[0] = and32(emu, ED->dword[0], tmp32u); break;
case 5: ED->q[0] = sub32(emu, ED->dword[0], tmp32u); break;
case 6: ED->q[0] = xor32(emu, ED->dword[0], tmp32u); break;
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
}
else
switch((nextop>>3)&7) {
case 0: ED->dword[0] = add32(emu, ED->dword[0], tmp32u); break;
case 1: ED->dword[0] = or32(emu, ED->dword[0], tmp32u); break;
case 2: ED->dword[0] = adc32(emu, ED->dword[0], tmp32u); break;
case 3: ED->dword[0] = sbb32(emu, ED->dword[0], tmp32u); break;
case 4: ED->dword[0] = and32(emu, ED->dword[0], tmp32u); break;
case 5: ED->dword[0] = sub32(emu, ED->dword[0], tmp32u); break;
case 6: ED->dword[0] = xor32(emu, ED->dword[0], tmp32u); break;
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
}
}
break;
case 0x88: /* MOV Eb,Gb */
nextop = F8;
GETEB_OFFS(0, tlsdata);
+519 -7
View File
@@ -19,23 +19,33 @@
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
//#include "signals.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#include "../dynarec/arm64_lock.h"
#endif
#include "modrm.h"
int Run66(x64emu_t *emu, rex_t rex)
int Run66(x64emu_t *emu, rex_t rex, int rep)
{
uint8_t opcode;
uint8_t nextop;
uint8_t tmp8u;
int8_t tmp8s;
uint8_t tmp8u, tmp8u2;
int16_t tmp16s;
uint16_t tmp16u;
uint16_t tmp16u, tmp16u2;
int64_t tmp64s;
uint64_t tmp64u, tmp64u2, tmp64u3;
reg64_t *oped, *opgd;
opcode = F8;
while((opcode==0x2E) || (opcode==0x66)) // ignoring CS: or multiple 0x66
opcode = F8;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
// REX prefix before the F0 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
@@ -44,10 +54,112 @@ int Run66(x64emu_t *emu, rex_t rex)
}
switch(opcode) {
#define GO(B, OP) \
case B+0: \
nextop = F8; \
GETEB(0); \
GETGB; \
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
break; \
case B+1: \
nextop = F8; \
GETEW(0); \
GETGW; \
if(rex.w) \
EW->q[0] = OP##64(emu, EW->q[0], GW->q[0]); \
else \
EW->word[0] = OP##16(emu, EW->word[0], GW->word[0]); \
break; \
case B+2: \
nextop = F8; \
GETEB(0); \
GETGB; \
GB = OP##8(emu, GB, EB->byte[0]); \
break; \
case B+3: \
nextop = F8; \
GETEW(0); \
GETGW; \
if(rex.w) \
GW->q[0] = OP##64(emu, GW->q[0], EW->q[0]); \
else \
GW->word[0] = OP##16(emu, GW->word[0], EW->word[0]); \
break; \
case B+4: \
R_AL = OP##8(emu, R_AL, F8); \
break; \
case B+5: \
if(rex.w) \
R_RAX = OP##64(emu, R_RAX, F32S64); \
else \
R_AX = OP##16(emu, R_AX, F16); \
break;
GO(0x00, add) /* ADD 0x01 ~> 0x05 */
GO(0x08, or) /* OR 0x09 ~> 0x0D */
GO(0x10, adc) /* ADC 0x11 ~> 0x15 */
GO(0x18, sbb) /* SBB 0x19 ~> 0x1D */
GO(0x20, and) /* AND 0x21 ~> 0x25 */
GO(0x28, sub) /* SUB 0x29 ~> 0x2D */
GO(0x30, xor) /* XOR 0x31 ~> 0x35 */
case 0x0F: /* more opcdes */
return Run660F(emu, rex);
case 0x39:
nextop = F8;
GETEW(0);
GETGW;
if(rex.w)
cmp64(emu, EW->q[0], GW->q[0]);
else
cmp16(emu, EW->word[0], GW->word[0]);
break;
case 0x3B:
nextop = F8;
GETEW(0);
GETGW;
if(rex.w)
cmp64(emu, GW->q[0], EW->dword[0]);
else
cmp16(emu, GW->word[0], EW->word[0]);
break;
case 0x3D:
if(rex.w)
cmp64(emu, R_RAX, F32S64);
else
cmp16(emu, R_AX, F16);
break;
case 0x64: /* FS: */
return Run6664(emu, rex);
case 0x69: /* IMUL Gw,Ew,Iw */
nextop = F8;
GETEW(rex.w?4:2);
GETGW;
if(rex.w) {
tmp64u = F32S64;
GW->q[0] = imul64(emu, EW->q[0], tmp64u);
} else {
tmp16u = F16;
GW->word[0] = imul16(emu, EW->word[0], tmp16u);
}
break;
case 0x6B: /* IMUL Gw,Ew,Ib */
nextop = F8;
GETEW(1);
GETGW;
if(rex.w) {
tmp64s = F8S;
GW->q[0] = imul64(emu, EW->q[0], (uint64_t)tmp64s);
} else {
tmp16s = F8S;
GW->word[0] = imul16(emu, EW->word[0], (uint16_t)tmp16s);
}
break;
case 0x81: /* GRP3 Ew,Iw */
case 0x83: /* GRP3 Ew,Ib */
nextop = F8;
@@ -71,6 +183,28 @@ int Run66(x64emu_t *emu, rex_t rex)
}
break;
case 0x85: /* TEST Ew,Gw */
nextop = F8;
GETEW(0);
GETGW;
test16(emu, EW->word[0], GW->word[0]);
break;
case 0x87: /* XCHG Ew,Gw */
nextop = F8;
GETEW(0);
GETGW;
if(rex.w) {
tmp64u = GW->q[0];
GW->q[0] = EW->q[0];
EW->q[0] = tmp64u;
} else {
tmp16u = GW->word[0];
GW->word[0] = EW->word[0];
EW->word[0] = tmp16u;
}
break;
case 0x89: /* MOV Ew,Gw */
nextop = F8;
GETEW(0);
@@ -81,6 +215,241 @@ int Run66(x64emu_t *emu, rex_t rex)
case 0x90: /* NOP */
break;
case 0x98: /* CBW */
emu->regs[_AX].sword[0] = emu->regs[_AX].sbyte[0];
break;
case 0x99: /* CWD */
R_DX=((R_AX & 0x8000)?0xFFFF:0x0000);
break;
case 0xA5: /* (REP) MOVSW */
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
tmp64u = (rep)?R_RCX:1L;
if(rex.w) {
tmp8s *= 8;
while(tmp64u) {
--tmp64u;
*(uint64_t*)R_RDI = *(uint64_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
}
} else {
tmp8s *= 2;
while(tmp64u) {
--tmp64u;
*(uint16_t*)R_RDI = *(uint16_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
}
}
if(rep)
R_RCX = tmp64u;
break;
case 0xA7: /* (REPZ/REPNE) CMPSW */
if(rex.w)
tmp8s = ACCESS_FLAG(F_DF)?-8:+8;
else
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
switch(rep) {
case 1:
tmp64u = R_RCX;
if(rex.w) {
while(tmp64u) {
--tmp64u;
tmp64u3 = *(uint64_t*)R_RDI;
tmp64u2 = *(uint64_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
if(tmp64u3==tmp64u2)
break;
}
if(R_RCX) cmp64(emu, tmp64u2, tmp64u3);
} else {
while(tmp64u) {
--tmp64u;
tmp16u = *(uint16_t*)R_RDI;
tmp16u2 = *(uint16_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
if(tmp16u==tmp16u2)
break;
}
if(R_RCX) cmp16(emu, tmp16u2, tmp16u);
}
R_RCX = tmp64u;
break;
case 2:
tmp64u = R_RCX;
if(rex.w) {
while(tmp64u) {
--tmp64u;
tmp64u3 = *(uint64_t*)R_RDI;
tmp64u2 = *(uint64_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
if(tmp64u3!=tmp64u2)
break;
}
if(R_RCX) cmp64(emu, tmp64u2, tmp64u3);
} else {
while(tmp64u) {
--tmp64u;
tmp16u = *(uint16_t*)R_RDI;
tmp16u2 = *(uint16_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
if(tmp16u!=tmp16u2)
break;
}
if(R_RCX) cmp16(emu, tmp16u2, tmp16u);
}
R_RCX = tmp64u;
break;
default:
if(rex.w) {
tmp8s = ACCESS_FLAG(F_DF)?-8:+8;
tmp64u = *(uint64_t*)R_RDI;
tmp64u2 = *(uint64_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
cmp64(emu, tmp64u2, tmp64u);
} else {
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
tmp16u = *(uint16_t*)R_RDI;
tmp16u2 = *(uint16_t*)R_RSI;
R_RDI += tmp8s;
R_RSI += tmp8s;
cmp16(emu, tmp16u2, tmp16u);
}
}
break;
case 0xA9: /* TEST AX,Iw */
if(rex.w)
test64(emu, R_RAX, F32S64);
else
test16(emu, R_AX, F16);
break;
case 0xAB: /* (REP) STOSW */
if(rex.w)
tmp8s = ACCESS_FLAG(F_DF)?-8:+8;
else
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
tmp64u = (rep)?R_RCX:1L;
if((rex.w))
while(tmp64u) {
*(uint64_t*)R_RDI = R_RAX;
R_RDI += tmp8s;
--tmp64u;
}
else
while(tmp64u) {
*(uint16_t*)R_RDI = R_AX;
R_RDI += tmp8s;
--tmp64u;
}
if(rep)
R_RCX = tmp64u;
break;
case 0xAD: /* (REP) LODSW */
if(rex.w)
tmp8s = ACCESS_FLAG(F_DF)?-8:+8;
else
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
tmp64u = (rep)?R_RCX:1L;
if((rex.w))
while(tmp64u) {
R_RAX = *(uint64_t*)R_RSI;
R_RSI += tmp8s;
--tmp64u;
}
else
while(tmp64u) {
R_AX = *(uint16_t*)R_RSI;
R_RSI += tmp8s;
--tmp64u;
}
if(rep)
R_RCX = tmp64u;
break;
case 0xAF: /* (REPZ/REPNE) SCASD */
if(rex.w)
tmp8s = ACCESS_FLAG(F_DF)?-8:+8;
else
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
switch(rep) {
case 1:
tmp64u = R_RCX;
if(rex.w) {
while(tmp64u) {
--tmp64u;
tmp64u = *(uint64_t*)R_RDI;
R_RDI += tmp8s;
if(R_RAX==tmp64u)
break;
}
if(R_RCX) cmp64(emu, R_RAX, tmp64u);
} else {
while(tmp64u) {
--tmp64u;
tmp16u = *(uint16_t*)R_RDI;
R_RDI += tmp8s;
if(R_AX==tmp16u)
break;
}
if(R_RCX) cmp16(emu, R_AX, tmp16u);
}
R_RCX = tmp64u;
break;
case 2:
tmp64u = R_RCX;
if(rex.w) {
while(tmp64u) {
--tmp64u;
tmp64u = *(uint64_t*)R_RDI;
R_RDI += tmp8s;
if(R_RAX!=tmp64u)
break;
}
if(R_RCX) cmp64(emu, R_RAX, tmp64u);
} else {
while(tmp64u) {
--tmp64u;
tmp16u = *(uint16_t*)R_RDI;
R_RDI += tmp8s;
if(R_AX!=tmp16u)
break;
}
if(R_RCX) cmp16(emu, R_AX, tmp16u);
}
R_RCX = tmp64u;
break;
default:
if(rex.w)
cmp64(emu, R_RAX, *(uint64_t*)R_RDI);
else
cmp16(emu, R_AX, *(uint16_t*)R_RDI);
R_RDI += tmp8s;
}
break;
case 0xB8: /* MOV AX,Iw */
case 0xB9: /* MOV CX,Iw */
case 0xBA: /* MOV DX,Iw */
case 0xBB: /* MOV BX,Iw */
case 0xBC: /* ... */
case 0xBD:
case 0xBE:
case 0xBF:
if(rex.w)
emu->regs[(opcode&7)+(rex.b<<3)].q[0] = F64;
else
emu->regs[(opcode&7)+(rex.b<<3)].word[0] = F16;
break;
case 0xC1: /* GRP2 Ew,Ib */
nextop = F8;
GETEW(1);
@@ -102,9 +471,152 @@ int Run66(x64emu_t *emu, rex_t rex)
GETEW(2);
EW->word[0] = F16;
break;
case 0xC8: /* ENTER Iw,Ib */
tmp16u = F16;
tmp8u = (F8) & 0x1f;
tmp64u = R_RBP;
Push16(emu, R_BP);
R_RBP = R_RSP;
if (tmp8u) {
for (tmp8u2 = 1; tmp8u2 < tmp8u; tmp8u2++) {
tmp64u -= 2;
Push16(emu, *((uint16_t*)tmp64u));
}
Push16(emu, R_BP);
}
R_RSP -= tmp16u;
break;
case 0xC9: /* LEAVE */
R_RSP = R_RBP;
R_BP = Pop16(emu);
break;
default:
return 1;
case 0xD1: /* GRP2 Ew,1 */
case 0xD3: /* GRP2 Ew,CL */
nextop = F8;
GETEW(0);
tmp8u=(opcode==0xD3)?R_CL:1;
if(rex.w) {
switch((nextop>>3)&7) {
case 0: EW->q[0] = rol64(emu, EW->q[0], tmp8u); break;
case 1: EW->q[0] = ror64(emu, EW->q[0], tmp8u); break;
case 2: EW->q[0] = rcl64(emu, EW->q[0], tmp8u); break;
case 3: EW->q[0] = rcr64(emu, EW->q[0], tmp8u); break;
case 4:
case 6: EW->q[0] = shl64(emu, EW->q[0], tmp8u); break;
case 5: EW->q[0] = shr64(emu, EW->q[0], tmp8u); break;
case 7: EW->q[0] = sar64(emu, EW->q[0], tmp8u); break;
}
} else {
switch((nextop>>3)&7) {
case 0: EW->word[0] = rol16(emu, EW->word[0], tmp8u); break;
case 1: EW->word[0] = ror16(emu, EW->word[0], tmp8u); break;
case 2: EW->word[0] = rcl16(emu, EW->word[0], tmp8u); break;
case 3: EW->word[0] = rcr16(emu, EW->word[0], tmp8u); break;
case 4:
case 6: EW->word[0] = shl16(emu, EW->word[0], tmp8u); break;
case 5: EW->word[0] = shr16(emu, EW->word[0], tmp8u); break;
case 7: EW->word[0] = sar16(emu, EW->word[0], tmp8u); break;
}
}
break;
case 0xD9: /* x87 opcdes */
return Run66D9(emu, rex);
case 0xDD: /* x87 opcdes */
return Run66DD(emu, rex);
case 0xF7: /* GRP3 Ew(,Iw) */
nextop = F8;
tmp8u = (nextop>>3)&7;
if(rex.w) {
GETED((tmp8u<2)?4:0);
switch(tmp8u) {
case 0:
case 1: /* TEST Ed,Id */
tmp64u = F32S64;
test64(emu, ED->q[0], tmp64u);
break;
case 2: /* NOT Ed */
ED->q[0] = not64(emu, ED->q[0]);
break;
case 3: /* NEG Ed */
ED->q[0] = neg64(emu, ED->q[0]);
break;
case 4: /* MUL RAX,Ed */
mul64_rax(emu, ED->q[0]);
break;
case 5: /* IMUL RAX,Ed */
imul64_rax(emu, ED->q[0]);
break;
case 6: /* DIV Ed */
div64(emu, ED->q[0]);
break;
case 7: /* IDIV Ed */
idiv64(emu, ED->q[0]);
break;
}
} else {
switch(tmp8u) {
case 0:
case 1: /* TEST Ew,Iw */
GETEW(2);
test16(emu, EW->word[0], F16);
break;
case 2: /* NOT Ew */
GETEW(0);
EW->word[0] = not16(emu, EW->word[0]);
break;
case 3: /* NEG Ew */
GETEW(0);
EW->word[0] = neg16(emu, EW->word[0]);
break;
case 4: /* MUL AX,Ew */
GETEW(0);
mul16(emu, EW->word[0]);
break;
case 5: /* IMUL AX,Ew */
GETEW(0);
imul16_eax(emu, EW->word[0]);
break;
case 6: /* DIV Ew */
GETEW(0);
div16(emu, EW->word[0]);
break;
case 7: /* IDIV Ew */
GETEW(0);
idiv16(emu, EW->word[0]);
break;
}
}
break;
case 0xFF: /* GRP 5 Ew */
nextop = F8;
GETEW(0);
GETGW;
switch((nextop>>3)&7) {
case 0: /* INC Ed */
EW->word[0] = inc16(emu, EW->word[0]);
break;
case 1: /* DEC Ed */
EW->word[0] = dec16(emu, EW->word[0]);
break;
/*case 6:
Push16(emu, EW->word[0]);
break;*/
default:
R_RIP = emu->old_ip;
printf_log(LOG_NONE, "Illegal Opcode %p: 66 %02X %02X %02X %02X %02X %02X\n",(void*)R_RIP, opcode, nextop, PK(2), PK(3), PK(4), PK(5));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
return 0;
}
break;
default:
return 1;
}
return 0;
}
+1126 -6
View File
File diff suppressed because it is too large. Load diff
+56
View File
@@ -0,0 +1,56 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64stack.h"
#include "x64emu.h"
#include "x64run.h"
#include "x64emu_private.h"
#include "x64run_private.h"
#include "x64primop.h"
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
#include "modrm.h"
int Run6664(x64emu_t *emu, rex_t rex)
{
uint8_t opcode;
uint8_t nextop;
reg64_t *oped, *opgd;
uintptr_t tlsdata = GetFSBaseEmu(emu);
opcode = F8;
// REX prefix before the F0 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
switch(opcode) {
case 0x8B: /* MOV Gd,Ed */
nextop = F8;
GETEW_OFFS(0, tlsdata);
GETGW;
if(rex.w)
GW->q[0] = EW->q[0];
else
GW->word[0] = EW->word[0];
break;
default:
return 1;
}
return 0;
}
+94
View File
@@ -0,0 +1,94 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64stack.h"
#include "x64emu.h"
#include "x64run.h"
#include "x64emu_private.h"
#include "x64run_private.h"
#include "x64primop.h"
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
#include "modrm.h"
int Run66D9(x64emu_t *emu, rex_t rex)
{
uint8_t nextop;
reg64_t *oped;
nextop = F8;
switch (nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
case 0xD0:
case 0xE0:
case 0xE5:
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xFC:
case 0xE1:
case 0xE4:
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFD:
case 0xFE:
case 0xFF:
return 1;
default:
switch((nextop>>3)&7) {
case 4: /* FLDENV m */
// warning, incomplete
GETEW(0);
fpu_loadenv(emu, (char*)ED, 1);
break;
case 6: /* FNSTENV m */
// warning, incomplete
GETEW(0);
fpu_savenv(emu, (char*)ED, 1);
break;
default:
return 1;
}
}
return 0;
}
+112
View File
@@ -0,0 +1,112 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64stack.h"
#include "x64emu.h"
#include "x64run.h"
#include "x64emu_private.h"
#include "x64run_private.h"
#include "x64primop.h"
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
#include "modrm.h"
int Run66DD(x64emu_t *emu, rex_t rex)
{
uint8_t nextop;
reg64_t *oped;
nextop = F8;
switch (nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
case 0xD0:
case 0xE0:
case 0xE5:
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xFC:
case 0xE1:
case 0xE4:
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFD:
case 0xFE:
case 0xFF:
return 1;
default:
switch((nextop>>3)&7) {
case 4: /* FRSTOR m94byte */
GETEW(0);
fpu_loadenv(emu, (char*)ED, 1);
// get the STx
{
char* p =(char*)ED;
p += 14;
for (int i=0; i<8; ++i) {
LD2D(p, &ST(i).d);
p+=10;
}
}
break;
case 6: /* FNSAVE m94byte */
GETEW(0);
// ENV first...
fpu_savenv(emu, (char*)ED, 1);
// save the STx
{
char* p =(char*)ED;
p += 14;
for (int i=0; i<8; ++i) {
D2LD(&ST(i).d, p);
p+=10;
}
}
reset_fpu(emu);
break;
default:
return 1;
}
}
return 0;
}
+83
View File
@@ -0,0 +1,83 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64stack.h"
#include "x64emu.h"
#include "x64run.h"
#include "x64emu_private.h"
#include "x64run_private.h"
#include "x64primop.h"
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
#include "modrm.h"
int Run67(x64emu_t *emu, rex_t rex)
{
uint8_t opcode;
uint8_t nextop;
int8_t tmp8s;
reg64_t *oped, *opgd;
opcode = F8;
// REX prefix before the F0 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
switch(opcode) {
case 0x8D: /* LEA Gd,M */
nextop = F8;
GETED32(0);
GETGD;
if(rex.w)
GD->q[0] = (uint64_t)ED;
else
GD->q[0] = (uint32_t)(uintptr_t)ED;
break;
case 0xE0: /* LOOPNZ */
CHECK_FLAGS(emu);
tmp8s = F8S;
--R_ECX; // don't update flags
if(R_ECX && !ACCESS_FLAG(F_ZF))
R_RIP += tmp8s;
break;
case 0xE1: /* LOOPZ */
CHECK_FLAGS(emu);
tmp8s = F8S;
--R_ECX; // don't update flags
if(R_ECX && ACCESS_FLAG(F_ZF))
R_RIP += tmp8s;
break;
case 0xE2: /* LOOP */
tmp8s = F8S;
--R_ECX; // don't update flags
if(R_ECX)
R_RIP += tmp8s;
break;
case 0xE3: /* JECXZ Ib */
tmp8s = F8S;
if(!R_ECX)
R_RIP += tmp8s;
break;
default:
return 1;
}
return 0;
}
+391 -325
View File
File diff suppressed because it is too large. Load diff
+10 -2
View File
@@ -75,10 +75,12 @@ static inline void Push(x64emu_t *emu, uint64_t v)
reg64_t* GetECommon(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta);
reg64_t* GetECommonO(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta, uintptr_t offset);
reg64_t* GetECommon32O(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta, uintptr_t offset);
reg64_t* GetEb(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
reg64_t* GetEbO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
reg64_t* GetEd(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
reg64_t* GetEdO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
reg64_t* GetEd32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
#define GetEw GetEd
reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v);
reg64_t* GetEw16off(x64emu_t *emu, rex_t rex, uint8_t v, uintptr_t offset);
@@ -97,11 +99,17 @@ void UpdateFlags(x64emu_t *emu);
int Run0F(x64emu_t *emu, rex_t rex);
int Run64(x64emu_t *emu, rex_t rex);
int Run66(x64emu_t *emu, rex_t rex);
int Run66(x64emu_t *emu, rex_t rex, int rep);
int Run660F(x64emu_t *emu, rex_t rex);
//int Run67(x64emu_t *emu, rex_t rex);
int Run6664(x64emu_t *emu, rex_t rex);
int Run66D9(x64emu_t *emu, rex_t rex);
int Run66DD(x64emu_t *emu, rex_t rex);
int Run67(x64emu_t *emu, rex_t rex);
int RunD8(x64emu_t *emu, rex_t rex);
int RunD9(x64emu_t *emu, rex_t rex);
int RunDA(x64emu_t *emu, rex_t rex);
int RunDB(x64emu_t *emu, rex_t rex);
int RunDD(x64emu_t *emu, rex_t rex);
int RunDF(x64emu_t *emu, rex_t rex);
int RunF0(x64emu_t *emu, rex_t rex);
int RunF20F(x64emu_t *emu, rex_t rex);
+195
View File
@@ -0,0 +1,195 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64stack.h"
#include "x64emu.h"
#include "x64run.h"
#include "x64emu_private.h"
#include "x64run_private.h"
#include "x64primop.h"
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
#include "modrm.h"
int RunD8(x64emu_t *emu, rex_t rex)
{
uint8_t nextop;
float f;
reg64_t *oped;
nextop = F8;
switch (nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7: /* FADD */
ST0.d += ST(nextop&7).d;
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF: /* FMUL */
ST0.d *= ST(nextop&7).d;
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7: /* FCOM */
fpu_fcom(emu, ST(nextop&7).d);
break;
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF: /* FCOMP */
fpu_fcom(emu, ST(nextop&7).d);
fpu_do_pop(emu);
break;
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7: /* FSUB */
ST0.d -= ST(nextop&7).d;
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF: /* FSUBR */
ST0.d = ST(nextop&7).d - ST0.d;
break;
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7: /* FDIV */
ST0.d /= ST(nextop&7).d;
break;
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF: /* FDIVR */
ST0.d = ST(nextop&7).d / ST0.d;
break;
default:
switch((nextop>>3)&7) {
case 0: /* FADD ST0, float */
GETED(0);
if(!(((uintptr_t)ED)&3))
ST0.d += *(float*)ED;
else {
memcpy(&f, ED, sizeof(float));
ST0.d += f;
}
break;
case 1: /* FMUL ST0, float */
GETED(0);
if(!(((uintptr_t)ED)&3))
ST0.d *= *(float*)ED;
else {
memcpy(&f, ED, sizeof(float));
ST0.d *= f;
}
break;
case 2: /* FCOM ST0, float */
GETED(0);
if(!(((uintptr_t)ED)&3))
fpu_fcom(emu, *(float*)ED);
else {
memcpy(&f, ED, sizeof(float));
fpu_fcom(emu, f);
}
break;
case 3: /* FCOMP */
GETED(0);
if(!(((uintptr_t)ED)&3))
fpu_fcom(emu, *(float*)ED);
else {
memcpy(&f, ED, sizeof(float));
fpu_fcom(emu, f);
}
fpu_do_pop(emu);
break;
case 4: /* FSUB ST0, float */
GETED(0);
if(!(((uintptr_t)ED)&3))
ST0.d -= *(float*)ED;
else {
memcpy(&f, ED, sizeof(float));
ST0.d -= f;
}
break;
case 5: /* FSUBR ST0, float */
GETED(0);
if(!(((uintptr_t)ED)&3))
ST0.d = *(float*)ED - ST0.d;
else {
memcpy(&f, ED, sizeof(float));
ST0.d = f - ST0.d;
}
break;
case 6: /* FDIV ST0, float */
GETED(0);
if(!(((uintptr_t)ED)&3))
ST0.d /= *(float*)ED;
else {
memcpy(&f, ED, sizeof(float));
ST0.d /= f;
}
break;
case 7: /* FDIVR ST0, float */
GETED(0);
if(!(((uintptr_t)ED)&3))
ST0.d = *(float*)ED / ST0.d;
else {
memcpy(&f, ED, sizeof(float));
ST0.d = f / ST0.d;
}
break;
default:
return 1;
}
}
return 0;
}
+1 -8
View File
@@ -18,12 +18,7 @@
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
//#include "my_cpuid.h"
#include "bridge.h"
//#include "signals.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
#include "modrm.h"
@@ -267,16 +262,14 @@ int RunD9(x64emu_t *emu, rex_t rex)
// do something with cw?
emu->round = (fpu_round_t)((emu->cw >> 10) & 3);
break;
#if 0
case 6: /* FNSTENV m */
// warning, incomplete
GETED;
GETED(0);
fpu_savenv(emu, (char*)ED, 0);
// intruction pointer: 48bits
// data (operand) pointer: 48bits
// last opcode: 11bits save: 16bits restaured (1st and 2nd opcode only)
break;
#endif
case 7: /* FNSTCW Ew */
GETEW(0);
EW->word[0] = emu->cw;
+136
View File
@@ -0,0 +1,136 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64stack.h"
#include "x64emu.h"
#include "x64run.h"
#include "x64emu_private.h"
#include "x64run_private.h"
#include "x64primop.h"
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
#include "modrm.h"
int RunDA(x64emu_t *emu, rex_t rex)
{
uint8_t nextop;
reg64_t *oped;
nextop = F8;
switch (nextop) {
case 0xC0: /* FCMOVB ST(0), ST(i) */
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
CHECK_FLAGS(emu);
if(ACCESS_FLAG(F_CF))
ST0.q = ST(nextop&7).q;
break;
case 0xC8: /* FCMOVE ST(0), ST(i) */
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
CHECK_FLAGS(emu);
if(ACCESS_FLAG(F_ZF))
ST0.q = ST(nextop&7).q;
break;
case 0xD0: /* FCMOVBE ST(0), ST(i) */
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
CHECK_FLAGS(emu);
if(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))
ST0.q = ST(nextop&7).q;
break;
case 0xD8: /* FCMOVU ST(0), ST(i) */
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
CHECK_FLAGS(emu);
if(ACCESS_FLAG(F_PF))
ST0.q = ST(nextop&7).q;
break;
case 0xE9: /* FUCOMPP */
fpu_fcom(emu, ST1.d); // bad, should handle QNaN and IA interrupt
fpu_do_pop(emu);
fpu_do_pop(emu);
break;
case 0xE4:
case 0xF0:
case 0xF1:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF8:
case 0xF9:
case 0xFD:
return 1;
default:
switch((nextop>>3)&7) {
case 0: /* FIADD ST0, Ed int */
GETED(0);
ST0.d += ED->sdword[0];
break;
case 1: /* FIMUL ST0, Ed int */
GETED(0);
ST0.d *= ED->sdword[0];
break;
case 2: /* FICOM ST0, Ed int */
GETED(0);
fpu_fcom(emu, ED->sdword[0]);
break;
case 3: /* FICOMP ST0, Ed int */
GETED(0);
fpu_fcom(emu, ED->sdword[0]);
fpu_do_pop(emu);
break;
case 4: /* FISUB ST0, Ed int */
GETED(0);
ST0.d -= ED->sdword[0];
break;
case 5: /* FISUBR ST0, Ed int */
GETED(0);
ST0.d = (double)ED->sdword[0] - ST0.d;
break;
case 6: /* FIDIV ST0, Ed int */
GETED(0);
ST0.d /= ED->sdword[0];
break;
case 7: /* FIDIVR ST0, Ed int */
GETED(0);
ST0.d = (double)ED->sdword[0] / ST0.d;
break;
}
}
return 0;
}
-5
View File
@@ -18,12 +18,7 @@
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
//#include "my_cpuid.h"
#include "bridge.h"
//#include "signals.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
#include "modrm.h"
+189
View File
@@ -0,0 +1,189 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64stack.h"
#include "x64emu.h"
#include "x64run.h"
#include "x64emu_private.h"
#include "x64run_private.h"
#include "x64primop.h"
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
#include "modrm.h"
int RunDD(x64emu_t *emu, rex_t rex)
{
uint8_t nextop;
reg64_t *oped;
nextop = F8;
switch (nextop) {
case 0xC0: /* FFREE STx */
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
fpu_do_free(emu, nextop-0xC0);
break;
case 0xD0: /* FST ST0, STx */
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
ST(nextop&7).q = ST0.q;
break;
case 0xD8: /* FSTP ST0, STx */
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
ST(nextop&7).q = ST0.q;
fpu_do_pop(emu);
break;
case 0xE0: /* FUCOM ST0, STx */
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
fpu_fcom(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
break;
case 0xE8: /* FUCOMP ST0, STx */
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
fpu_fcom(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
fpu_do_pop(emu);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
return 1;
default:
switch((nextop>>3)&7) {
case 0: /* FLD double */
GETED(0);
fpu_do_push(emu);
if(!(((uintptr_t)ED)&7))
ST0.d = *(double*)ED;
else {
memcpy(&ST0.d, ED, sizeof(double));
}
break;
case 1: /* FISTTP ED qword */
GETED(0);
if(!(((uintptr_t)ED)&7))
*(int64_t*)ED = ST0.d;
else {
int64_t i64 = ST0.d;
memcpy(ED, &i64, sizeof(int64_t));
}
fpu_do_pop(emu);
break;
case 2: /* FST double */
GETED(0);
if(!(((uintptr_t)ED)&7))
*(double*)ED = ST0.d;
else {
memcpy(ED, &ST0.d, sizeof(double));
}
break;
case 3: /* FSTP double */
GETED(0);
if(!(((uintptr_t)ED)&7))
*(double*)ED = ST0.d;
else {
memcpy(ED, &ST0.d, sizeof(double));
}
fpu_do_pop(emu);
break;
case 4: /* FRSTOR m108byte */
GETED(0);
fpu_loadenv(emu, (char*)ED, 0);
// get the STx
{
char* p =(char*)ED;
p += 28;
for (int i=0; i<8; ++i) {
LD2D(p, &ST(i).d);
p+=10;
}
}
break;
case 6: /* FNSAVE m108byte */
GETED(0);
// ENV first...
// warning, incomplete
fpu_savenv(emu, (char*)ED, 0);
// save the STx
{
char* p =(char*)ED;
p += 28;
for (int i=0; i<8; ++i) {
D2LD(&ST(i).d, p);
p+=10;
}
}
reset_fpu(emu);
break;
case 7: /* FNSTSW m2byte */
GETED(0);
emu->sw.f.F87_TOP = emu->top&7;
*(uint16_t*)ED = emu->sw.x16;
break;
default:
return 1;
}
}
return 0;
}
+10 -30
View File
@@ -18,12 +18,7 @@
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
//#include "my_cpuid.h"
#include "bridge.h"
//#include "signals.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
#include "modrm.h"
@@ -31,6 +26,7 @@ int RunDF(x64emu_t *emu, rex_t rex)
{
uint8_t nextop;
int16_t tmp16s;
int64_t tmp64s;
reg64_t *oped;
nextop = F8;
@@ -146,7 +142,6 @@ int RunDF(x64emu_t *emu, rex_t rex)
EW->sword[0] = fpu_round(emu, ST0.d);
fpu_do_pop(emu);
break;
#if 0
case 4: /* FBLD ST0, tbytes */
GETED(0);
fpu_do_push(emu);
@@ -154,11 +149,11 @@ int RunDF(x64emu_t *emu, rex_t rex)
break;
case 5: /* FILD ST0, Gq */
GETED(0);
tmp64s = *(int64_t*)ED;
tmp64s = ED->sq[0];
fpu_do_push(emu);
ST0.d = tmp64s;
STll(0).ll = tmp64s;
STll(0).ref = ST0.ll;
STll(0).ref = ST0.q;
break;
case 6: /* FBSTP tbytes, ST0 */
GETED(0);
@@ -167,31 +162,16 @@ int RunDF(x64emu_t *emu, rex_t rex)
break;
case 7: /* FISTP i64 */
GETED(0);
if((uintptr_t)ED & 0x7) {
// un-aligned!
if(STll(0).ref==ST(0).ll)
memcpy(ED, &STll(0).ll, sizeof(int64_t));
else {
int64_t i64;
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
i64 = 0x8000000000000000LL;
else
i64 = fpu_round(emu, ST0.d);
memcpy(ED, &i64, sizeof(int64_t));
}
} else {
if(STll(0).ref==ST(0).ll)
*(int64_t*)ED = STll(0).ll;
else {
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
*(int64_t*)ED = 0x8000000000000000LL;
else
*(int64_t*)ED = fpu_round(emu, ST0.d);
}
if(STll(0).ref==ST(0).q)
ED->sq[0] = STll(0).ll;
else {
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
ED->sq[0] = 0x8000000000000000LL;
else
ED->sq[0] = fpu_round(emu, ST0.d);
}
fpu_do_pop(emu);
break;
#endif
default:
return 1;
}
+178 -38
View File
@@ -20,9 +20,8 @@
#include "box64context.h"
#include "my_cpuid.h"
#include "bridge.h"
//#include "signals.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#include "../dynarec/arm64_lock.h"
#endif
#include "modrm.h"
@@ -31,9 +30,11 @@ int RunF0(x64emu_t *emu, rex_t rex)
{
uint8_t opcode;
uint8_t nextop;
uint32_t tmp32u;
uint8_t tmp8u;
int32_t tmp32s;
uint32_t tmp32u, tmp32u2;
int64_t tmp64s;
uint64_t tmp64u;
uint64_t tmp64u, tmp64u2;
reg64_t *oped, *opgd;
opcode = F8;
@@ -45,7 +46,124 @@ int RunF0(x64emu_t *emu, rex_t rex)
}
switch(opcode) {
#ifdef DYNAREC
#define GO(B, OP) \
case B+0: \
nextop = F8; \
GETEB(0); \
GETGB; \
do { \
tmp8u = arm64_lock_read_b(EB); \
tmp8u = OP##8(emu, tmp8u, GB); \
} while (arm64_lock_write_b(EB, tmp8u)); \
break; \
case B+1: \
nextop = F8; \
GETED(0); \
GETGD; \
if(rex.w) { \
do { \
tmp64u = arm64_lock_read_dd(ED); \
tmp64u = OP##64(emu, tmp64u, GD->q[0]); \
} while (arm64_lock_write_dd(ED, tmp64u)); \
} else { \
do { \
tmp32u = arm64_lock_read_d(ED); \
tmp32u = OP##32(emu, tmp32u, GD->dword[0]); \
} while (arm64_lock_write_d(ED, tmp32u)); \
if(MODREG) \
ED->dword[1] = 0; \
} \
break; \
case B+2: \
nextop = F8; \
GETEB(0); \
GETGB; \
GB = OP##8(emu, GB, EB->byte[0]); \
break; \
case B+3: \
nextop = F8; \
GETED(0); \
GETGD; \
if(rex.w) \
GD->q[0] = OP##64(emu, GD->q[0], ED->q[0]); \
else \
GD->q[0] = OP##32(emu, GD->dword[0], ED->dword[0]); \
break; \
case B+4: \
R_AL = OP##8(emu, R_AL, F8); \
break; \
case B+5: \
if(rex.w) \
R_RAX = OP##64(emu, R_RAX, F32S64); \
else \
R_RAX = OP##32(emu, R_EAX, F32); \
break;
#else
#define GO(B, OP) \
case B+0: \
nextop = F8; \
GETEB(0); \
GETGB; \
pthread_mutex_lock(&emu->context->mutex_lock); \
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
pthread_mutex_unlock(&emu->context->mutex_lock); \
break; \
case B+1: \
nextop = F8; \
GETED(0); \
GETGD; \
pthread_mutex_lock(&emu->context->mutex_lock); \
if(rex.w) \
ED->q[0] = OP##64(emu, ED->q[0], GD->q[0]); \
else \
if(MODREG) \
ED->q[0] = OP##32(emu, ED->dword[0], GD->dword[0]); \
else \
ED->dword[0] = OP##32(emu, ED->dword[0], GD->dword[0]); \
pthread_mutex_unlock(&emu->context->mutex_lock); \
break; \
case B+2: \
nextop = F8; \
GETEB(0); \
GETGB; \
pthread_mutex_lock(&emu->context->mutex_lock); \
GB = OP##8(emu, GB, EB->byte[0]); \
pthread_mutex_unlock(&emu->context->mutex_lock); \
break; \
case B+3: \
nextop = F8; \
GETED(0); \
GETGD; \
pthread_mutex_lock(&emu->context->mutex_lock); \
if(rex.w) \
GD->q[0] = OP##64(emu, GD->q[0], ED->q[0]); \
else \
GD->q[0] = OP##32(emu, GD->dword[0], ED->dword[0]); \
pthread_mutex_unlock(&emu->context->mutex_lock); \
break; \
case B+4: \
pthread_mutex_lock(&emu->context->mutex_lock); \
R_AL = OP##8(emu, R_AL, F8); \
pthread_mutex_unlock(&emu->context->mutex_lock); \
break; \
case B+5: \
pthread_mutex_lock(&emu->context->mutex_lock); \
if(rex.w) \
R_RAX = OP##64(emu, R_RAX, F32S64); \
else \
R_RAX = OP##32(emu, R_EAX, F32); \
pthread_mutex_unlock(&emu->context->mutex_lock); \
break;
#endif
GO(0x00, add) /* ADD 0x00 -> 0x05 */
GO(0x08, or) /* OR 0x08 -> 0x0D */
GO(0x10, adc) /* ADC 0x10 -> 0x15 */
GO(0x18, sbb) /* SBB 0x18 -> 0x1D */
GO(0x20, and) /* AND 0x20 -> 0x25 */
GO(0x28, sub) /* SUB 0x28 -> 0x2D */
GO(0x30, xor) /* XOR 0x30 -> 0x35 */
#undef GO
case 0x0f:
opcode = F8;
switch (opcode) {
@@ -55,32 +173,28 @@ int RunF0(x64emu_t *emu, rex_t rex)
GETED(0);
GETGD;
#ifdef DYNAREC
if(((uintptr_t)ED)&3) {
if(rex.w)
do {
tmp32u = ED->dword[0] & ~0xff;
tmp32u |= arm_lock_read_b(ED);
cmp32(emu, R_EAX, tmp32u);
tmp64u = arm64_lock_read_dd(ED);
cmp64(emu, R_RAX, tmp64u);
if(ACCESS_FLAG(F_ZF)) {
tmp32s = arm_lock_write_b(ED, GD->dword[0] & 0xff);
if(!tmp32s)
ED->dword[0] = GD.dword[0];
tmp32s = arm64_lock_write_dd(ED, GD->q[0]);
} else {
R_EAX = tmp32u;
R_RAX = tmp64u;
tmp32s = 0;
}
} while(tmp32s);
} else {
else
do {
tmp32u = arm_lock_read_d(ED);
tmp32u = arm64_lock_read_d(ED);
cmp32(emu, R_EAX, tmp32u);
if(ACCESS_FLAG(F_ZF)) {
tmp32s = arm_lock_write_d(ED, GD.dword[0]);
tmp32s = arm64_lock_write_d(ED, GD->dword[0]);
} else {
R_EAX = tmp32u;
R_RAX = tmp32u;
tmp32s = 0;
}
} while(tmp32s);
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(rex.w) {
@@ -107,20 +221,21 @@ int RunF0(x64emu_t *emu, rex_t rex)
GETED(0);
GETGD;
#ifdef DYNAREC
if(((uintptr_t)ED)&3) {
if(rex.w) {
do {
tmp32u = ED->dword[0] & ~0xff;
tmp32u |= arm_lock_read_b(ED);
tmp32u2 = add32(emu, tmp32u, GD.dword[0]);
} while(arm_lock_write_b(ED, tmp32u2&0xff));
ED->dword[0] = tmp32u2;
tmp64u = arm64_lock_read_dd(ED);
tmp64u2 = add64(emu, tmp64u, GD->dword[0]);
} while(arm64_lock_write_dd(ED, tmp64u2));
GD->q[0] = tmp64u;
} else {
do {
tmp32u = arm_lock_read_d(ED);
tmp32u2 = add32(emu, tmp32u, GD.dword[0]);
} while(arm_lock_write_d(ED, tmp32u2));
tmp32u = arm64_lock_read_d(ED);
tmp32u2 = add32(emu, tmp32u, GD->dword[0]);
} while(arm64_lock_write_d(ED, tmp32u2));
GD->q[0] = tmp32u;
if(MODREG)
ED->dword[1] = 0;
}
GD.dword[0] = tmp32u;
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(rex.w) {
@@ -130,7 +245,7 @@ int RunF0(x64emu_t *emu, rex_t rex)
} else {
tmp32u = add32(emu, ED->dword[0], GD->dword[0]);
GD->q[0] = ED->dword[0];
if((nextop&0xC0)==0xC0)
if(MODREG)
ED->q[0] = tmp32u;
else
ED->dword[0] = tmp32u;
@@ -154,15 +269,40 @@ int RunF0(x64emu_t *emu, rex_t rex)
} else
tmp64u = F32S64;
#ifdef DYNAREC
switch((nextop>>3)&7) {
case 0: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, add32(emu, tmp32u2, tmp32u))); break;
case 1: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, or32(emu, tmp32u2, tmp32u))); break;
case 2: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, adc32(emu, tmp32u2, tmp32u))); break;
case 3: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, sbb32(emu, tmp32u2, tmp32u))); break;
case 4: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, and32(emu, tmp32u2, tmp32u))); break;
case 5: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, sub32(emu, tmp32u2, tmp32u))); break;
case 6: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, xor32(emu, tmp32u2, tmp32u))); break;
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
if(rex.w) {
switch((nextop>>3)&7) {
case 0: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = add64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 1: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = or64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 2: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = adc64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 3: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = sbb64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 4: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = and64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 5: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = sub64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 6: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = xor64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 7: cmp64(emu, ED->q[0], tmp64u); break;
}
} else {
if(MODREG)
switch((nextop>>3)&7) {
case 0: ED->q[0] = add32(emu, ED->dword[0], tmp64u); break;
case 1: ED->q[0] = or32(emu, ED->dword[0], tmp64u); break;
case 2: ED->q[0] = adc32(emu, ED->dword[0], tmp64u); break;
case 3: ED->q[0] = sbb32(emu, ED->dword[0], tmp64u); break;
case 4: ED->q[0] = and32(emu, ED->dword[0], tmp64u); break;
case 5: ED->q[0] = sub32(emu, ED->dword[0], tmp64u); break;
case 6: ED->q[0] = xor32(emu, ED->dword[0], tmp64u); break;
case 7: cmp32(emu, ED->dword[0], tmp64u); break;
}
else
switch((nextop>>3)&7) {
case 0: do { tmp32u2 = arm64_lock_read_d(ED); tmp32u2 = add32(emu, tmp32u2, tmp64u);} while(arm64_lock_write_d(ED, tmp32u2)); break;
case 1: do { tmp32u2 = arm64_lock_read_d(ED); tmp32u2 = or32(emu, tmp32u2, tmp64u);} while(arm64_lock_write_d(ED, tmp32u2)); break;
case 2: do { tmp32u2 = arm64_lock_read_d(ED); tmp32u2 = adc32(emu, tmp32u2, tmp64u);} while(arm64_lock_write_d(ED, tmp32u2)); break;
case 3: do { tmp32u2 = arm64_lock_read_d(ED); tmp32u2 = sbb32(emu, tmp32u2, tmp64u);} while(arm64_lock_write_d(ED, tmp32u2)); break;
case 4: do { tmp32u2 = arm64_lock_read_d(ED); tmp32u2 = and32(emu, tmp32u2, tmp64u);} while(arm64_lock_write_d(ED, tmp32u2)); break;
case 5: do { tmp32u2 = arm64_lock_read_d(ED); tmp32u2 = sub32(emu, tmp32u2, tmp64u);} while(arm64_lock_write_d(ED, tmp32u2)); break;
case 6: do { tmp32u2 = arm64_lock_read_d(ED); tmp32u2 = xor32(emu, tmp32u2, tmp64u);} while(arm64_lock_write_d(ED, tmp32u2)); break;
case 7: cmp32(emu, ED->dword[0], tmp64u); break;
}
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
+174 -8
View File
@@ -19,10 +19,6 @@
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
//#include "signals.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
#include "modrm.h"
@@ -30,8 +26,12 @@ int RunF20F(x64emu_t *emu, rex_t rex)
{
uint8_t opcode;
uint8_t nextop;
int8_t tmp8s;
uint8_t tmp8u;
int32_t tmp32s;
reg64_t *oped, *opgd;
sse_regs_t *opex, *opgx;
sse_regs_t *opex, *opgx, eax1;
mmx87_regs_t *opgm;
opcode = F8;
@@ -58,10 +58,11 @@ int RunF20F(x64emu_t *emu, rex_t rex)
nextop = F8;
GETED(0);
GETGX;
if(rex.w)
if(rex.w) {
GX->d[0] = ED->sq[0];
else
} else {
GX->d[0] = ED->sdword[0];
}
break;
case 0x2C: /* CVTTSD2SI Gd, Ex */
@@ -70,23 +71,188 @@ int RunF20F(x64emu_t *emu, rex_t rex)
GETGD;
if(rex.w)
GD->sq[0] = EX->d[0];
else
else {
GD->sdword[0] = EX->d[0];
GD->dword[1] = 0;
}
break;
case 0x2D: /* CVTSD2SI Gd, Ex */
nextop = F8;
GETEX(0);
GETGD;
if(rex.w) {
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GD->q[0] = floor(EX->d[0]+0.5);
break;
case ROUND_Down:
GD->q[0] = floor(EX->d[0]);
break;
case ROUND_Up:
GD->q[0] = ceil(EX->d[0]);
break;
case ROUND_Chop:
GD->q[0] = EX->d[0];
break;
}
} else {
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GD->sdword[0] = floor(EX->d[0]+0.5);
break;
case ROUND_Down:
GD->sdword[0] = floor(EX->d[0]);
break;
case ROUND_Up:
GD->sdword[0] = ceil(EX->d[0]);
break;
case ROUND_Chop:
GD->sdword[0] = EX->d[0];
break;
}
}
break;
case 0x51: /* SQRTSD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->d[0] = sqrt(EX->d[0]);
break;
case 0x58: /* ADDSD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->d[0] += EX->d[0];
break;
case 0x59: /* MULSD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->d[0] *= EX->d[0];
break;
case 0x5A: /* CVTSD2SS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->f[0] = EX->d[0];
break;
case 0x5C: /* SUBSD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->d[0] -= EX->d[0];
break;
case 0x5D: /* MINSD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
if (isnan(GX->d[0]) || isnan(EX->d[0]) || isless(EX->d[0], GX->d[0]))
GX->d[0] = EX->d[0];
break;
case 0x5E: /* DIVSD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->d[0] /= EX->d[0];
break;
case 0x5F: /* MAXSD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
if (isnan(GX->d[0]) || isnan(EX->d[0]) || isgreater(EX->d[0], GX->d[0]))
GX->d[0] = EX->d[0];
break;
case 0x70: /* PSHUFLW Gx, Ex, Ib */
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
if(GX==EX) {
for (int i=0; i<4; ++i)
eax1.uw[i] = EX->uw[(tmp8u>>(i*2))&3];
GX->q[0] = eax1.q[0];
} else {
for (int i=0; i<4; ++i)
GX->uw[i] = EX->uw[(tmp8u>>(i*2))&3];
GX->q[1] = EX->q[1];
}
break;
case 0x7C: /* HADDPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->f[0] += GX->f[1];
GX->f[1] = GX->f[2] + GX->f[3];
if(EX==GX) {
GX->f[2] = GX->f[0];
GX->f[3] = GX->f[1];
} else {
GX->f[2] = EX->f[0] + EX->f[1];
GX->f[3] = EX->f[2] + EX->f[3];
}
break;
GOCOND(0x80
, tmp32s = F32S; CHECK_FLAGS(emu);
, R_RIP += tmp32s;
,
) /* 0x80 -> 0x8F Jxx */
case 0xC2: /* CMPSD Gx, Ex, Ib */
nextop = F8;
GETEX(0);
GETGX;
tmp8u = F8;
tmp8s = 0;
switch(tmp8u&7) {
case 0: tmp8s=(GX->d[0] == EX->d[0]); break;
case 1: tmp8s=isless(GX->d[0], EX->d[0]); break;
case 2: tmp8s=islessequal(GX->d[0], EX->d[0]); break;
case 3: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]); break;
case 4: tmp8s=(GX->d[0] != EX->d[0]); break;
case 5: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]) || isgreaterequal(GX->d[0], EX->d[0]); break;
case 6: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]) || isgreater(GX->d[0], EX->d[0]); break;
case 7: tmp8s=!isnan(GX->d[0]) && !isnan(EX->d[0]); break;
}
GX->q[0]=(tmp8s)?0xffffffffffffffffLL:0LL;
break;
case 0xD6: /* MOVDQ2Q Gm, Ex */
nextop = F8;
GETEX(0);
GETGM;
GM->q = EX->q[0];
break;
case 0xE6: /* CVTPD2DQ Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GX->sd[0] = floor(EX->d[0]+0.5);
GX->sd[1] = floor(EX->d[1]+0.5);
break;
case ROUND_Down:
GX->sd[0] = floor(EX->d[0]);
GX->sd[1] = floor(EX->d[1]);
break;
case ROUND_Up:
GX->sd[0] = ceil(EX->d[0]);
GX->sd[1] = ceil(EX->d[1]);
break;
case ROUND_Chop:
GX->sd[0] = EX->d[0];
GX->sd[1] = EX->d[1];
break;
}
GX->q[1] = 0;
break;
default:
return 1;
+184 -7
View File
@@ -18,12 +18,7 @@
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
//#include "my_cpuid.h"
#include "bridge.h"
//#include "signals.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
#include "modrm.h"
@@ -31,9 +26,11 @@ int RunF30F(x64emu_t *emu, rex_t rex)
{
uint8_t opcode;
uint8_t nextop;
int32_t tmp32s;
int8_t tmp8s;
uint8_t tmp8u;
reg64_t *oped, *opgd;
sse_regs_t *opex, *opgx;
sse_regs_t *opex, *opgx, eax1;
mmx87_regs_t *opem;
opcode = F8;
@@ -55,6 +52,21 @@ int RunF30F(x64emu_t *emu, rex_t rex)
GETGX;
EX->ud[0] = GX->ud[0];
break;
case 0x12: /* MOVSLDUP Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->ud[1] = GX->ud[0] = EX->ud[0];
GX->ud[3] = GX->ud[2] = EX->ud[2];
break;
case 0x16: /* MOVSHDUP Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->ud[1] = GX->ud[0] = EX->ud[1];
GX->ud[3] = GX->ud[2] = EX->ud[3];
break;
case 0x2A: /* CVTSI2SS Gx, Ed */
nextop = F8;
@@ -66,6 +78,80 @@ int RunF30F(x64emu_t *emu, rex_t rex)
GX->f[0] = ED->sdword[0];
break;
case 0x2C: /* CVTTSS2SI Gd, Ex */
nextop = F8;
GETEX(0);
GETGD;
if (rex.w)
GD->sq[0] = EX->f[0];
else {
GD->sdword[0] = EX->f[0];
GD->dword[1] = 0;
}
break;
case 0x2D: /* CVTSS2SI Gd, Ex */
nextop = F8;
GETEX(0);
GETGD;
if(rex.w) {
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GD->sq[0] = floorf(EX->f[0]+0.5f);
break;
case ROUND_Down:
GD->sq[0] = floorf(EX->f[0]);
break;
case ROUND_Up:
GD->sq[0] = ceilf(EX->f[0]);
break;
case ROUND_Chop:
GD->sq[0] = EX->f[0];
break;
}
} else {
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GD->sdword[0] = floorf(EX->f[0]+0.5f);
break;
case ROUND_Down:
GD->sdword[0] = floorf(EX->f[0]);
break;
case ROUND_Up:
GD->sdword[0] = ceilf(EX->f[0]);
break;
case ROUND_Chop:
GD->sdword[0] = EX->f[0];
break;
}
GD->dword[1] = 0;
}
break;
case 0x51: /* SQRTSS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->f[0] = sqrtf(EX->f[0]);
break;
case 0x52: /* RSQRTSS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->f[0] = 1.0f/sqrtf(EX->f[0]);
break;
case 0x53: /* RCPSS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->f[0] = 1.0f/EX->f[0];
break;
case 0x58: /* ADDSS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->f[0] += EX->f[0];
break;
case 0x59: /* MULSS Gx, Ex */
nextop = F8;
GETEX(0);
@@ -78,6 +164,41 @@ int RunF30F(x64emu_t *emu, rex_t rex)
GETGX;
GX->d[0] = EX->f[0];
break;
case 0x5B: /* CVTTPS2DQ Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->sd[0] = EX->f[0];
GX->sd[1] = EX->f[1];
GX->sd[2] = EX->f[2];
GX->sd[3] = EX->f[3];
break;
case 0x5C: /* SUBSS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->f[0] -= EX->f[0];
break;
case 0x5D: /* MINSS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
if(isnan(GX->f[0]) || isnan(EX->f[0]) || isless(EX->f[0], GX->f[0]))
GX->f[0] = EX->f[0];
break;
case 0x5E: /* DIVSS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->f[0] /= EX->f[0];
break;
case 0x5F: /* MAXSS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
if (isnan(GX->f[0]) || isnan(EX->f[0]) || isgreater(EX->f[0], GX->f[0]))
GX->f[0] = EX->f[0];
break;
case 0x6F: /* MOVDQU Gx, Ex */
nextop = F8;
@@ -85,6 +206,21 @@ int RunF30F(x64emu_t *emu, rex_t rex)
GETGX;
memcpy(GX, EX, 16); // unaligned...
break;
case 0x70: /* PSHUFHW Gx, Ex, Ib */
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
if(GX==EX) {
for (int i=0; i<4; ++i)
eax1.uw[4+i] = EX->uw[4+((tmp8u>>(i*2))&3)];
GX->q[1] = eax1.q[1];
} else {
for (int i=0; i<4; ++i)
GX->uw[4+i] = EX->uw[4+((tmp8u>>(i*2))&3)];
GX->q[0] = EX->q[0];
}
break;
case 0x7E: /* MOVQ Gx, Ex */
nextop = F8;
@@ -93,6 +229,47 @@ int RunF30F(x64emu_t *emu, rex_t rex)
GX->q[0] = EX->q[0];
GX->q[1] = 0;
break;
case 0x7F: /* MOVDQU Ex, Gx */
nextop = F8;
GETEX(0);
GETGX;
memcpy(EX, GX, 16); // unaligned...
break;
case 0xC2: /* CMPSS Gx, Ex, Ib */
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
tmp8s = 0;
switch(tmp8u&7) {
case 0: tmp8s=(GX->f[0] == EX->f[0]); break;
case 1: tmp8s=isless(GX->f[0], EX->f[0]); break;
case 2: tmp8s=islessequal(GX->f[0], EX->f[0]); break;
case 3: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]); break;
case 4: tmp8s=(GX->f[0] != EX->f[0]); break;
case 5: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]) || isgreaterequal(GX->f[0], EX->f[0]); break;
case 6: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]) || isgreater(GX->f[0], EX->f[0]); break;
case 7: tmp8s=!isnan(GX->f[0]) && !isnan(EX->f[0]); break;
}
GX->ud[0]=(tmp8s)?0xffffffff:0;
break;
case 0xD6: /* MOVQ2DQ Gx, Em */
nextop = F8;
GETEM(0);
GETGX;
GX->q[0] = EM->q;
GX->q[1] = 0;
break;
case 0xE6: /* CVTDQ2PD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->d[1] = EX->sd[1];
GX->d[0] = EX->sd[0];
break;
default:
return 1;
+1
View File
@@ -68,6 +68,7 @@ scwrap_t syscallwrap[] = {
//{ 3, __NR_close, 1 }, // wrapped so SA_RESTART can be handled by libc
{ 5, __NR_fstat, 2},
{ 186, __NR_gettid, 0 },
};
struct mmap_arg_struct {
+6
View File
@@ -102,7 +102,13 @@ const char* DecodeX64Trace(zydis_dec_t *dec, uintptr_t p)
sprintf(tmp, "%02X ", *((unsigned char*)p+i));
strcat(buff, tmp);
}
#if 0
const /*ZydisFormatterToken*/void* token;
dec->ZydisFormatterTokenizeInstruction(&dec->formatter, &dec->instruction, tmp, sizeof(tmp), p, &token);
dec->PrintTokenizedInstruction(token);
#else
dec->ZydisFormatterFormatInstruction(&dec->formatter, &dec->instruction, tmp, sizeof(tmp),p);
#endif
strcat(buff, tmp);
} else {
sprintf(buff, "Decoder failed @%p", (void*)p);
+2
View File
@@ -27,6 +27,8 @@ typedef struct dynablocklist_s dynablocklist_t;
typedef struct mmaplist_s mmaplist_t;
typedef struct kh_dynablocks_s kh_dynablocks_t;
#endif
#define DYNAMAP_SHIFT 16
#define JMPTABL_SHIFT 16
typedef void* (*procaddess_t)(const char* name);
typedef void* (*vkprocaddess_t)(void* instance, const char* name);
+9 -2
View File
@@ -10,9 +10,9 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
bridge_t *NewBridge();
void FreeBridge(bridge_t** bridge);
uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N);
uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name);
uintptr_t CheckBridged(bridge_t* bridge, void* fnc);
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N);
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name);
uintptr_t AddAutomaticBridge(x64emu_t* emu, bridge_t* bridge, wrapper_t w, void* fnc, int N);
void* GetNativeFnc(uintptr_t fnc);
void* GetNativeFncOrFnc(uintptr_t fnc);
@@ -22,4 +22,11 @@ void* getAlternate(void* addr);
void addAlternate(void* addr, void* alt);
void cleanAlternate();
#ifdef HAVE_TRACE
const char* getBridgeName(void* addr);
#endif
void init_bridge_helper();
void fini_bridge_helper();
#endif //__BRIDGE_H_
+25 -25
View File
@@ -6,31 +6,31 @@
typedef struct box64context_s box64context_t;
//void* customMalloc(size_t size);
//void* customCalloc(size_t n, size_t size);
//void* customRealloc(void* p, size_t size);
//void customFree(void* p);
void* customMalloc(size_t size);
void* customCalloc(size_t n, size_t size);
void* customRealloc(void* p, size_t size);
void customFree(void* p);
//#define kcalloc customCalloc
//#define kmalloc customMalloc
//#define krealloc customRealloc
//#define kfree customFree
#define kcalloc customCalloc
#define kmalloc customMalloc
#define krealloc customRealloc
#define kfree customFree
#ifdef DYNAREC
//typedef struct dynablock_s dynablock_t;
//typedef struct dynablocklist_s dynablocklist_t;
//// custom protection flag to mark Page that are Write protected for Dynarec purpose
//uintptr_t AllocDynarecMap(dynablock_t* db, int size);
//void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size);
typedef struct dynablock_s dynablock_t;
typedef struct dynablocklist_s dynablocklist_t;
// custom protection flag to mark Page that are Write protected for Dynarec purpose
uintptr_t AllocDynarecMap(dynablock_t* db, int size);
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size);
//void addDBFromAddressRange(uintptr_t addr, uintptr_t size);
//void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
void addDBFromAddressRange(uintptr_t addr, uintptr_t size);
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
//dynablocklist_t* getDB(uintptr_t idx);
//void addJumpTableIfDefault(void* addr, void* jmp);
//void setJumpTableDefault(void* addr);
//uintptr_t getJumpTable();
//uintptr_t getJumpTableAddress(uintptr_t addr);
dynablocklist_t* getDB(uintptr_t idx);
void addJumpTableIfDefault64(void* addr, void* jmp);
void setJumpTableDefault64(void* addr);
uintptr_t getJumpTable64();
uintptr_t getJumpTableAddress64(uintptr_t addr);
#endif
#define PROT_DYNAREC 0x80
@@ -38,11 +38,11 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
uint32_t getProtection(uintptr_t addr);
#ifdef DYNAREC
//void protectDB(uintptr_t addr, uintptr_t size);
//void protectDBnolock(uintptr_t addr, uintptr_t size);
//void unprotectDB(uintptr_t addr, uintptr_t size);
//void lockDB();
//void unlockDB();
void protectDB(uintptr_t addr, uintptr_t size);
void protectDBnolock(uintptr_t addr, uintptr_t size);
void unprotectDB(uintptr_t addr, uintptr_t size);
void lockDB();
void unlockDB();
#endif
+8 -1
View File
@@ -7,6 +7,13 @@ extern int box64_log; // log level
extern int box64_dynarec_log;
extern int box64_dynarec;
extern int box64_pagesize;
#ifdef DYNAREC
extern int box64_dynarec_dump;
extern int box64_dynarec_trace;
extern int box64_dynarec_forced;
extern int box64_dynarec_largest;
extern uintptr_t box64_nodynarec_start, box64_nodynarec_end;
#endif
extern int dlsym_error; // log dlsym error
extern int trace_xmm; // include XMM reg in trace?
extern int trace_emm; // include EMM reg in trace?
@@ -30,7 +37,7 @@ extern FILE* ftrace;
#define printf_log(L, ...) do {if(L<=box64_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define dynarec_log(L, ...) do {if(L<=box64_dynarec_log) {fprintf(ftrace, __VA_ARGS__); /*fflush(ftrace);*/}} while(0)
#define dynarec_log(L, ...) do {if(L<=box64_dynarec_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define EXPORT __attribute__((visibility("default")))
#ifdef BUILD_DYNAMIC
+31
View File
@@ -0,0 +1,31 @@
#ifndef __DYNABLOCK_H_
#define __DYNABLOCK_H_
typedef struct x64emu_s x64emu_t;
typedef struct dynablock_s dynablock_t;
typedef struct dynablocklist_s dynablocklist_t;
typedef struct kh_dynablocks_s kh_dynablocks_t;
uint32_t X31_hash_code(void* addr, int len);
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct);
void FreeDynablockList(dynablocklist_t** dynablocks);
void FreeDynablock(dynablock_t* db);
void MarkDynablock(dynablock_t* db);
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
dynablock_t* FindDynablockFromNativeAddress(void* addr); // defined in box64context.h
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks);
uintptr_t StartDynablockList(dynablocklist_t* db);
uintptr_t EndDynablockList(dynablocklist_t* db);
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
// Handling of Dynarec block (i.e. an exectable chunk of x64 translated code)
dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, dynablock_t** current); // return NULL if block is not found / cannot be created. Don't create if create==0
dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr);
// Create and Add an new dynablock in the list, handling direct/map
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created);
#endif //__DYNABLOCK_H_
+9
View File
@@ -0,0 +1,9 @@
#ifndef __DYNAREC_ARM_H_
#define __DYNAREC_ARM_H_
typedef struct dynablock_s dynablock_t;
typedef struct x64emu_s x64emu_t;
void* FillBlock64(dynablock_t* block, uintptr_t addr);
#endif //__DYNAREC_ARM_H_
+36 -2
View File
@@ -1,5 +1,15 @@
#include <stdint.h>
typedef struct x64_va_list_s {
unsigned int gp_offset;
unsigned int fp_offset;
void *overflow_arg_area;
void *reg_save_area;
} x64_va_list_t[1];
#define X64_VA_MAX_REG (6*8)
#define X64_VA_MAX_XMM ((6*8)+(8*16))
#ifdef __x86_64__
// x86_64, 6 64bits general regs and 16 or 8? 128bits float regs
/*
@@ -13,10 +23,19 @@ typedef struct {
*/
#define CREATE_SYSV_VALIST(A) \
va_list sysv_varargs; \
sysv_varargs->gp_offset=(6*8); \
sysv_varargs->fp_offset=(6*8)+(16*16); \
sysv_varargs->gp_offset=X64_VA_MAX_REG; \
sysv_varargs->fp_offset=X64_VA_MAX_XMM; \
sysv_varargs->reg_save_area=A; \
sysv_varargs->overflow_arg_area=A;
#define CONVERT_VALIST(A) \
va_list sysv_varargs; \
sysv_varargs->gp_offset=A->gp_offset; \
sysv_varargs->fp_offset=A->fp_offset; \
sysv_varargs->reg_save_area=A->reg_save_area; \
sysv_varargs->overflow_arg_area=A->overflow_arg_area;
#elif defined(__aarch64__)
// aarch64: 8 64bits general regs and 8 128bits float regs
/*
@@ -34,6 +53,15 @@ typedef struct va_list {
sysv_varargs.__gr_offs=(8*8); \
sysv_varargs.__vr_offs=(8*16); \
sysv_varargs.__stack=A;
#define CONVERT_VALIST(A) \
va_list sysv_varargs; \
sysv_varargs.__gr_offs=-(6*8)+A->gp_offset; \
sysv_varargs.__vr_offs=-(8*16)+(A->fp_offset-X64_VA_MAX_REG); \
sysv_varargs.__stack=A->overflow_arg_area; \
sysv_varargs.__gr_top=A->reg_save_area + X64_VA_MAX_REG; \
sysv_varargs.__vr_top=A->reg_save_area + X64_VA_MAX_XMM;
#elif defined(__powerpc64__)
// TODO, is this correct?
#define CREATE_SYSV_VALIST(A) \
@@ -41,6 +69,9 @@ typedef struct va_list {
sysv_varargs->gpr=8; \
sysv_varargs->fpr=8; \
sysv_varargs->overflow_arg_area=A;
#define CONVERT_VALIST(A) \
#error TODO!
#else
#error Unknown architecture!
#endif
@@ -55,9 +86,12 @@ typedef struct x64emu_s x64emu_t;
// 1st pos is of vaarg is 0, not 1!
void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos);
void myStackAlignScanf(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int pos);
void myStackAlignGVariantNew(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos);
void myStackAlignW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos);
void UnalignStat64(const void* source, void* dest);
// defined in wrapperlibc.c
int of_convert(int); // x86->arm
int of_unconvert(int); // arm->x86
+26 -14
View File
@@ -2,11 +2,19 @@
#define __REGS_H_
enum {
_AX, _CX, _DX, _BX,
_SP, _BP, _SI, _DI,
_RAX, _RCX, _RDX, _RBX,
_RSP, _RBP, _RSI, _RDI,
_R8, _R9,_R10,_R11,
_R12,_R13,_R14,_R15
};
#define _AX _RAX
#define _CX _RCX
#define _DX _RDX
#define _BX _RBX
#define _SP _RSP
#define _BP _RBP
#define _SI _RSI
#define _DI _RDI
enum {
_CS, _DS, _SS, _ES, _FS, _GS
@@ -39,7 +47,8 @@ typedef enum {
d_none = 0,
d_add8,
d_add16,
d_add32,
d_add32, // using 64bits res
d_add32b, // using 32bits res
d_add64,
d_and8,
d_and16,
@@ -100,6 +109,7 @@ typedef enum {
d_adc8,
d_adc16,
d_adc32,
d_adc32b,
d_adc64,
d_sbb8,
d_sbb16,
@@ -150,18 +160,18 @@ typedef struct {
typedef union {
struct __attribute__ ((__packed__)) {
unsigned int _F_CF:1;
unsigned int _F_CF:1; //0x0001
unsigned int _F_res1:1;
unsigned int _F_PF:1;
unsigned int _F_PF:1; //0x0004
unsigned int _F_res2:1;
unsigned int _F_AF:1;
unsigned int _F_AF:1; //0x0010
unsigned int _F_res3:1;
unsigned int _F_ZF:1;
unsigned int _F_SF:1;
unsigned int _F_TF:1;
unsigned int _F_IF:1;
unsigned int _F_DF:1;
unsigned int _F_OF:1;
unsigned int _F_ZF:1; //0x0040
unsigned int _F_SF:1; //0x0080
unsigned int _F_TF:1; //0x0100
unsigned int _F_IF:1; //0x0200
unsigned int _F_DF:1; //0x0400
unsigned int _F_OF:1; //0x0800
unsigned int _F_IOPL:2;
unsigned int _F_NT:1;
unsigned int _F_dummy:1;
@@ -171,9 +181,11 @@ typedef union {
unsigned int _F_VIF:1;
unsigned int _F_VIP:1;
unsigned int _F_ID:1;
unsigned int _F_fill1:10;
uint32_t _F_fill2;
} f;
uint32_t x32;
} x86flags_t;
uint64_t x64;
} x64flags_t;
typedef enum {
F_CF = 0,
+21
View File
@@ -0,0 +1,21 @@
#ifndef __SDL1RWOPS_H__
#define __SDL1RWOPS_H__
typedef struct SDL1_RWops_s SDL1_RWops_t; // the actual SDL1 SDL_RWops
typedef struct x64emu_s x64emu_t;
typedef SDL1_RWops_t* (*sdl1_allocrw)();
typedef void (*sdl1_freerw)(SDL1_RWops_t*);
// each function will be added to dictionary, and each native functions will be wrapped so they run in emulated world
SDL1_RWops_t* AddNativeRW(x64emu_t* emu, SDL1_RWops_t* ops);
SDL1_RWops_t* RWNativeStart(x64emu_t* emu, SDL1_RWops_t* ops); // put Native RW function, wrapping emulated (callback style) ones if needed
void RWNativeEnd(SDL1_RWops_t* ops); // put back emulated function back in place
int32_t RWNativeSeek(SDL1_RWops_t *ops, int32_t offset, int32_t whence);
uint32_t RWNativeRead(SDL1_RWops_t* ops, void* ptr, uint32_t size, uint32_t maxnum);
int32_t RWNativeWrite(SDL1_RWops_t *ops, const void *ptr, int32_t size, int32_t num);
int32_t RWNativeClose(SDL1_RWops_t* ops);
void RWSetType(SDL1_RWops_t* r, int t);
#endif
+31
View File
@@ -0,0 +1,31 @@
#ifndef __SDL2RWOPS_H__
#define __SDL2RWOPS_H__
typedef struct SDL2_RWops_s SDL2_RWops_t; // the actual SDL1 SDL_RWops
typedef struct x64emu_s x64emu_t;
typedef SDL2_RWops_t* (*sdl2_allocrw)();
typedef void (*sdl2_freerw)(SDL2_RWops_t*);
typedef struct SDL2RWSave_s {
int anyEmu;
void* size;
void* seek;
void* read;
void* write;
void* close;
void* s1;
void* s2;
} SDL2RWSave_t;
// each function will be added to dictionary, and each native functions will be wrapped so they run in emulated world
SDL2_RWops_t* AddNativeRW2(x64emu_t* emu, SDL2_RWops_t* ops);
SDL2_RWops_t* RWNativeStart2(x64emu_t* emu, SDL2_RWops_t* ops); // put Native RW function, wrapping emulated (callback style) ones if needed
void RWNativeEnd2(SDL2_RWops_t* ops); // put back emulated function back in place
int64_t RWNativeSeek2(SDL2_RWops_t *ops, int64_t offset, int32_t whence);
uint32_t RWNativeRead2(SDL2_RWops_t* ops, void* ptr, uint32_t size, uint32_t maxnum);
int32_t RWNativeWrite2(SDL2_RWops_t *ops, const void *ptr, int32_t size, int32_t num);
int32_t RWNativeClose2(SDL2_RWops_t* ops);
#endif
+2 -1
View File
@@ -430,7 +430,8 @@ int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* st
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name)
{
uintptr_t start, end;
uintptr_t start=0;
uintptr_t end=0;
for(int i=0; i<maplib->libsz; ++i)
if(GetElfIndex(maplib->libraries[i].lib)==-1)
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, &start, &end))
+5 -5
View File
@@ -587,7 +587,7 @@ int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr
printf_log(LOG_NONE, "Warning, function %s not found\n", buff);
} else
AddOffsetSymbol(lib->context->maplib, symbol, name);
*addr = AddBridge(lib->priv.w.bridge, kh_value(lib->mysymbolmap, k), symbol, 0);
*addr = AddBridge(lib->priv.w.bridge, kh_value(lib->mysymbolmap, k), symbol, 0, name);
*size = sizeof(void*);
return 1;
}
@@ -605,7 +605,7 @@ int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr
printf_log(LOG_NONE, "Warning, function %s not found\n", buff);
} else
AddOffsetSymbol(lib->context->maplib, symbol, name);
*addr = AddBridge(lib->priv.w.bridge, kh_value(lib->stsymbolmap, k), symbol, 4); // all of this for this little "4"
*addr = AddBridge(lib->priv.w.bridge, kh_value(lib->stsymbolmap, k), symbol, sizeof(void*), name);
*size = sizeof(void*);
return 1;
}
@@ -624,7 +624,7 @@ int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr
return 0;
} else
AddOffsetSymbol(lib->context->maplib, symbol, name);
*addr = AddBridge(lib->priv.w.bridge, kh_value(lib->symbolmap, k), symbol, 0);
*addr = AddBridge(lib->priv.w.bridge, kh_value(lib->symbolmap, k), symbol, 0, name);
*size = sizeof(void*);
return 1;
}
@@ -643,7 +643,7 @@ int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr
return 0;
} else
AddOffsetSymbol(lib->context->maplib, symbol, name);
*addr = AddBridge(lib->priv.w.bridge, kh_value(lib->wsymbolmap, k), symbol, 0);
*addr = AddBridge(lib->priv.w.bridge, kh_value(lib->wsymbolmap, k), symbol, 0, name);
*size = sizeof(void*);
return 1;
}
@@ -661,7 +661,7 @@ int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr
return 0;
} else
AddOffsetSymbol(lib->context->maplib, symbol, name);
*addr = AddBridge(lib->priv.w.bridge, kh_value(lib->symbol2map, k).w, symbol, 0);
*addr = AddBridge(lib->priv.w.bridge, kh_value(lib->symbol2map, k).w, symbol, 0, name);
*size = sizeof(void*);
return 1;
}
+36 -36
View File
@@ -5,46 +5,45 @@
GO("libc.so.6", libc)
GO("libpthread.so.0", libpthread)
GO("librt.so.1", librt)
//GO("libGL.so.1", libgl)
//GO("libGL.so", libgl)
//GO("libGLU.so.1", libglu)
//GO("libX11.so.6", libx11)
//GO("libasound.so.2", libasound)
GO("libGL.so.1", libgl)
GO("libGL.so", libgl)
GO("libGLU.so.1", libglu)
GO("libX11.so.6", libx11)
GO("libasound.so.2", libasound)
GO("libdl.so.2", libdl)
GO("libm.so.6", libm)
//GO("libSDL2-2.0.so.0", sdl2)
//GO("libSDL2-2.0.so.1", sdl2)
//GO("libSDL2.so", sdl2)
//GO("libsdl2-2.0.so.0", sdl2)
//GO("libSDL2_mixer-2.0.so.0", sdl2mixer)
//GO("libSDL2_image-2.0.so.0", sdl2image)
//GO("libSDL2_ttf-2.0.so.0", sdl2ttf)
//GO("libSDL-1.2.so.0", sdl1)
//GO("libSDL-1.1.so.0", sdl1)
//GO("libSDL_mixer-1.2.so.0", sdl1mixer)
//GO("libSDL_image-1.2.so.0", sdl1image)
//GO("libSDL_ttf-2.0.so.0", sdl1ttf)
//GO("libsmpeg-0.4.so.0", smpeg)
//GO("libsmpeg2-2.0.so.0", smpeg2)
GO("libSDL2-2.0.so.0", sdl2)
GO("libSDL2-2.0.so.1", sdl2)
GO("libSDL2.so", sdl2)
GO("libsdl2-2.0.so.0", sdl2)
GO("libSDL2_mixer-2.0.so.0", sdl2mixer)
GO("libSDL2_image-2.0.so.0", sdl2image)
GO("libSDL2_ttf-2.0.so.0", sdl2ttf)
GO("libSDL-1.2.so.0", sdl1)
GO("libSDL_mixer-1.2.so.0", sdl1mixer)
GO("libSDL_image-1.2.so.0", sdl1image)
GO("libSDL_ttf-2.0.so.0", sdl1ttf)
GO("libsmpeg-0.4.so.0", smpeg)
GO("libsmpeg2-2.0.so.0", smpeg2)
//GO("libvorbisfile.so.3", vorbisfile)
//GO("libvorbis.so.0", libvorbis)
//GO("libogg.so.0", libogg)
//GO("libpng12.so.0", png12)
//GO("libpng16.so.16", png16)
//GO("libXxf86vm.so.1", libxxf86vm)
//GO("libXinerama.so.1", xinerama)
//GO("libXrandr.so.2", libxrandr)
//GO("libXext.so.6", libxext)
GO("libXxf86vm.so.1", libxxf86vm)
GO("libXinerama.so.1", xinerama)
GO("libXrandr.so.2", libxrandr)
GO("libXext.so.6", libxext)
//GO("libXfixes.so.3", libxfixes)
//GO("libXcursor.so.1", libxcursor)
//GO("libXrender.so.1", libxrender)
//GO("libXi.so.6", libxi)
GO("libXrender.so.1", libxrender)
GO("libXi.so.6", libxi)
//GO("libXss.so.1", libxss)
//GO("libXpm.so.4", libxpm)
//GO("libXau.so.6", libxau)
//GO("libXdmcp.so.6", libxdmcp)
GO("libXau.so.6", libxau)
GO("libXdmcp.so.6", libxdmcp)
//GO("libX11-xcb.so.1", libx11xcb)
//GO("libxcb.so.1", libxcb)
GO("libxcb.so.1", libxcb)
//GO("libxcb-xfixes.so.0", libxcbxfixes)
//GO("libxcb-shape.so.0", libxcbshape)
//GO("libxcb-shm.so.0", libxcbshm)
@@ -60,12 +59,13 @@ GO("libm.so.6", libm)
//GO("libXcomposite.so.1", libxcomposite)
//GO("libXdamage.so.1", libxdamage)
//GO("libXmu.so.6", libxmu)
//GO("libz.so.1", libz)
//GO("libopenal.so.1", openal)
//GO("libopenal.so.0", openal)
//GO("libopenal.so", openal)
//GO("openal.so", openal)
//GO("libalut.so.0", alut)
GO("libz.so.1", libz)
GO("libopenal.so.1", openal)
GO("libopenal.so.0", openal)
GO("libopenal.so", openal)
GO("openal.so", openal)
GO("libalut.so.0", alut)
GO("libalure.so.1", alure)
//GO("libjpeg.so.8", libjpeg)
//GO("libjpeg.so.62", libjpeg62)
//GO("libturbojpeg.so.0", turbojpeg)
@@ -82,8 +82,8 @@ GO("libm.so.6", libm)
//GO("libutil.so.1", util)
//GO("libuuid.so.1", libuuid)
//GO("libresolv.so.2", libresolv)
//GO("libpulse-simple.so.0", pulsesimple)
//GO("libpulse.so.0", pulse)
GO("libpulse-simple.so.0", pulsesimple)
GO("libpulse.so.0", pulse)
//GO("libsndfile.so.1", libsndfile)
//GO("libgtk-x11-2.0.so.0", gtkx112)
//GO("libgdk-x11-2.0.so.0", gdkx112)
+143
View File
@@ -5,6 +5,7 @@
#include <wchar.h>
#include <sys/epoll.h>
#include <fts.h>
#include <sys/stat.h>
#include "x64emu.h"
#include "emu/x64emu_private.h"
@@ -99,7 +100,11 @@ void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystac
++p;
break;
case 14: //%LG long double
if((((uintptr_t)(st+1))&0xf)!=0)
st++;
#ifdef HAVE_LD80BITS
if((((uintptr_t)mystack)&0xf)!=0)
mystack++;
memcpy(mystack, st, 16);
st+=2; mystack+=2;
#else
@@ -136,6 +141,100 @@ void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystac
}
}
}
void myStackAlignScanf(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int pos)
{
if(!fmt)
return;
// loop...
const char* p = fmt;
int state = 0;
while(*p)
{
switch(state) {
case 0:
switch(*p) {
case '%': state = 1; ++p; break;
default:
++p;
}
break;
case 1: // normal
case 2: // l
case 3: // ll
case 4: // L
switch(*p) {
case '%': state = 0; ++p; break; //%% = back to 0
case 'l': ++state; if (state>3) state=3; ++p; break;
case 'L': state = 4; ++p; break;
case 'a':
case 'A':
case 'e':
case 'E':
case 'g':
case 'G':
case 'F':
case 'f': state += 10; break; // float
case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X': state += 20; break; // int
case 'h': ++p; break; // ignored...
case '\'':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
case '+':
case '-': ++p; break; // formating, ignored
case 'm': state = 0; ++p; break; // no argument
case 'n':
case 'p':
case 'S':
case 's': state = 30; break; // pointers
case '$': ++p; break; // should issue a warning, it's not handled...
case '*': *(mystack++) = *(st++); ++p; break; // fetch an int in the stack....
case ' ': state=0; ++p; break;
default:
state=20; // other stuff, put an int...
}
break;
case 11: //double
case 12: //%lg, still double
case 13: //%llg, still double
case 14: //%LG long double
case 20: // fallback
case 21:
case 22:
case 23: // 64bits int
case 24: // normal int / pointer
case 30:
if(pos<6)
*mystack = emu->regs[regs_abi[pos++]].q[0];
else {
*mystack = *st;
++st;
}
++mystack;
state = 0;
++p;
break;
default:
// whattt?
state = 0;
}
}
}
#if 0
void myStackAlignGVariantNew(const char* fmt, uint32_t* st, uint32_t* mystack)
{
@@ -430,3 +529,47 @@ void myStackAlignW(const char* fmt, uint32_t* st, uint32_t* mystack)
}
}
#endif
#undef st_atime
#undef st_mtime
#undef st_ctime
struct x64_stat64 { /* x86_64 arm64 */
uint64_t st_dev; /* 0 */ /* 0 */
uint64_t st_ino; /* 8 */ /* 8 */
uint64_t st_nlink; /* 16 */ /* 20 */
uint32_t st_mode; /* 24 */ /* 16 */
uint32_t st_uid; /* 28 */ /* 24 */
uint32_t st_gid; /* 32 */ /* 28 */
int __pad0; /* 36 */ /* --- */
uint64_t st_rdev; /* 40 */ /* 32 */
int64_t st_size; /* 48 */ /* 48 */
int64_t st_blksize; /* 56 */ /* 56 */
uint64_t st_blocks; /* 64 */ /* 64 */
struct timespec st_atim; /* 72 */ /* 72 */
struct timespec st_mtim; /* 88 */ /* 88 */
struct timespec st_ctim; /* 104 */ /* 104 */
uint64_t __glibc_reserved[3]; /* 120 */ /* 120 */
} __attribute__((packed)); /* 144 */ /* 128 */
void UnalignStat64(const void* source, void* dest)
{
struct x64_stat64 *x64st = (struct x64_stat64*)dest;
struct stat *st = (struct stat*) source;
x64st->__pad0 = 0;
memset(x64st->__glibc_reserved, 0, sizeof(x64st->__glibc_reserved));
x64st->st_dev = st->st_dev;
x64st->st_ino = st->st_ino;
x64st->st_mode = st->st_mode;
x64st->st_nlink = st->st_nlink;
x64st->st_uid = st->st_uid;
x64st->st_gid = st->st_gid;
x64st->st_rdev = st->st_rdev;
x64st->st_size = st->st_size;
x64st->st_blksize = st->st_blksize;
x64st->st_blocks = st->st_blocks;
x64st->st_atim = st->st_atim;
x64st->st_mtim = st->st_mtim;
x64st->st_ctim = st->st_ctim;
}
+182
View File
@@ -0,0 +1,182 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "sdl1rwops.h"
#include "debug.h"
#include "wrapper.h"
#include "box64context.h"
#include "x64run.h"
#include "x64emu.h"
#include "emu/x64emu_private.h"
#include "librarian/library_private.h"
#include "bridge.h"
#include "callback.h"
typedef struct SDL1_RWops_s SDL1_RWops_t;
typedef int32_t (*sdl1_seek)(SDL1_RWops_t *context, int32_t offset, int32_t whence);
typedef int32_t (*sdl1_read)(SDL1_RWops_t *context, void *ptr, int32_t size, int32_t maxnum);
typedef int32_t (*sdl1_write)(SDL1_RWops_t *context, const void *ptr, int32_t size, int32_t num);
typedef int32_t (*sdl1_close)(SDL1_RWops_t *context);
#define BOX64RW 0xBECF4572 // random signature value
typedef struct SDL1_RWops_s {
sdl1_seek seek;
sdl1_read read;
sdl1_write write;
sdl1_close close;
uint32_t type;
union {
struct {
int autoclose;
FILE *fp;
} stdio;
struct {
uint8_t *base;
uint8_t *here;
uint8_t *stop;
} mem;
struct {
void *data1;
} unknown;
struct {
SDL1_RWops_t *orig;
sdl1_freerw custom_free;
} my;
} hidden;
} SDL1_RWops_t;
EXPORT int32_t my_native_seek(SDL1_RWops_t *context, int32_t offset, int32_t whence)
{
return context->hidden.my.orig->seek(context->hidden.my.orig, offset, whence);
}
EXPORT int32_t my_native_read(SDL1_RWops_t *context, void *ptr, int32_t size, int32_t maxnum)
{
return context->hidden.my.orig->read(context->hidden.my.orig, ptr, size, maxnum);
}
EXPORT int32_t my_native_write(SDL1_RWops_t *context, const void *ptr, int32_t size, int32_t num)
{
return context->hidden.my.orig->write(context->hidden.my.orig, ptr, size, num);
}
EXPORT int32_t my_native_close(SDL1_RWops_t *context)
{
int32_t ret = context->hidden.my.orig->close(context->hidden.my.orig);
context->hidden.my.custom_free(context);
return ret;
}
EXPORT int32_t my_emulated_seek(SDL1_RWops_t *context, int32_t offset, int32_t whence)
{
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->seek, 3, context->hidden.my.orig, offset, whence);
}
EXPORT int32_t my_emulated_read(SDL1_RWops_t *context, void *ptr, int32_t size, int32_t maxnum)
{
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->read, 4, context->hidden.my.orig, ptr, size, maxnum);
}
EXPORT int32_t my_emulated_write(SDL1_RWops_t *context, const void *ptr, int32_t size, int32_t num)
{
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->write, 4, context->hidden.my.orig, ptr, size, num);
}
EXPORT int32_t my_emulated_close(SDL1_RWops_t *context)
{
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->close, 1, context->hidden.my.orig);
}
SDL1_RWops_t* AddNativeRW(x64emu_t* emu, SDL1_RWops_t* ops)
{
if(!ops)
return NULL;
uintptr_t fnc;
bridge_t* system = emu->context->system;
sdl1_allocrw Alloc = (sdl1_allocrw)emu->context->sdl1allocrw;
sdl1_freerw Free = (sdl1_freerw)emu->context->sdl1freerw;
SDL1_RWops_t* newrw = Alloc();
newrw->type = BOX64RW;
newrw->hidden.my.orig = ops;
newrw->hidden.my.custom_free = Free;
// get or create wrapper, add it to map and change to the emulated one if rw
#define GO(A, W) \
fnc = AddCheckBridge(system, W, my_native_##A, 0, NULL); \
newrw->A = (sdl1_##A)fnc;
GO(seek, iFpii)
GO(read, iFppii)
GO(write, iFppii)
GO(close, iFp)
#undef GO
return newrw;
}
// put Native RW function, wrapping emulated (callback style) ones if needed
SDL1_RWops_t* RWNativeStart(x64emu_t* emu, SDL1_RWops_t* ops)
{
if(!ops)
return NULL;
if(ops->type == BOX64RW)
return ops->hidden.my.orig;
sdl1_allocrw Alloc = (sdl1_allocrw)emu->context->sdl1allocrw;
SDL1_RWops_t* newrw = Alloc();
newrw->type = BOX64RW;
newrw->hidden.my.orig = ops;
// create wrapper
#define GO(A, W) \
newrw->A = my_emulated_##A;
GO(seek, iFpii)
GO(read, iFppii)
GO(write, iFppii)
GO(close, iFp)
#undef GO
return newrw;
}
// put back emulated function back in place
void RWNativeEnd(SDL1_RWops_t* ops)
{
if(!ops)
return;
if(ops->type != BOX64RW)
return; // do nothing
ops->hidden.my.custom_free(ops);
}
int32_t RWNativeSeek(SDL1_RWops_t *ops, int32_t offset, int32_t whence)
{
return ops->seek(ops, offset, whence);
}
uint32_t RWNativeRead(SDL1_RWops_t* ops, void* ptr, uint32_t size, uint32_t maxnum)
{
return ops->read(ops, ptr, size, maxnum);
}
int32_t RWNativeWrite(SDL1_RWops_t *ops, const void *ptr, int32_t size, int32_t num)
{
return ops->write(ops, ptr, size, num);
}
int32_t RWNativeClose(SDL1_RWops_t* ops)
{
return ops->close(ops);
}
void RWSetType(SDL1_RWops_t* r, int awesome)
{
if(r)
r->type = awesome; // I like shoot'em up :D
}
+185
View File
@@ -0,0 +1,185 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "sdl2rwops.h"
#include "debug.h"
#include "wrapper.h"
#include "box64context.h"
#include "x64run.h"
#include "x64emu.h"
#include "emu/x64emu_private.h"
#include "librarian/library_private.h"
#include "bridge.h"
#include "callback.h"
typedef struct SDL2_RWops_s SDL2_RWops_t;
typedef int64_t (*sdl2_size)(SDL2_RWops_t *context);
typedef int64_t (*sdl2_seek)(SDL2_RWops_t *context, int64_t offset, int32_t whence);
typedef int32_t (*sdl2_read)(SDL2_RWops_t *context, void *ptr, int32_t size, int32_t maxnum);
typedef int32_t (*sdl2_write)(SDL2_RWops_t *context, const void *ptr, int32_t size, int32_t num);
typedef int32_t (*sdl2_close)(SDL2_RWops_t *context);
#define BOX64RW 0x79 // random signature value
typedef struct SDL2_RWops_s {
sdl2_size size;
sdl2_seek seek;
sdl2_read read;
sdl2_write write;
sdl2_close close;
uint32_t type;
union {
struct {
int autoclose;
FILE *fp;
} stdio;
struct {
uint8_t *base;
uint8_t *here;
uint8_t *stop;
} mem;
struct {
void *data1;
} unknown;
struct {
SDL2_RWops_t *orig;
sdl2_freerw custom_free;
} my;
} hidden;
} SDL2_RWops_t;
EXPORT int64_t my2_native_size(SDL2_RWops_t *context)
{
return context->hidden.my.orig->size(context->hidden.my.orig);
}
EXPORT int64_t my2_native_seek(SDL2_RWops_t *context, int64_t offset, int32_t whence)
{
return context->hidden.my.orig->seek(context->hidden.my.orig, offset, whence);
}
EXPORT int32_t my2_native_read(SDL2_RWops_t *context, void *ptr, int32_t size, int32_t maxnum)
{
return context->hidden.my.orig->read(context->hidden.my.orig, ptr, size, maxnum);
}
EXPORT int32_t my2_native_write(SDL2_RWops_t *context, const void *ptr, int32_t size, int32_t num)
{
return context->hidden.my.orig->write(context->hidden.my.orig, ptr, size, num);
}
EXPORT int32_t my2_native_close(SDL2_RWops_t *context)
{
int32_t ret = context->hidden.my.orig->close(context->hidden.my.orig);
context->hidden.my.custom_free(context);
return ret;
}
EXPORT int64_t my2_emulated_size(SDL2_RWops_t *context)
{
return (int64_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->size, 1, context->hidden.my.orig);
}
EXPORT int64_t my2_emulated_seek(SDL2_RWops_t *context, int64_t offset, int32_t whence)
{
return (int64_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->seek, 3, context->hidden.my.orig, offset, whence);
}
EXPORT int32_t my2_emulated_read(SDL2_RWops_t *context, void *ptr, int32_t size, int32_t maxnum)
{
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->read, 4, context->hidden.my.orig, ptr, size, maxnum);
}
EXPORT int32_t my2_emulated_write(SDL2_RWops_t *context, const void *ptr, int32_t size, int32_t num)
{
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->write, 4, context->hidden.my.orig, ptr, size, num);
}
EXPORT int32_t my2_emulated_close(SDL2_RWops_t *context)
{
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->close, 1, context->hidden.my.orig);
}
SDL2_RWops_t* AddNativeRW2(x64emu_t* emu, SDL2_RWops_t* ops)
{
if(!ops)
return NULL;
uintptr_t fnc;
bridge_t* system = emu->context->system;
sdl2_allocrw Alloc = (sdl2_allocrw)emu->context->sdl2allocrw;
sdl2_freerw Free = (sdl2_freerw)emu->context->sdl2freerw;
SDL2_RWops_t* newrw = Alloc();
newrw->type = BOX64RW;
newrw->hidden.my.orig = ops;
newrw->hidden.my.custom_free = Free;
// get or create wrapper, add it to map and change to the emulated one if rw
#define GO(A, W) \
fnc = AddCheckBridge(system, W, my2_native_##A, 0, NULL); \
newrw->A = (sdl2_##A)fnc;
GO(size, IFp)
GO(seek, IFpIi)
GO(read, iFppii)
GO(write, iFppii)
GO(close, iFp)
#undef GO
return newrw;
}
// put Native RW function, wrapping emulated (callback style) ones if needed
SDL2_RWops_t* RWNativeStart2(x64emu_t* emu, SDL2_RWops_t* ops)
{
if(!ops)
return NULL;
if(ops->type == BOX64RW)
return ops->hidden.my.orig;
sdl2_allocrw Alloc = (sdl2_allocrw)emu->context->sdl2allocrw;
SDL2_RWops_t* newrw = Alloc();
newrw->type = BOX64RW;
newrw->hidden.my.orig = ops;
newrw->hidden.my.custom_free = (sdl2_freerw)emu->context->sdl2freerw;
// create wrapper
#define GO(A, W) \
newrw->A = my2_emulated_##A;
GO(size, IFp)
GO(seek, IFpIi)
GO(read, iFppii)
GO(write, iFppii)
GO(close, iFp)
#undef GO
return newrw;
}
void RWNativeEnd2(SDL2_RWops_t* ops)
{
if(!ops || ops->type != BOX64RW)
return; // do nothing
ops->hidden.my.custom_free(ops);
}
int64_t RWNativeSeek2(SDL2_RWops_t *ops, int64_t offset, int32_t whence)
{
return ops->seek(ops, offset, whence);
}
uint32_t RWNativeRead2(SDL2_RWops_t* ops, void* ptr, uint32_t size, uint32_t maxnum)
{
return ops->read(ops, ptr, size, maxnum);
}
int32_t RWNativeWrite2(SDL2_RWops_t *ops, const void *ptr, int32_t size, int32_t num)
{
return ops->write(ops, ptr, size, num);
}
int32_t RWNativeClose2(SDL2_RWops_t* ops)
{
return ops->close(ops);
}
+74 -51
View File
@@ -445,13 +445,13 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
uintptr_t restorer = my_context->restorer[sig];
// get that actual ESP first!
x64emu_t *emu = thread_get_emu();
uint64_t *frame = (uint64_t*)R_RSP;
#if defined(DYNAREC) && defined(__arm__)
uintptr_t *frame = (uintptr_t*)R_RSP;
#if defined(DYNAREC) && defined(__aarch64__)
ucontext_t *p = (ucontext_t *)ucntx;
void * pc = (void*)p->uc_mcontext.arm_pc;
void * pc = (void*)p->uc_mcontext.pc;
dynablock_t* db = (dynablock_t*)cur_db;//FindDynablockFromNativeAddress(pc);
if(db) {
frame = (uint32_t*)p->uc_mcontext.arm_r8;
frame = (uintptr_t*)p->uc_mcontext.regs[10+_SP];
}
#endif
// stack tracking
@@ -460,9 +460,9 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
int used_stack = 0;
if(new_ss) {
if(new_ss->ss_flags == SS_ONSTACK) { // already using it!
frame = (uint64_t*)sigemu->regs[_SP].q[0];
frame = (uintptr_t*)sigemu->regs[_SP].q[0];
} else {
frame = (uint64_t*)(((uintptr_t)new_ss->ss_sp + new_ss->ss_size - 16) & ~0x0f);
frame = (uintptr_t*)(((uintptr_t)new_ss->ss_sp + new_ss->ss_size - 16) & ~0x0f);
used_stack = 1;
new_ss->ss_flags = SS_ONSTACK;
}
@@ -471,7 +471,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
// TODO: do I need to really setup 2 stack frame? That doesn't seems right!
// setup stack frame
// try to fill some sigcontext....
frame -= sizeof(x64_ucontext_t);
frame -= sizeof(x64_ucontext_t)/sizeof(uintptr_t);
x64_ucontext_t *sigcontext = (x64_ucontext_t*)frame;
// get general register
sigcontext->uc_mcontext.gregs[X64_R8] = R_R8;
@@ -492,20 +492,28 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
sigcontext->uc_mcontext.gregs[X64_RSP] = R_RSP;
sigcontext->uc_mcontext.gregs[X64_RBX] = R_RBX;
// flags
sigcontext->uc_mcontext.gregs[X64_EFL] = emu->eflags.x32;
sigcontext->uc_mcontext.gregs[X64_EFL] = emu->eflags.x64;
// get segments
sigcontext->uc_mcontext.gregs[X64_CSGSFS] = ((uint64_t)(R_CS)) | (((uint64_t)(R_GS))<<16) | (((uint64_t)(R_FS))<<32);
#if defined(DYNAREC) && defined(__arm__)
#if defined(DYNAREC) && defined(__aarch64__)
if(db) {
sigcontext->uc_mcontext.gregs[X64_RAX] = p->uc_mcontext.arm_r4;
sigcontext->uc_mcontext.gregs[X64_RCX] = p->uc_mcontext.arm_r5;
sigcontext->uc_mcontext.gregs[X64_RDX] = p->uc_mcontext.arm_r6;
sigcontext->uc_mcontext.gregs[X64_RBX] = p->uc_mcontext.arm_r7;
sigcontext->uc_mcontext.gregs[X64_RSP] = p->uc_mcontext.arm_r8;
sigcontext->uc_mcontext.gregs[X64_RBP] = p->uc_mcontext.arm_r9;
sigcontext->uc_mcontext.gregs[X64_RSI] = p->uc_mcontext.arm_r10;
sigcontext->uc_mcontext.gregs[X64_RDI] = p->uc_mcontext.arm_fp;
sigcontext->uc_mcontext.gregs[X64_RIP] = getX86Address(db, (uintptr_t)pc);
sigcontext->uc_mcontext.gregs[X64_RAX] = p->uc_mcontext.regs[10];
sigcontext->uc_mcontext.gregs[X64_RCX] = p->uc_mcontext.regs[11];
sigcontext->uc_mcontext.gregs[X64_RDX] = p->uc_mcontext.regs[12];
sigcontext->uc_mcontext.gregs[X64_RBX] = p->uc_mcontext.regs[13];
sigcontext->uc_mcontext.gregs[X64_RSP] = p->uc_mcontext.regs[14];
sigcontext->uc_mcontext.gregs[X64_RBP] = p->uc_mcontext.regs[15];
sigcontext->uc_mcontext.gregs[X64_RSI] = p->uc_mcontext.regs[16];
sigcontext->uc_mcontext.gregs[X64_RDI] = p->uc_mcontext.regs[17];
sigcontext->uc_mcontext.gregs[X64_R8] = p->uc_mcontext.regs[18];
sigcontext->uc_mcontext.gregs[X64_R9] = p->uc_mcontext.regs[19];
sigcontext->uc_mcontext.gregs[X64_R10] = p->uc_mcontext.regs[20];
sigcontext->uc_mcontext.gregs[X64_R11] = p->uc_mcontext.regs[21];
sigcontext->uc_mcontext.gregs[X64_R12] = p->uc_mcontext.regs[22];
sigcontext->uc_mcontext.gregs[X64_R13] = p->uc_mcontext.regs[23];
sigcontext->uc_mcontext.gregs[X64_R14] = p->uc_mcontext.regs[24];
sigcontext->uc_mcontext.gregs[X64_R15] = p->uc_mcontext.regs[25];
sigcontext->uc_mcontext.gregs[X64_RIP] = getX64Address(db, (uintptr_t)pc);
}
#endif
// get FloatPoint status
@@ -608,7 +616,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
if(sigcontext->uc_mcontext.gregs[X64_RIP]!=sigcontext_copy.uc_mcontext.gregs[X64_RIP]) ejb->emu->ip.dword[0]=sigcontext->uc_mcontext.gregs[X64_RIP];
sigcontext->uc_mcontext.gregs[X64_RIP] = R_RIP;
// flags
if(sigcontext->uc_mcontext.gregs[X64_EFL]!=sigcontext_copy.uc_mcontext.gregs[X64_EFL]) ejb->emu->eflags.x32=sigcontext->uc_mcontext.gregs[X64_EFL];
if(sigcontext->uc_mcontext.gregs[X64_EFL]!=sigcontext_copy.uc_mcontext.gregs[X64_EFL]) ejb->emu->eflags.x64=sigcontext->uc_mcontext.gregs[X64_EFL];
// get segments
uint16_t seg;
seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 0)&0xffff;
@@ -637,7 +645,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
new_ss->ss_flags = 0;
}
void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
{
// sig==SIGSEGV || sig==SIGBUS || sig==SIGILL here!
int log_minimum = (my_context->is_sigaction[sig] && sig==SIGSEGV)?LOG_INFO:LOG_NONE;
@@ -659,32 +667,47 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
dynablock_t* db = NULL;
int db_searched = 0;
if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC)) {
if(box86_dynarec_smc) {
dynablock_t* db_pc = NULL;
db_pc = FindDynablockFromNativeAddress(pc);
if(db_pc) {
db = FindDynablockFromNativeAddress(addr);
db_searched = 1;
}
if(db_pc && db) {
if (db_pc == db) {
dynarec_log(LOG_NONE, "Warning: Access to protected %p from %p, inside same dynablock\n", addr, pc);
}
}
if(db && db->x86_addr>= addr && (db->x86_addr+db->x86_size)<addr) {
dynarec_log(LOG_INFO, "Warning, addr inside current dynablock!\n");
}
}
dynarec_log(LOG_DEBUG, "Access to protected %p from %p, unprotecting memory (prot=%x)\n", addr, pc, prot);
// access error, unprotect the block (and mark them dirty)
if(prot&PROT_DYNAREC) // on heavy multi-thread program, the protection can already be gone...
unprotectDB((uintptr_t)addr, 1); // unprotect 1 byte... But then, the whole page will be unprotected
// check if SMC inside block
if(!db_searched) {
db = FindDynablockFromNativeAddress(pc);
db_searched = 1;
}
if(db && (addr>=db->x64_addr && addr<(db->x64_addr+db->x64_size))) {
// dynablock got auto-dirty! need to get out of it!!!
emu_jmpbuf_t* ejb = GetJmpBuf();
if(ejb->jmpbuf_ok) {
ejb->emu->regs[_AX].q[0] = p->uc_mcontext.regs[10];
ejb->emu->regs[_CX].q[0] = p->uc_mcontext.regs[11];
ejb->emu->regs[_DX].q[0] = p->uc_mcontext.regs[12];
ejb->emu->regs[_BX].q[0] = p->uc_mcontext.regs[13];
ejb->emu->regs[_SP].q[0] = p->uc_mcontext.regs[14];
ejb->emu->regs[_BP].q[0] = p->uc_mcontext.regs[15];
ejb->emu->regs[_SI].q[0] = p->uc_mcontext.regs[16];
ejb->emu->regs[_DI].q[0] = p->uc_mcontext.regs[17];
ejb->emu->regs[_R8].q[0] = p->uc_mcontext.regs[18];
ejb->emu->regs[_R9].q[0] = p->uc_mcontext.regs[19];
ejb->emu->regs[_R10].q[0] = p->uc_mcontext.regs[20];
ejb->emu->regs[_R11].q[0] = p->uc_mcontext.regs[21];
ejb->emu->regs[_R12].q[0] = p->uc_mcontext.regs[22];
ejb->emu->regs[_R13].q[0] = p->uc_mcontext.regs[23];
ejb->emu->regs[_R14].q[0] = p->uc_mcontext.regs[24];
ejb->emu->regs[_R15].q[0] = p->uc_mcontext.regs[25];
ejb->emu->ip.q[0] = getX64Address(db, (uintptr_t)pc);
ejb->emu->eflags.x64 = p->uc_mcontext.regs[26];
dynarec_log(LOG_DEBUG, "Auto-SMC detected, getting out of current Dynablock!\n");
longjmp(ejb->jmpbuf, 2);
}
dynarec_log(LOG_INFO, "Warning, Auto-SMC (%p for db %p/%p) detected, but jmpbuffer not ready!\n", (void*)addr, db, (void*)db->x64_addr);
}
// done
if(prot&PROT_WRITE) return; // if there is no write permission, don't return and continue to program signal handling
} else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&(PROT_READ|PROT_WRITE))) {
db = FindDynablockFromNativeAddress(pc);
db_searched = 1;
if(db && db->x86_addr>= addr && (db->x86_addr+db->x86_size)<addr) {
if(db && db->x64_addr>= addr && (db->x64_addr+db->x64_size)<addr) {
dynarec_log(LOG_INFO, "Warning, addr inside current dynablock!\n");
}
if(addr && pc && db) {
@@ -718,13 +741,13 @@ exit(-1);
x64emu_t* emu = thread_get_emu();
x64pc = R_RIP;
rsp = (void*)R_RSP;
#if defined(__arm__) && defined(DYNAREC)
if(db && p->uc_mcontext.arm_r0>0x10000) {
emu = (x64emu_t*)p->uc_mcontext.arm_r0;
#if defined(__aarch64__) && defined(DYNAREC)
if(db && p->uc_mcontext.regs[0]>0x10000) {
emu = (x64emu_t*)p->uc_mcontext.regs[0];
}
if(db) {
x64pc = getX64Address(db, (uintptr_t)pc);
rsp = (void*)p->uc_mcontext.arm_r8;
rsp = (void*)p->uc_mcontext.regs[10+_SP];
}
#endif
x64name = getAddrFunctionName(x64pc);
@@ -755,12 +778,12 @@ exit(-1);
#ifdef DYNAREC
uint32_t hash = 0;
if(db)
hash = X31_hash_code(db->x86_addr, db->x86_size);
hash = X31_hash_code(db->x64_addr, db->x64_size);
printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p), for accessing %p (code=%d/prot=%x), db=%p(%p:%p/%p:%p/%s:%s, hash:%x/%x)",
GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp, addr, info->si_code,
prot, db, db?db->block:0, db?(db->block+db->size):0,
db?db->x86_addr:0, db?(db->x86_addr+db->x86_size):0,
getAddrFunctionName((uintptr_t)(db?db->x86_addr:0)), (db?db->need_test:0)?"need_stest":"clean", db?db->hash:0, hash);
db?db->x64_addr:0, db?(db->x64_addr+db->x64_size):0,
getAddrFunctionName((uintptr_t)(db?db->x64_addr:0)), (db?db->need_test:0)?"need_stest":"clean", db?db->hash:0, hash);
#else
printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p), for accessing %p (code=%d)", GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp, addr, info->si_code);
#endif
@@ -788,7 +811,7 @@ void my_sigactionhandler(int32_t sig, siginfo_t* info, void * ucntx)
{
#ifdef DYNAREC
ucontext_t *p = (ucontext_t *)ucntx;
void * pc = (void*)p->uc_mcontext.arm_pc;
void * pc = (void*)p->uc_mcontext.pc;
dynablock_t* db = FindDynablockFromNativeAddress(pc);
#else
void* db = NULL;
@@ -898,7 +921,7 @@ int EXPORT my_syscall_rt_sigaction(x64emu_t* emu, int signum, const x64_sigactio
struct kernel_sigaction newact = {0};
struct kernel_sigaction old = {0};
if(act) {
printf_log(LOG_DEBUG, " New (kernel) action flags=0x%x mask=0x%x\n", act->sa_flags, *(uint32_t*)&act->sa_mask);
printf_log(LOG_DEBUG, " New (kernel) action flags=0x%x mask=0x%lx\n", act->sa_flags, *(uint64_t*)&act->sa_mask);
memcpy(&newact.sa_mask, &act->sa_mask, (sigsetsize>16)?16:sigsetsize);
newact.sa_flags = act->sa_flags&~0x04000000; // No sa_restorer...
if(act->sa_flags&0x04) {
@@ -1133,15 +1156,15 @@ void init_signal_helper(box64context_t* context)
for(int i=0; i<MAX_SIGNAL; ++i) {
context->signals[i] = 1; // SIG_DFL
}
struct sigaction action;
struct sigaction action = {0};
action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
action.sa_sigaction = my_box86signalhandler;
action.sa_sigaction = my_box64signalhandler;
sigaction(SIGSEGV, &action, NULL);
action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
action.sa_sigaction = my_box86signalhandler;
action.sa_sigaction = my_box64signalhandler;
sigaction(SIGBUS, &action, NULL);
action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
action.sa_sigaction = my_box86signalhandler;
action.sa_sigaction = my_box64signalhandler;
sigaction(SIGILL, &action, NULL);
pthread_once(&sigstack_key_once, sigstack_key_alloc);
+46 -32
View File
@@ -56,6 +56,8 @@ typedef struct x64_unwind_buff_s {
void *__pad[4];
} x64_unwind_buff_t __attribute__((__aligned__));
typedef void(*vFv_t)();
KHASH_MAP_INIT_INT64(threadstack, threadstack_t*)
KHASH_MAP_INIT_INT64(cancelthread, __pthread_unwind_buf_t*)
@@ -152,8 +154,10 @@ typedef struct emuthread_s {
static void emuthread_destroy(void* p)
{
emuthread_t *et = (emuthread_t*)p;
FreeX64Emu(&et->emu);
free(et);
if(et) {
FreeX64Emu(&et->emu);
free(et);
}
}
static pthread_key_t thread_key;
@@ -258,6 +262,14 @@ EXPORT int my_pthread_attr_setstack(x64emu_t* emu, void* attr, void* stackaddr,
return pthread_attr_setstacksize(attr, stacksize);
}
EXPORT int my_pthread_attr_setstacksize(x64emu_t* emu, void* attr, size_t stacksize)
{
//aarch64 have an PTHREAD_STACK_MIN of 131072 instead of 16384 on x86_64!
if(stacksize<PTHREAD_STACK_MIN)
stacksize = PTHREAD_STACK_MIN;
return pthread_attr_setstacksize(attr, stacksize);
}
EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_routine, void* arg)
{
int stacksize = 2*1024*1024; //default stack size is 2Mo
@@ -289,7 +301,7 @@ EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_rou
et->fnc = (uintptr_t)start_routine;
et->arg = arg;
#ifdef DYNAREC
if(box86_dynarec) {
if(box64_dynarec) {
// pre-creation of the JIT code for the entry point of the thread
dynablock_t *current = NULL;
DBGetBlock(emu, (uintptr_t)start_routine, 1, &current);
@@ -407,28 +419,6 @@ GO(27) \
GO(28) \
GO(29)
// once_callback
#define GO(A) \
static uintptr_t my_once_callback_fct_##A = 0; \
static void my_once_callback_##A() \
{ \
RunFunction(my_context, my_once_callback_fct_##A, 0, 0);\
}
SUPER()
#undef GO
static void* findonce_callbackFct(void* fct)
{
if(!fct) return fct;
if(GetNativeFnc((uintptr_t)fct)) return GetNativeFnc((uintptr_t)fct);
#define GO(A) if(my_once_callback_fct_##A == (uintptr_t)fct) return my_once_callback_##A;
SUPER()
#undef GO
#define GO(A) if(my_once_callback_fct_##A == 0) {my_once_callback_fct_##A = (uintptr_t)fct; return my_once_callback_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for pthread once_callback callback\n");
return NULL;
}
// key_destructor
#define GO(A) \
static uintptr_t my_key_destructor_fct_##A = 0; \
@@ -476,9 +466,25 @@ static void* findcleanup_routineFct(void* fct)
#undef SUPER
// once_callback
// Don't use a "GO" scheme, once callback are only called once by definition
static __thread uintptr_t my_once_callback_fct = 0;
static void my_once_callback()
{
if(my_once_callback_fct) {
if(GetNativeFnc((uintptr_t)my_once_callback_fct)) {
vFv_t f = (vFv_t)GetNativeFnc((uintptr_t)my_once_callback_fct);
f();
return;
}
RunFunction(my_context, my_once_callback_fct, 0, 0);
}
}
int EXPORT my_pthread_once(x64emu_t* emu, void* once, void* cb)
{
return pthread_once(once, findonce_callbackFct(cb));
my_once_callback_fct = (uintptr_t)cb;
return pthread_once(once, my_once_callback);
}
EXPORT int my___pthread_once(x64emu_t* emu, void* once, void* cb) __attribute__((alias("my_pthread_once")));
@@ -667,8 +673,6 @@ static kh_mutex_t* unaligned_mutex = NULL;
pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m)
{
if(!(((uintptr_t)m)&3))
return m;
khint_t k = kh_get(mutex, unaligned_mutex, (uintptr_t)m);
if(k!=kh_end(unaligned_mutex))
return kh_value(unaligned_mutex, k);
@@ -680,8 +684,6 @@ pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m)
}
EXPORT int my_pthread_mutex_destroy(pthread_mutex_t *m)
{
if(!(((uintptr_t)m)&3))
return pthread_mutex_destroy(m);
khint_t k = kh_get(mutex, unaligned_mutex, (uintptr_t)m);
if(k!=kh_end(unaligned_mutex)) {
pthread_mutex_t *n = kh_value(unaligned_mutex, k);
@@ -728,8 +730,10 @@ EXPORT int my_pthread_mutex_unlock(pthread_mutex_t *m)
static void emujmpbuf_destroy(void* p)
{
emu_jmpbuf_t *ej = (emu_jmpbuf_t*)p;
free(ej->jmpbuf);
free(ej);
if(ej) {
free(ej->jmpbuf);
free(ej);
}
}
static pthread_key_t jmpbuf_key;
@@ -774,4 +778,14 @@ void fini_pthread_helper(box64context_t* context)
);
kh_destroy(mutex, unaligned_mutex);
#endif
emu_jmpbuf_t *ejb = (emu_jmpbuf_t*)pthread_getspecific(jmpbuf_key);
if(ejb) {
emujmpbuf_destroy(ejb);
pthread_setspecific(jmpbuf_key, NULL);
}
emuthread_t *et = (emuthread_t*)pthread_getspecific(thread_key);
if(et) {
emuthread_destroy(et);
pthread_setspecific(thread_key, NULL);
}
}
+89 -5
View File
@@ -25,11 +25,20 @@
#include "x64run.h"
box64context_t *my_context = NULL;
int box64_log = LOG_NONE;
int box64_log = LOG_INFO; //LOG_NONE;
int box64_nobanner = 0;
int box64_dynarec_log = LOG_INFO; //LOG_NONE;
int box64_dynarec_log = LOG_NONE;
int box64_pagesize;
#ifdef DYNAREC
int box64_dynarec = 1;
int box64_dynarec_dump = 0;
int box64_dynarec_forced = 0;
int box64_dynarec_largest = 0;
uintptr_t box64_nodynarec_start = 0;
uintptr_t box64_nodynarec_end = 0;
#else //DYNAREC
int box64_dynarec = 0;
#endif
int dlsym_error = 0;
int trace_xmm = 0;
int trace_emm = 0;
@@ -128,6 +137,61 @@ void LoadLogEnv()
if(!box64_nobanner)
printf_log(LOG_INFO, "Debug level is %d\n", box64_log);
}
#ifdef DYNAREC
p = getenv("BOX64_DYNAREC_DUMP");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[1]<='1')
box64_dynarec_dump = p[0]-'0';
}
if (box64_dynarec_dump) printf_log(LOG_INFO, "Dynarec blocks are dumped%s\n", (box64_dynarec_dump>1)?" in color":"");
}
p = getenv("BOX64_DYNAREC_LOG");
if(p) {
if(strlen(p)==1) {
if((p[0]>='0'+LOG_NONE) && (p[0]<='0'+LOG_DUMP))
box64_dynarec_log = p[0]-'0';
} else {
if(!strcasecmp(p, "NONE"))
box64_dynarec_log = LOG_NONE;
else if(!strcasecmp(p, "INFO"))
box64_dynarec_log = LOG_INFO;
else if(!strcasecmp(p, "DEBUG"))
box64_dynarec_log = LOG_DEBUG;
else if(!strcasecmp(p, "VERBOSE"))
box64_dynarec_log = LOG_DUMP;
}
printf_log(LOG_INFO, "Dynarec log level is %d\n", box64_dynarec_log);
}
p = getenv("BOX64_DYNAREC");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[1]<='1')
box64_dynarec = p[0]-'0';
}
printf_log(LOG_INFO, "Dynarec is %s\n", box64_dynarec?"On":"Off");
}
p = getenv("BOX64_DYNAREC_FORCED");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[1]<='1')
box64_dynarec_forced = p[0]-'0';
}
if(box64_dynarec_forced)
printf_log(LOG_INFO, "Dynarec is Forced on all addresses\n");
}
p = getenv("BOX64_NODYNAREC");
if(p) {
if (strchr(p,'-')) {
if(sscanf(p, "%ld-%ld", &box64_nodynarec_start, &box64_nodynarec_end)!=2) {
if(sscanf(p, "0x%lX-0x%lX", &box64_nodynarec_start, &box64_nodynarec_end)!=2)
sscanf(p, "%lx-%lx", &box64_nodynarec_start, &box64_nodynarec_end);
}
printf_log(LOG_INFO, "No Dynablock creation that start in %p - %p range\n", (void*)box64_nodynarec_start, (void*)box64_nodynarec_end);
}
}
#endif
#ifdef HAVE_TRACE
p = getenv("BOX64_TRACE_XMM");
if(p) {
@@ -149,6 +213,17 @@ void LoadLogEnv()
start_cnt = strtoll(p, &p2, 10);
printf_log(LOG_INFO, "Will start trace only after %lu instructions\n", start_cnt);
}
#ifdef DYNAREC
p = getenv("BOX64_DYNAREC_TRACE");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[1]<='0'+1)
box64_dynarec_trace = p[0]-'0';
if(box64_dynarec_trace)
printf_log(LOG_INFO, "Dynarec generated code will also print a trace\n");
}
}
#endif
#endif
// grab BOX64_TRACE_FILE envvar, and change %pid to actual pid is present in the name
openFTrace();
@@ -345,6 +420,11 @@ void PrintHelp() {
printf(" BOX64_LD_LIBRARY_PATH is the box64 version LD_LIBRARY_PATH (default is '.:lib')\n");
printf(" BOX64_LOG with 0/1/2/3 or NONE/INFO/DEBUG/DUMP to set the printed debug info\n");
printf(" BOX64_NOBANNER with 0/1 to enable/disable the printing of box64 version and build at start\n");
#ifdef DYNAREC
printf(" BOX64_DYNAREC_LOG with 0/1/2/3 or NONE/INFO/DEBUG/DUMP to set the printed dynarec info\n");
printf(" BOX64_DYNAREC with 0/1 to disable or enable Dynarec (On by default)\n");
printf(" BOX64_NODYNAREC with address interval (0x1234-0x4567) to forbid dynablock creation in the interval specified\n");
#endif
#ifdef HAVE_TRACE
printf(" BOX64_TRACE with 1 to enable x86_64 execution trace\n");
printf(" or with XXXXXX-YYYYYY to enable x86_64 execution trace only between address\n");
@@ -353,6 +433,9 @@ void PrintHelp() {
printf(" BOX64_TRACE_EMM with 1 to enable dump of MMX registers along with regular registers\n");
printf(" BOX64_TRACE_XMM with 1 to enable dump of SSE registers along with regular registers\n");
printf(" BOX64_TRACE_START with N to enable trace after N instructions\n");
#ifdef DYNAREC
printf(" BOX64_DYNAREC_TRACE with 0/1 to disable or enable Trace on generated code too\n");
#endif
#endif
printf(" BOX64_TRACE_FILE with FileName to redirect logs in a file");
printf(" BOX64_DLSYM_ERROR with 1 to log dlsym errors\n");
@@ -765,7 +848,7 @@ int main(int argc, const char **argv, const char **env) {
if(ElfCheckIfUseTCMallocMinimal(elf_header)) {
if(!box64_tcmalloc_minimal) {
// need to reload with tcmalloc_minimal as a LD_PRELOAD!
printf_log(LOG_INFO, "BOX86: tcmalloc_minimal.so.4 used, reloading box64 with the lib preladed\n");
printf_log(LOG_INFO, "BOX64: tcmalloc_minimal.so.4 used, reloading box64 with the lib preladed\n");
// need to get a new envv variable. so first count it and check if LD_PRELOAD is there
int preload=(getenv("LD_PRELOAD"))?1:0;
int nenv = 0;
@@ -805,7 +888,7 @@ int main(int argc, const char **argv, const char **env) {
if(execve(newargv[0], newargv, newenv)<0)
printf_log(LOG_NONE, "Failed to relaunch, error is %d/%s\n", errno, strerror(errno));
} else {
printf_log(LOG_INFO, "BOX86: Using tcmalloc_minimal.so.4, and it's in the LD_PRELOAD command\n");
printf_log(LOG_INFO, "BOX64: Using tcmalloc_minimal.so.4, and it's in the LD_PRELOAD command\n");
}
}
// get and alloc stack size and align
@@ -850,7 +933,8 @@ int main(int argc, const char **argv, const char **env) {
if(ld_preload.size) {
for (int i=0; i<ld_preload.size; ++i) {
if(AddNeededLib(NULL, NULL, 0, ld_preload.paths[i], my_context, emu)) {
printf_log(LOG_INFO, "Warning, cannot pre-load lib: \"%s\"\n", ld_preload.paths[i]);
if(!strstr(ld_preload.paths[i], "vgpreload_"))
printf_log(LOG_INFO, "Warning, cannot pre-load lib: \"%s\"\n", ld_preload.paths[i]);
}
}
}
+98 -32
View File
@@ -5,7 +5,7 @@
#include <dlfcn.h>
#include <pthread.h>
//#include "custommem.h"
#include "custommem.h"
#include "bridge.h"
#include "bridge_private.h"
#include "khash.h"
@@ -37,7 +37,9 @@ typedef struct bridge_s {
brick_t* NewBrick()
{
brick_t* ret = (brick_t*)calloc(1, sizeof(brick_t));
posix_memalign((void**)&ret->b, box64_pagesize, NBRICK*sizeof(onebridge_t));
if(posix_memalign((void**)&ret->b, box64_pagesize, NBRICK*sizeof(onebridge_t))) {
printf_log(LOG_NONE, "Warning, cannot allocate 0x%lx aligned bytes for bridge, will probably crash later\n", NBRICK*sizeof(onebridge_t));
}
return ret;
}
@@ -70,41 +72,59 @@ void FreeBridge(bridge_t** bridge)
*bridge = NULL;
}
uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N)
#ifdef HAVE_TRACE
void addBridgeName(void* addr, const char* name);
#endif
uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name)
{
pthread_mutex_lock(&bridge->mutex);
brick_t *b = bridge->last;
if(b->sz == NBRICK) {
b->next = NewBrick();
b = b->next;
bridge->last = b;
}
brick_t *b = NULL;
int sz = -1;
#ifdef DYNAREC
int prot = 0;
if(box64_dynarec) {
prot=(getProtection((uintptr_t)b->b)&PROT_DYNAREC)?1:0;
if(prot)
unprotectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
addDBFromAddressRange((uintptr_t)&b->b[b->sz].CC, sizeof(onebridge_t));
}
do {
#endif
pthread_mutex_lock(&bridge->mutex);
b = bridge->last;
if(b->sz == NBRICK) {
b->next = NewBrick();
b = b->next;
bridge->last = b;
}
#ifdef DYNAREC
sz = b->sz;
pthread_mutex_unlock(&bridge->mutex);
if(box64_dynarec) {
prot=(getProtection((uintptr_t)b->b)&PROT_DYNAREC)?1:0;
if(prot)
unprotectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
addDBFromAddressRange((uintptr_t)&b->b[b->sz].CC, sizeof(onebridge_t));
}
} while(sz!=b->sz); // this while loop if someone took the slot when the bridge mutex was unlocked doing memory protection managment
pthread_mutex_lock(&bridge->mutex);
#endif
b->b[b->sz].CC = 0xCC;
b->b[b->sz].S = 'S'; b->b[b->sz].C='C';
b->b[b->sz].w = w;
b->b[b->sz].f = (uintptr_t)fnc;
b->b[b->sz].C3 = N?0xC2:0xC3;
b->b[b->sz].N = N;
b->sz++;
b->b[sz].CC = 0xCC;
b->b[sz].S = 'S'; b->b[sz].C='C';
b->b[sz].w = w;
b->b[sz].f = (uintptr_t)fnc;
b->b[sz].C3 = N?0xC2:0xC3;
b->b[sz].N = N;
// add bridge to map, for fast recovery
int ret;
khint_t k = kh_put(bridgemap, bridge->bridgemap, (uintptr_t)fnc, &ret);
kh_value(bridge->bridgemap, k) = (uintptr_t)&b->b[sz].CC;
pthread_mutex_unlock(&bridge->mutex);
#ifdef DYNAREC
if(box64_dynarec && prot)
protectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
#endif
// add bridge to map, for fast recovery
int ret;
khint_t k = kh_put(bridgemap, bridge->bridgemap, (uintptr_t)fnc, &ret);
kh_value(bridge->bridgemap, k) = (uintptr_t)&b->b[b->sz].CC;
pthread_mutex_unlock(&bridge->mutex);
#ifdef HAVE_TRACE
if(name)
addBridgeName(fnc, name);
#endif
return (uintptr_t)&b->b[b->sz++].CC;
return (uintptr_t)&b->b[sz].CC;
}
uintptr_t CheckBridged(bridge_t* bridge, void* fnc)
@@ -116,13 +136,13 @@ uintptr_t CheckBridged(bridge_t* bridge, void* fnc)
return kh_value(bridge->bridgemap, k);
}
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N)
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name)
{
if(!fnc && w)
return 0;
uintptr_t ret = CheckBridged(bridge, fnc);
if(!ret)
ret = AddBridge(bridge, w, fnc, N);
ret = AddBridge(bridge, w, fnc, N, name);
return ret;
}
@@ -132,13 +152,14 @@ uintptr_t AddAutomaticBridge(x64emu_t* emu, bridge_t* bridge, wrapper_t w, void*
return 0;
uintptr_t ret = CheckBridged(bridge, fnc);
if(!ret)
ret = AddBridge(bridge, w, fnc, N);
ret = AddBridge(bridge, w, fnc, N, NULL);
if(!hasAlternate(fnc)) {
printf_log(LOG_DEBUG, "Adding AutomaticBridge for %p to %p\n", fnc, (void*)ret);
addAlternate(fnc, (void*)ret);
#ifdef DYNAREC
// now, check if dynablock at native address exist
DBAlternateBlock(emu, (uintptr_t)fnc, ret);
if(box64_dynarec)
DBAlternateBlock(emu, (uintptr_t)fnc, ret);
#endif
}
return ret;
@@ -180,6 +201,36 @@ void* GetNativeFncOrFnc(uintptr_t fnc)
return (void*)b->f;
}
#ifdef HAVE_TRACE
KHASH_MAP_INIT_INT64(bridgename, const char*)
static kh_bridgename_t *bridgename;
void initBridgeName()
{
bridgename = kh_init(bridgename);
}
void finiBridgeName()
{
kh_destroy(bridgename, bridgename);
bridgename = NULL;
}
void addBridgeName(void* addr, const char* name)
{
int ret;
khint_t k = kh_put(bridgename, bridgename, (uintptr_t)addr, &ret);
if(!ret) // already there
return;
kh_value(bridgename, k) = name;
}
const char* getBridgeName(void* addr)
{
khint_t k = kh_get(bridgename, bridgename, (uintptr_t)addr);
if(k!=kh_end(bridgename))
return kh_value(bridgename, k);
return NULL;
}
#endif
// Alternate address handling
KHASH_MAP_INIT_INT64(alternate, void*)
static kh_alternate_t *my_alternates = NULL;
@@ -218,3 +269,18 @@ void cleanAlternate() {
my_alternates = NULL;
}
}
void init_bridge_helper()
{
#ifdef HAVE_TRACE
initBridgeName();
#endif
}
void fini_bridge_helper()
{
cleanAlternate();
#ifdef HAVE_TRACE
finiBridgeName();
#endif
}
+861
View File
@@ -1,7 +1,17 @@
#() vFE
#() vFv
#() vFi
#() vFu
#() vFf
#() vFd
#() vFp
#() vFS
#() cFv
#() cFi
#() cFu
#() cFf
#() cFp
#() wFp
#() iFE
#() iFv
#() iFi
@@ -10,77 +20,921 @@
#() iFd
#() iFL
#() iFp
#() iFS
#() IFf
#() IFd
#() IFp
#() WFi
#() WFp
#() uFv
#() uFi
#() uFu
#() uFd
#() uFp
#() UFv
#() UFp
#() UFV
#() fFi
#() fFf
#() fFp
#() dFi
#() dFu
#() dFd
#() dFp
#() lFE
#() lFi
#() lFp
#() LFv
#() LFL
#() LFp
#() pFE
#() pFv
#() pFi
#() pFu
#() pFL
#() pFp
#() HFi
#() HFp
#() vFEp
#() vFii
#() vFiu
#() vFif
#() vFid
#() vFip
#() vFWW
#() vFui
#() vFuu
#() vFuf
#() vFud
#() vFup
#() vFfi
#() vFff
#() vFfp
#() vFdd
#() vFpi
#() vFpu
#() vFpf
#() vFpL
#() vFpp
#() vFpS
#() vFSi
#() cFpp
#() iFEp
#() iFii
#() iFiu
#() iFip
#() iFIi
#() iFui
#() iFuu
#() iFup
#() iFUU
#() iFli
#() iFLL
#() iFLp
#() iFpw
#() iFpi
#() iFpI
#() iFpC
#() iFpu
#() iFpf
#() iFpd
#() iFpl
#() iFpL
#() iFpp
#() iFpO
#() iFSi
#() IFEp
#() IFpu
#() CFui
#() CFpi
#() CFpu
#() uFEp
#() uFiu
#() uFui
#() uFuu
#() uFup
#() uFUp
#() uFpi
#() uFpu
#() uFpU
#() uFpp
#() UFEp
#() UFUp
#() UFpp
#() fFif
#() fFfi
#() fFff
#() fFfp
#() fFpp
#() dFid
#() dFdi
#() dFdd
#() dFdp
#() dFpp
#() LFpi
#() LFpL
#() LFpp
#() pFEp
#() pFii
#() pFip
#() pFui
#() pFuu
#() pFup
#() pFlp
#() pFLL
#() pFpi
#() pFpC
#() pFpu
#() pFpU
#() pFpL
#() pFpp
#() pFpV
#() pFSi
#() HFpi
#() vFEpi
#() vFEpu
#() vFEpp
#() vFEpV
#() vFiii
#() vFiip
#() vFiui
#() vFiuu
#() vFiup
#() vFiff
#() vFidd
#() vFipi
#() vFipu
#() vFipp
#() vFuii
#() vFuiI
#() vFuiu
#() vFuif
#() vFuid
#() vFuip
#() vFuui
#() vFuuu
#() vFuuf
#() vFuud
#() vFuup
#() vFuff
#() vFudd
#() vFupi
#() vFfff
#() vFfpp
#() vFddd
#() vFdpp
#() vFLpp
#() vFpii
#() vFpiu
#() vFpif
#() vFpid
#() vFpip
#() vFpui
#() vFpuI
#() vFpuu
#() vFpup
#() vFppi
#() vFppu
#() vFppp
#() iFEiw
#() iFEip
#() iFEWW
#() iFEup
#() iFEpi
#() iFEpL
#() iFEpp
#() iFEpV
#() iFESp
#() iFiwC
#() iFiii
#() iFiiu
#() iFiip
#() iFiiO
#() iFiuu
#() iFiLN
#() iFipu
#() iFipp
#() iFuuu
#() iFuup
#() iFuff
#() iFfff
#() iFLip
#() iFLpp
#() iFpii
#() iFpiu
#() iFpiL
#() iFpip
#() iFpIi
#() iFpui
#() iFpuu
#() iFpuU
#() iFpuL
#() iFpup
#() iFpfu
#() iFpff
#() iFpli
#() iFplp
#() iFpLp
#() iFppi
#() iFppI
#() iFppu
#() iFppd
#() iFppL
#() iFppp
#() iFppV
#() iFSpL
#() IFiIi
#() IFpIi
#() IFppi
#() IFSIi
#() uFEpW
#() uFEpu
#() uFEpU
#() uFipu
#() uFuip
#() uFuui
#() uFuuu
#() uFuup
#() uFupu
#() uFupp
#() uFpiu
#() uFpip
#() uFpLp
#() uFppi
#() uFppu
#() UFppi
#() fFuii
#() fFfff
#() fFffp
#() dFddd
#() dFddp
#() dFppi
#() dFppp
#() lFipi
#() lFipL
#() lFlpi
#() lFppi
#() lFSpl
#() LFLLi
#() LFLLI
#() LFLpu
#() LFLpL
#() LFpii
#() LFppi
#() LFSpL
#() pFEip
#() pFEpi
#() pFEpp
#() pFipi
#() pFipp
#() pFIpi
#() pFuii
#() pFupi
#() pFUpi
#() pFpii
#() pFpiu
#() pFpiL
#() pFpip
#() pFpCC
#() pFpui
#() pFpuu
#() pFpuL
#() pFpup
#() pFpUp
#() pFplp
#() pFpLu
#() pFpLL
#() pFpLp
#() pFppi
#() pFppu
#() pFppf
#() pFppL
#() pFppp
#() pFpOM
#() pFSpl
#() vFEipV
#() vFEpip
#() vFEpup
#() vFEppp
#() vFiiii
#() vFiiip
#() vFiuip
#() vFiuuu
#() vFiupu
#() vFiupV
#() vFifff
#() vFiddd
#() vFipii
#() vFipup
#() vFippp
#() vFuiii
#() vFuiip
#() vFuiui
#() vFuiuu
#() vFuiup
#() vFuifi
#() vFuiff
#() vFuidd
#() vFuipi
#() vFuipu
#() vFuipp
#() vFuuii
#() vFuuiu
#() vFuuip
#() vFuuui
#() vFuuuu
#() vFuuuf
#() vFuuud
#() vFuuup
#() vFuupi
#() vFuupp
#() vFufff
#() vFuddd
#() vFupii
#() vFuppi
#() vFffff
#() vFdddd
#() vFpiii
#() vFpiip
#() vFpipp
#() vFpupp
#() vFpdii
#() vFpddd
#() vFppii
#() vFppip
#() vFppui
#() vFppup
#() vFpppi
#() vFpppu
#() vFpppp
#() cFpiii
#() iFEiip
#() iFEiiN
#() iFEipp
#() iFEipV
#() iFEupp
#() iFEpip
#() iFEppi
#() iFEppL
#() iFEppp
#() iFEppV
#() iFEpOu
#() iFiiii
#() iFiiiu
#() iFiuii
#() iFipii
#() iFippi
#() iFippp
#() iFuipp
#() iFuuff
#() iFuppp
#() iFpiii
#() iFpiiu
#() iFpiid
#() iFpiiL
#() iFpiip
#() iFpiup
#() iFpipi
#() iFpipp
#() iFpCCC
#() iFpWWu
#() iFpuip
#() iFpuui
#() iFpuuu
#() iFpuup
#() iFpuLL
#() iFpuLp
#() iFpupV
#() iFppii
#() iFppiu
#() iFppiL
#() iFppip
#() iFppuw
#() iFppui
#() iFppuu
#() iFppup
#() iFpplp
#() iFppLp
#() iFpppi
#() iFpppu
#() iFpppL
#() iFpppp
#() IFEpIi
#() IFSIii
#() uFifff
#() uFuuuu
#() uFpipp
#() uFpCCC
#() uFpuip
#() uFpuuu
#() uFpppi
#() UFpipp
#() lFipiI
#() lFipLI
#() lFipLl
#() LFpuuu
#() LFpLLp
#() LFpLpp
#() LFppii
#() LFppLp
#() pFEipp
#() pFEupp
#() pFEpii
#() pFEpip
#() pFEppi
#() pFEppL
#() pFEppp
#() pFiiiu
#() pFiiup
#() pFippL
#() pFuiii
#() pFpiii
#() pFpiip
#() pFpiLL
#() pFpipi
#() pFpipp
#() pFpCWp
#() pFpCuW
#() pFpCuu
#() pFpuii
#() pFpuWp
#() pFpuuu
#() pFpuup
#() pFpupi
#() pFplpp
#() pFppii
#() pFppiL
#() pFppip
#() pFppuu
#() pFppuL
#() pFppup
#() pFppLL
#() pFpppi
#() pFpppu
#() pFpppL
#() pFpppp
#() pFSppi
#() vFEpuup
#() vFEpLLp
#() vFEpppp
#() vFiiiii
#() vFiiiiu
#() vFiiuup
#() vFiipii
#() vFiuiip
#() vFiuipi
#() vFiuuuu
#() vFiffff
#() vFidddd
#() vFilill
#() vFipipu
#() vFipipp
#() vFipupi
#() vFuiiii
#() vFuiiiu
#() vFuiiip
#() vFuiiup
#() vFuiIII
#() vFuiuii
#() vFuiuiu
#() vFuiuip
#() vFuiuuu
#() vFuiuup
#() vFuiupi
#() vFuiupu
#() vFuifff
#() vFuiddd
#() vFuipii
#() vFuipip
#() vFuipup
#() vFuippp
#() vFuuiii
#() vFuuiui
#() vFuuiuu
#() vFuuiup
#() vFuuipi
#() vFuuipu
#() vFuuipp
#() vFuuuii
#() vFuuuiu
#() vFuuuip
#() vFuuuui
#() vFuuuuu
#() vFuuuup
#() vFuupii
#() vFuffff
#() vFudddd
#() vFupupi
#() vFuppip
#() vFupppp
#() vFfffff
#() vFddddp
#() vFpiiii
#() vFpipii
#() vFpuipp
#() vFpddii
#() vFppiii
#() vFppiip
#() vFppWui
#() vFpppii
#() vFppppi
#() vFppppp
#() iFEippp
#() iFEpipi
#() iFEpipp
#() iFEpipV
#() iFEpLpp
#() iFEpLpV
#() iFEppip
#() iFEppiV
#() iFEpppp
#() iFEpppV
#() iFiiupp
#() iFipiii
#() iFipppi
#() iFipppp
#() iFpiiii
#() iFpiiip
#() iFpiiuu
#() iFpiipi
#() iFpiipp
#() iFpipii
#() iFpippi
#() iFpippp
#() iFpCCCC
#() iFpuuui
#() iFpuuLL
#() iFpuupp
#() iFppiip
#() iFppiup
#() iFppipi
#() iFppipp
#() iFppupi
#() iFpppii
#() iFpppiL
#() iFpppip
#() iFpppLi
#() iFppppi
#() iFppppp
#() IFppIII
#() uFEppuu
#() uFiuuuu
#() uFuiiiu
#() uFpCCCC
#() uFpuuuu
#() uFppiip
#() uFppppp
#() LFLpppp
#() LFpLLLp
#() LFpLppL
#() LFppppp
#() pFEpiii
#() pFEpipL
#() pFEpipp
#() pFEpupp
#() pFEppii
#() pFEppip
#() pFEpppp
#() pFuiiiu
#() pFuiipp
#() pFpiiuu
#() pFpiipp
#() pFpippp
#() pFpCuup
#() pFpCppp
#() pFpuiii
#() pFpuiip
#() pFpuWWW
#() pFpuuWW
#() pFpuuup
#() pFppipi
#() pFppipp
#() pFppuuu
#() pFppuup
#() pFppLLp
#() pFpppip
#() pFpppuu
#() pFpppup
#() pFppppi
#() pFppppp
#() vFEiiipp
#() vFEpLLpp
#() vFiiiiii
#() vFiiiuil
#() vFiuippp
#() vFiffiff
#() vFiddidd
#() vFuiiiii
#() vFuiiiip
#() vFuiiuii
#() vFuiiuup
#() vFuiuiii
#() vFuiuiip
#() vFuiuiuu
#() vFuiuuip
#() vFuiuuuu
#() vFuiupii
#() vFuiupiu
#() vFuiffff
#() vFuidddd
#() vFuipiup
#() vFuuiiii
#() vFuuiuii
#() vFuuiuiu
#() vFuuiuup
#() vFuuippp
#() vFuuuiup
#() vFuuuipi
#() vFuuuipp
#() vFuuuuii
#() vFuuuuip
#() vFuuuuuu
#() vFuuuuff
#() vFuuuppi
#() vFuuuppp
#() vFuuffff
#() vFuudddd
#() vFuffiip
#() vFufffff
#() vFuddiip
#() vFupupip
#() vFuppppp
#() vFffffff
#() vFdddddd
#() vFpipipV
#() vFpipppi
#() vFpdddii
#() vFppiiii
#() vFppiipi
#() vFppupii
#() vFpppppp
#() iFEiippi
#() iFEpilpV
#() iFEpippi
#() iFEpuppp
#() iFEppppp
#() iFiiiiii
#() iFiiiiip
#() iFiuiipi
#() iFuppipp
#() iFuppppp
#() iFpiiiii
#() iFpiiipp
#() iFpiippp
#() iFpipppp
#() iFpupuui
#() iFppiiuu
#() iFppIppp
#() iFppuiii
#() iFppuiiL
#() iFppuIII
#() iFppuupp
#() iFppupip
#() iFpppiuu
#() iFpppipi
#() iFpppipp
#() iFppppii
#() iFpppppi
#() iFpppppL
#() iFpppppp
#() uFpippup
#() UFpippup
#() LFSpLiip
#() pFEpippp
#() pFEpuipp
#() pFEpuupp
#() pFEpuppp
#() pFEppppp
#() pFiCiiCi
#() pFpiiiiu
#() pFpippip
#() pFpCuuCC
#() pFpCuuWW
#() pFpCuuup
#() pFpuuuuu
#() pFppiiii
#() pFpppppp
#() pFSpiiii
#() vFiiiiiip
#() vFiiiiuup
#() vFiiupuip
#() vFiiffffp
#() vFiupuuup
#() vFuiiiiii
#() vFuiiiuip
#() vFuiiiuup
#() vFuiuiiii
#() vFuiuiiip
#() vFuiuiiuu
#() vFuiupiiu
#() vFuipiiii
#() vFuipffff
#() vFuipdddd
#() vFuuiiiii
#() vFuuiiiip
#() vFuuiiiui
#() vFuuiiiuu
#() vFuuiiuup
#() vFuuiuiii
#() vFuuipppp
#() vFuuuiiii
#() vFuuuiiip
#() vFuuuiuii
#() vFuuuiupi
#() vFuuuuiip
#() vFuuuuuuu
#() vFuuuufff
#() vFuuuffff
#() vFuuudddd
#() vFuuffiip
#() vFuuddiip
#() vFuffffff
#() vFudddddd
#() vFpipipii
#() vFpddiidd
#() vFppiiipi
#() vFpppiiii
#() vFppppipi
#() iFEpLiLpV
#() iFEppLpIi
#() iFEpppiiu
#() iFEpppppp
#() iFiiiiiip
#() iFpiiuuiu
#() iFpiupiii
#() iFpuuiuui
#() iFpupuuui
#() iFpuppppp
#() iFppiiuui
#() iFppiipii
#() iFppipipi
#() iFppipppp
#() iFpppiiii
#() iFpppiiuu
#() iFpppiipi
#() iFpppiuwu
#() iFppppiii
#() iFppppdpi
#() iFppppppp
#() uFuippppp
#() pFEppppip
#() pFifffppp
#() pFuupupup
#() pFpCuwwWW
#() pFpCuWCCC
#() pFpCuuwwp
#() pFpCuuuuu
#() pFppuuppp
#() pFppppuuu
#() pFpppppuu
#() pFppppppp
#() vFiiiiuuip
#() vFiupuiuup
#() vFiupuuuup
#() vFuiiiiiii
#() vFuiiiiuup
#() vFuiiipiup
#() vFuiuiiiii
#() vFuiuiiiip
#() vFuuiiiiii
#() vFuuiiiuip
#() vFuuiiiuup
#() vFuuiiuupp
#() vFuuiuiiii
#() vFuuiuiiip
#() vFuuuiiiii
#() vFuuuiuiii
#() vFuuuipipp
#() vFuuuuuuuu
#() vFuuuuufff
#() vFffffffff
#() vFpippiiuu
#() vFpippiipi
#() vFppiiipii
#() vFppppiipi
#() iFEpippppp
#() iFiiiiiiip
#() iFiiupiupi
#() iFuiifpppp
#() iFpiiiiipi
#() iFpuuiiiii
#() iFpupppppp
#() iFppIIIppp
#() iFpppiippp
#() iFpppipipi
#() iFpppipppp
#() iFppppiipi
#() iFpppppppp
#() uFuipppppp
#() pFuiiiuuuu
#() pFuupupipp
#() pFpCuwwWWu
#() pFpCuuuCup
#() pFpppuuLLu
#() vFuiiiiiiii
#() vFuiiiiiuip
#() vFuiiiiiuup
#() vFuiuiiiiip
#() vFuiupuffup
#() vFuuiiiiiii
#() vFuuiuiiiii
#() vFuuiuiiiip
#() vFuuiuiiuup
#() vFuuuiiiiip
#() vFuuuuuuuuu
#() vFuupiuiuuf
#() vFuffffffff
#() vFffuuuufff
#() vFddddddddd
#() vFpipppiipi
#() vFppiiipiii
#() vFpppppippp
#() iFEpiiiiipi
#() iFiiiiiiiip
#() iFiiiipiiip
#() iFdddpppppp
#() iFpipLpiiip
#() iFppiuiippL
#() iFpppiiuuii
#() iFpppiipiiu
#() iFppppppppp
#() pFEppiiuuLi
#() pFEppuippuu
#() pFpiiiiuuuu
#() pFpCuWCCuuu
#() pFpuuwwWWww
#() pFppiiuuuLL
#() pFppipppppp
#() vFiiiiiiiiiu
#() vFuiiiiiiiii
#() vFuiiiiiiuup
#() vFuiuiiiiuup
#() vFuuiiiiiiii
#() vFuuiiiiiuip
#() vFuuiiiiiuup
#() vFuuiuiiiiip
#() vFuuiuiiiuup
#() vFuuuuuuuiii
#() vFuuuuuuuuuu
#() vFuupiiupuuf
#() vFuffiiffiip
#() vFuddiiddiip
#() vFffffffffff
#() iFiiiiiiiiip
#() iFpuupiuiipp
#() iFppuuiiiiii
#() iFppuuiiuupi
#() iFppppiiuuii
#() pFpCuWCCuuCW
#() pFpuuuwwwwWW
#() pFppuiipuuii
#() pFpppppppppp
#() vFuiiiiiiiiip
#() vFuiiiiiiiuip
#() vFuiiiiiiiuup
#() vFuiuiiiiiuup
#() vFuuiuiiiiuup
#() vFuuuuuuuuuuu
#() vFuuffiiffiip
#() vFuufffffffff
#() vFuuddiiddiip
#() vFuffffffffff
#() vFpipipiipiii
#() vFpipppiiiipi
#() iFEppppiiiiuu
#() iFiiiiiiiiiip
#() iFpipllippppp
#() iFppppiiuuiiL
#() pFEppuiipuuii
#() vFuuiiiiiiiuip
#() vFuuiiiiiiiuup
#() vFuuuuuuuuuuuu
#() vFffffffffffff
#() vFpipppiiiipii
#() vFpippppiiiipi
#() iFEppppiiiiuui
#() iFpipppppppppp
#() iFpppllipppppp
#() iFpppppppppppp
#() pFEppiiuuuipii
#() pFpCuuWWwwCCup
#() pFpuuuWWWWWWWW
#() pFppiiuuuiupLp
#() vFuiiiiiiiiiuup
#() vFuuuuuuuuuuuuu
#() vFuffffffffffff
#() iFddddpppddpppp
#() iFpippuuuiipppp
#() iFpupiiiipppppp
#() pFpCuuwwWWWWuup
#() pFppppppppppppp
#() vFuffiiffiiffiip
#() vFuddiiddiiddiip
#() vFuuiiiiuuiiiiiii
#() vFfffffffffffffff
#() pFpppppppppppppppp
#() vFppuiiiiipuiiiiiiii
#() pFipppppppppppppppppppppp
#defined(HAVE_LD80BITS) DFD
#defined(HAVE_LD80BITS) DFDD
#defined(HAVE_LD80BITS) DFDp
@@ -88,4 +942,11 @@
#!defined(HAVE_LD80BITS) KFKK
#!defined(HAVE_LD80BITS) KFKp
#() iFEv -> iFE
#() lFEv -> lFE
#() pFEv -> pFE
#() pFppv -> pFpp
#() iFEvpp -> iFEpp
#() iFEpvpp -> iFEppp
#() iFEpvvppp -> iFEpppp
#() iFEpLvvpp -> iFEpLpp
#() iFEpuvvppp -> iFEpuppp
File diff suppressed because it is too large. Load diff
+862 -3
View File
@@ -24,16 +24,24 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
// O = libc O_ flags bitfield
// S = _IO_2_1_stdXXX_ pointer (or FILE*)
// Q = ...
// 2 = struct of 2 uint
// P = Vulkan struture pointer
// G = a single GValue pointer
// N = ... automatically sending 1 arg
// M = ... automatically sending 2 args
// H = Huge 128bits value/struct
void vFE(x64emu_t *emu, uintptr_t fnc);
void vFv(x64emu_t *emu, uintptr_t fnc);
void vFi(x64emu_t *emu, uintptr_t fnc);
void vFu(x64emu_t *emu, uintptr_t fnc);
void vFf(x64emu_t *emu, uintptr_t fnc);
void vFd(x64emu_t *emu, uintptr_t fnc);
void vFp(x64emu_t *emu, uintptr_t fnc);
void vFS(x64emu_t *emu, uintptr_t fnc);
void cFv(x64emu_t *emu, uintptr_t fnc);
void cFi(x64emu_t *emu, uintptr_t fnc);
void cFu(x64emu_t *emu, uintptr_t fnc);
void cFf(x64emu_t *emu, uintptr_t fnc);
void cFp(x64emu_t *emu, uintptr_t fnc);
void wFp(x64emu_t *emu, uintptr_t fnc);
void iFE(x64emu_t *emu, uintptr_t fnc);
void iFv(x64emu_t *emu, uintptr_t fnc);
void iFi(x64emu_t *emu, uintptr_t fnc);
@@ -42,77 +50,921 @@ void iFf(x64emu_t *emu, uintptr_t fnc);
void iFd(x64emu_t *emu, uintptr_t fnc);
void iFL(x64emu_t *emu, uintptr_t fnc);
void iFp(x64emu_t *emu, uintptr_t fnc);
void iFS(x64emu_t *emu, uintptr_t fnc);
void IFf(x64emu_t *emu, uintptr_t fnc);
void IFd(x64emu_t *emu, uintptr_t fnc);
void IFp(x64emu_t *emu, uintptr_t fnc);
void WFi(x64emu_t *emu, uintptr_t fnc);
void WFp(x64emu_t *emu, uintptr_t fnc);
void uFv(x64emu_t *emu, uintptr_t fnc);
void uFi(x64emu_t *emu, uintptr_t fnc);
void uFu(x64emu_t *emu, uintptr_t fnc);
void uFd(x64emu_t *emu, uintptr_t fnc);
void uFp(x64emu_t *emu, uintptr_t fnc);
void UFv(x64emu_t *emu, uintptr_t fnc);
void UFp(x64emu_t *emu, uintptr_t fnc);
void UFV(x64emu_t *emu, uintptr_t fnc);
void fFi(x64emu_t *emu, uintptr_t fnc);
void fFf(x64emu_t *emu, uintptr_t fnc);
void fFp(x64emu_t *emu, uintptr_t fnc);
void dFi(x64emu_t *emu, uintptr_t fnc);
void dFu(x64emu_t *emu, uintptr_t fnc);
void dFd(x64emu_t *emu, uintptr_t fnc);
void dFp(x64emu_t *emu, uintptr_t fnc);
void lFE(x64emu_t *emu, uintptr_t fnc);
void lFi(x64emu_t *emu, uintptr_t fnc);
void lFp(x64emu_t *emu, uintptr_t fnc);
void LFv(x64emu_t *emu, uintptr_t fnc);
void LFL(x64emu_t *emu, uintptr_t fnc);
void LFp(x64emu_t *emu, uintptr_t fnc);
void pFE(x64emu_t *emu, uintptr_t fnc);
void pFv(x64emu_t *emu, uintptr_t fnc);
void pFi(x64emu_t *emu, uintptr_t fnc);
void pFu(x64emu_t *emu, uintptr_t fnc);
void pFL(x64emu_t *emu, uintptr_t fnc);
void pFp(x64emu_t *emu, uintptr_t fnc);
void HFi(x64emu_t *emu, uintptr_t fnc);
void HFp(x64emu_t *emu, uintptr_t fnc);
void vFEp(x64emu_t *emu, uintptr_t fnc);
void vFii(x64emu_t *emu, uintptr_t fnc);
void vFiu(x64emu_t *emu, uintptr_t fnc);
void vFif(x64emu_t *emu, uintptr_t fnc);
void vFid(x64emu_t *emu, uintptr_t fnc);
void vFip(x64emu_t *emu, uintptr_t fnc);
void vFWW(x64emu_t *emu, uintptr_t fnc);
void vFui(x64emu_t *emu, uintptr_t fnc);
void vFuu(x64emu_t *emu, uintptr_t fnc);
void vFuf(x64emu_t *emu, uintptr_t fnc);
void vFud(x64emu_t *emu, uintptr_t fnc);
void vFup(x64emu_t *emu, uintptr_t fnc);
void vFfi(x64emu_t *emu, uintptr_t fnc);
void vFff(x64emu_t *emu, uintptr_t fnc);
void vFfp(x64emu_t *emu, uintptr_t fnc);
void vFdd(x64emu_t *emu, uintptr_t fnc);
void vFpi(x64emu_t *emu, uintptr_t fnc);
void vFpu(x64emu_t *emu, uintptr_t fnc);
void vFpf(x64emu_t *emu, uintptr_t fnc);
void vFpL(x64emu_t *emu, uintptr_t fnc);
void vFpp(x64emu_t *emu, uintptr_t fnc);
void vFpS(x64emu_t *emu, uintptr_t fnc);
void vFSi(x64emu_t *emu, uintptr_t fnc);
void cFpp(x64emu_t *emu, uintptr_t fnc);
void iFEp(x64emu_t *emu, uintptr_t fnc);
void iFii(x64emu_t *emu, uintptr_t fnc);
void iFiu(x64emu_t *emu, uintptr_t fnc);
void iFip(x64emu_t *emu, uintptr_t fnc);
void iFIi(x64emu_t *emu, uintptr_t fnc);
void iFui(x64emu_t *emu, uintptr_t fnc);
void iFuu(x64emu_t *emu, uintptr_t fnc);
void iFup(x64emu_t *emu, uintptr_t fnc);
void iFUU(x64emu_t *emu, uintptr_t fnc);
void iFli(x64emu_t *emu, uintptr_t fnc);
void iFLL(x64emu_t *emu, uintptr_t fnc);
void iFLp(x64emu_t *emu, uintptr_t fnc);
void iFpw(x64emu_t *emu, uintptr_t fnc);
void iFpi(x64emu_t *emu, uintptr_t fnc);
void iFpI(x64emu_t *emu, uintptr_t fnc);
void iFpC(x64emu_t *emu, uintptr_t fnc);
void iFpu(x64emu_t *emu, uintptr_t fnc);
void iFpf(x64emu_t *emu, uintptr_t fnc);
void iFpd(x64emu_t *emu, uintptr_t fnc);
void iFpl(x64emu_t *emu, uintptr_t fnc);
void iFpL(x64emu_t *emu, uintptr_t fnc);
void iFpp(x64emu_t *emu, uintptr_t fnc);
void iFpO(x64emu_t *emu, uintptr_t fnc);
void iFSi(x64emu_t *emu, uintptr_t fnc);
void IFEp(x64emu_t *emu, uintptr_t fnc);
void IFpu(x64emu_t *emu, uintptr_t fnc);
void CFui(x64emu_t *emu, uintptr_t fnc);
void CFpi(x64emu_t *emu, uintptr_t fnc);
void CFpu(x64emu_t *emu, uintptr_t fnc);
void uFEp(x64emu_t *emu, uintptr_t fnc);
void uFiu(x64emu_t *emu, uintptr_t fnc);
void uFui(x64emu_t *emu, uintptr_t fnc);
void uFuu(x64emu_t *emu, uintptr_t fnc);
void uFup(x64emu_t *emu, uintptr_t fnc);
void uFUp(x64emu_t *emu, uintptr_t fnc);
void uFpi(x64emu_t *emu, uintptr_t fnc);
void uFpu(x64emu_t *emu, uintptr_t fnc);
void uFpU(x64emu_t *emu, uintptr_t fnc);
void uFpp(x64emu_t *emu, uintptr_t fnc);
void UFEp(x64emu_t *emu, uintptr_t fnc);
void UFUp(x64emu_t *emu, uintptr_t fnc);
void UFpp(x64emu_t *emu, uintptr_t fnc);
void fFif(x64emu_t *emu, uintptr_t fnc);
void fFfi(x64emu_t *emu, uintptr_t fnc);
void fFff(x64emu_t *emu, uintptr_t fnc);
void fFfp(x64emu_t *emu, uintptr_t fnc);
void fFpp(x64emu_t *emu, uintptr_t fnc);
void dFid(x64emu_t *emu, uintptr_t fnc);
void dFdi(x64emu_t *emu, uintptr_t fnc);
void dFdd(x64emu_t *emu, uintptr_t fnc);
void dFdp(x64emu_t *emu, uintptr_t fnc);
void dFpp(x64emu_t *emu, uintptr_t fnc);
void LFpi(x64emu_t *emu, uintptr_t fnc);
void LFpL(x64emu_t *emu, uintptr_t fnc);
void LFpp(x64emu_t *emu, uintptr_t fnc);
void pFEp(x64emu_t *emu, uintptr_t fnc);
void pFii(x64emu_t *emu, uintptr_t fnc);
void pFip(x64emu_t *emu, uintptr_t fnc);
void pFui(x64emu_t *emu, uintptr_t fnc);
void pFuu(x64emu_t *emu, uintptr_t fnc);
void pFup(x64emu_t *emu, uintptr_t fnc);
void pFlp(x64emu_t *emu, uintptr_t fnc);
void pFLL(x64emu_t *emu, uintptr_t fnc);
void pFpi(x64emu_t *emu, uintptr_t fnc);
void pFpC(x64emu_t *emu, uintptr_t fnc);
void pFpu(x64emu_t *emu, uintptr_t fnc);
void pFpU(x64emu_t *emu, uintptr_t fnc);
void pFpL(x64emu_t *emu, uintptr_t fnc);
void pFpp(x64emu_t *emu, uintptr_t fnc);
void pFpV(x64emu_t *emu, uintptr_t fnc);
void pFSi(x64emu_t *emu, uintptr_t fnc);
void HFpi(x64emu_t *emu, uintptr_t fnc);
void vFEpi(x64emu_t *emu, uintptr_t fnc);
void vFEpu(x64emu_t *emu, uintptr_t fnc);
void vFEpp(x64emu_t *emu, uintptr_t fnc);
void vFEpV(x64emu_t *emu, uintptr_t fnc);
void vFiii(x64emu_t *emu, uintptr_t fnc);
void vFiip(x64emu_t *emu, uintptr_t fnc);
void vFiui(x64emu_t *emu, uintptr_t fnc);
void vFiuu(x64emu_t *emu, uintptr_t fnc);
void vFiup(x64emu_t *emu, uintptr_t fnc);
void vFiff(x64emu_t *emu, uintptr_t fnc);
void vFidd(x64emu_t *emu, uintptr_t fnc);
void vFipi(x64emu_t *emu, uintptr_t fnc);
void vFipu(x64emu_t *emu, uintptr_t fnc);
void vFipp(x64emu_t *emu, uintptr_t fnc);
void vFuii(x64emu_t *emu, uintptr_t fnc);
void vFuiI(x64emu_t *emu, uintptr_t fnc);
void vFuiu(x64emu_t *emu, uintptr_t fnc);
void vFuif(x64emu_t *emu, uintptr_t fnc);
void vFuid(x64emu_t *emu, uintptr_t fnc);
void vFuip(x64emu_t *emu, uintptr_t fnc);
void vFuui(x64emu_t *emu, uintptr_t fnc);
void vFuuu(x64emu_t *emu, uintptr_t fnc);
void vFuuf(x64emu_t *emu, uintptr_t fnc);
void vFuud(x64emu_t *emu, uintptr_t fnc);
void vFuup(x64emu_t *emu, uintptr_t fnc);
void vFuff(x64emu_t *emu, uintptr_t fnc);
void vFudd(x64emu_t *emu, uintptr_t fnc);
void vFupi(x64emu_t *emu, uintptr_t fnc);
void vFfff(x64emu_t *emu, uintptr_t fnc);
void vFfpp(x64emu_t *emu, uintptr_t fnc);
void vFddd(x64emu_t *emu, uintptr_t fnc);
void vFdpp(x64emu_t *emu, uintptr_t fnc);
void vFLpp(x64emu_t *emu, uintptr_t fnc);
void vFpii(x64emu_t *emu, uintptr_t fnc);
void vFpiu(x64emu_t *emu, uintptr_t fnc);
void vFpif(x64emu_t *emu, uintptr_t fnc);
void vFpid(x64emu_t *emu, uintptr_t fnc);
void vFpip(x64emu_t *emu, uintptr_t fnc);
void vFpui(x64emu_t *emu, uintptr_t fnc);
void vFpuI(x64emu_t *emu, uintptr_t fnc);
void vFpuu(x64emu_t *emu, uintptr_t fnc);
void vFpup(x64emu_t *emu, uintptr_t fnc);
void vFppi(x64emu_t *emu, uintptr_t fnc);
void vFppu(x64emu_t *emu, uintptr_t fnc);
void vFppp(x64emu_t *emu, uintptr_t fnc);
void iFEiw(x64emu_t *emu, uintptr_t fnc);
void iFEip(x64emu_t *emu, uintptr_t fnc);
void iFEWW(x64emu_t *emu, uintptr_t fnc);
void iFEup(x64emu_t *emu, uintptr_t fnc);
void iFEpi(x64emu_t *emu, uintptr_t fnc);
void iFEpL(x64emu_t *emu, uintptr_t fnc);
void iFEpp(x64emu_t *emu, uintptr_t fnc);
void iFEpV(x64emu_t *emu, uintptr_t fnc);
void iFESp(x64emu_t *emu, uintptr_t fnc);
void iFiwC(x64emu_t *emu, uintptr_t fnc);
void iFiii(x64emu_t *emu, uintptr_t fnc);
void iFiiu(x64emu_t *emu, uintptr_t fnc);
void iFiip(x64emu_t *emu, uintptr_t fnc);
void iFiiO(x64emu_t *emu, uintptr_t fnc);
void iFiuu(x64emu_t *emu, uintptr_t fnc);
void iFiLN(x64emu_t *emu, uintptr_t fnc);
void iFipu(x64emu_t *emu, uintptr_t fnc);
void iFipp(x64emu_t *emu, uintptr_t fnc);
void iFuuu(x64emu_t *emu, uintptr_t fnc);
void iFuup(x64emu_t *emu, uintptr_t fnc);
void iFuff(x64emu_t *emu, uintptr_t fnc);
void iFfff(x64emu_t *emu, uintptr_t fnc);
void iFLip(x64emu_t *emu, uintptr_t fnc);
void iFLpp(x64emu_t *emu, uintptr_t fnc);
void iFpii(x64emu_t *emu, uintptr_t fnc);
void iFpiu(x64emu_t *emu, uintptr_t fnc);
void iFpiL(x64emu_t *emu, uintptr_t fnc);
void iFpip(x64emu_t *emu, uintptr_t fnc);
void iFpIi(x64emu_t *emu, uintptr_t fnc);
void iFpui(x64emu_t *emu, uintptr_t fnc);
void iFpuu(x64emu_t *emu, uintptr_t fnc);
void iFpuU(x64emu_t *emu, uintptr_t fnc);
void iFpuL(x64emu_t *emu, uintptr_t fnc);
void iFpup(x64emu_t *emu, uintptr_t fnc);
void iFpfu(x64emu_t *emu, uintptr_t fnc);
void iFpff(x64emu_t *emu, uintptr_t fnc);
void iFpli(x64emu_t *emu, uintptr_t fnc);
void iFplp(x64emu_t *emu, uintptr_t fnc);
void iFpLp(x64emu_t *emu, uintptr_t fnc);
void iFppi(x64emu_t *emu, uintptr_t fnc);
void iFppI(x64emu_t *emu, uintptr_t fnc);
void iFppu(x64emu_t *emu, uintptr_t fnc);
void iFppd(x64emu_t *emu, uintptr_t fnc);
void iFppL(x64emu_t *emu, uintptr_t fnc);
void iFppp(x64emu_t *emu, uintptr_t fnc);
void iFppV(x64emu_t *emu, uintptr_t fnc);
void iFSpL(x64emu_t *emu, uintptr_t fnc);
void IFiIi(x64emu_t *emu, uintptr_t fnc);
void IFpIi(x64emu_t *emu, uintptr_t fnc);
void IFppi(x64emu_t *emu, uintptr_t fnc);
void IFSIi(x64emu_t *emu, uintptr_t fnc);
void uFEpW(x64emu_t *emu, uintptr_t fnc);
void uFEpu(x64emu_t *emu, uintptr_t fnc);
void uFEpU(x64emu_t *emu, uintptr_t fnc);
void uFipu(x64emu_t *emu, uintptr_t fnc);
void uFuip(x64emu_t *emu, uintptr_t fnc);
void uFuui(x64emu_t *emu, uintptr_t fnc);
void uFuuu(x64emu_t *emu, uintptr_t fnc);
void uFuup(x64emu_t *emu, uintptr_t fnc);
void uFupu(x64emu_t *emu, uintptr_t fnc);
void uFupp(x64emu_t *emu, uintptr_t fnc);
void uFpiu(x64emu_t *emu, uintptr_t fnc);
void uFpip(x64emu_t *emu, uintptr_t fnc);
void uFpLp(x64emu_t *emu, uintptr_t fnc);
void uFppi(x64emu_t *emu, uintptr_t fnc);
void uFppu(x64emu_t *emu, uintptr_t fnc);
void UFppi(x64emu_t *emu, uintptr_t fnc);
void fFuii(x64emu_t *emu, uintptr_t fnc);
void fFfff(x64emu_t *emu, uintptr_t fnc);
void fFffp(x64emu_t *emu, uintptr_t fnc);
void dFddd(x64emu_t *emu, uintptr_t fnc);
void dFddp(x64emu_t *emu, uintptr_t fnc);
void dFppi(x64emu_t *emu, uintptr_t fnc);
void dFppp(x64emu_t *emu, uintptr_t fnc);
void lFipi(x64emu_t *emu, uintptr_t fnc);
void lFipL(x64emu_t *emu, uintptr_t fnc);
void lFlpi(x64emu_t *emu, uintptr_t fnc);
void lFppi(x64emu_t *emu, uintptr_t fnc);
void lFSpl(x64emu_t *emu, uintptr_t fnc);
void LFLLi(x64emu_t *emu, uintptr_t fnc);
void LFLLI(x64emu_t *emu, uintptr_t fnc);
void LFLpu(x64emu_t *emu, uintptr_t fnc);
void LFLpL(x64emu_t *emu, uintptr_t fnc);
void LFpii(x64emu_t *emu, uintptr_t fnc);
void LFppi(x64emu_t *emu, uintptr_t fnc);
void LFSpL(x64emu_t *emu, uintptr_t fnc);
void pFEip(x64emu_t *emu, uintptr_t fnc);
void pFEpi(x64emu_t *emu, uintptr_t fnc);
void pFEpp(x64emu_t *emu, uintptr_t fnc);
void pFipi(x64emu_t *emu, uintptr_t fnc);
void pFipp(x64emu_t *emu, uintptr_t fnc);
void pFIpi(x64emu_t *emu, uintptr_t fnc);
void pFuii(x64emu_t *emu, uintptr_t fnc);
void pFupi(x64emu_t *emu, uintptr_t fnc);
void pFUpi(x64emu_t *emu, uintptr_t fnc);
void pFpii(x64emu_t *emu, uintptr_t fnc);
void pFpiu(x64emu_t *emu, uintptr_t fnc);
void pFpiL(x64emu_t *emu, uintptr_t fnc);
void pFpip(x64emu_t *emu, uintptr_t fnc);
void pFpCC(x64emu_t *emu, uintptr_t fnc);
void pFpui(x64emu_t *emu, uintptr_t fnc);
void pFpuu(x64emu_t *emu, uintptr_t fnc);
void pFpuL(x64emu_t *emu, uintptr_t fnc);
void pFpup(x64emu_t *emu, uintptr_t fnc);
void pFpUp(x64emu_t *emu, uintptr_t fnc);
void pFplp(x64emu_t *emu, uintptr_t fnc);
void pFpLu(x64emu_t *emu, uintptr_t fnc);
void pFpLL(x64emu_t *emu, uintptr_t fnc);
void pFpLp(x64emu_t *emu, uintptr_t fnc);
void pFppi(x64emu_t *emu, uintptr_t fnc);
void pFppu(x64emu_t *emu, uintptr_t fnc);
void pFppf(x64emu_t *emu, uintptr_t fnc);
void pFppL(x64emu_t *emu, uintptr_t fnc);
void pFppp(x64emu_t *emu, uintptr_t fnc);
void pFpOM(x64emu_t *emu, uintptr_t fnc);
void pFSpl(x64emu_t *emu, uintptr_t fnc);
void vFEipV(x64emu_t *emu, uintptr_t fnc);
void vFEpip(x64emu_t *emu, uintptr_t fnc);
void vFEpup(x64emu_t *emu, uintptr_t fnc);
void vFEppp(x64emu_t *emu, uintptr_t fnc);
void vFiiii(x64emu_t *emu, uintptr_t fnc);
void vFiiip(x64emu_t *emu, uintptr_t fnc);
void vFiuip(x64emu_t *emu, uintptr_t fnc);
void vFiuuu(x64emu_t *emu, uintptr_t fnc);
void vFiupu(x64emu_t *emu, uintptr_t fnc);
void vFiupV(x64emu_t *emu, uintptr_t fnc);
void vFifff(x64emu_t *emu, uintptr_t fnc);
void vFiddd(x64emu_t *emu, uintptr_t fnc);
void vFipii(x64emu_t *emu, uintptr_t fnc);
void vFipup(x64emu_t *emu, uintptr_t fnc);
void vFippp(x64emu_t *emu, uintptr_t fnc);
void vFuiii(x64emu_t *emu, uintptr_t fnc);
void vFuiip(x64emu_t *emu, uintptr_t fnc);
void vFuiui(x64emu_t *emu, uintptr_t fnc);
void vFuiuu(x64emu_t *emu, uintptr_t fnc);
void vFuiup(x64emu_t *emu, uintptr_t fnc);
void vFuifi(x64emu_t *emu, uintptr_t fnc);
void vFuiff(x64emu_t *emu, uintptr_t fnc);
void vFuidd(x64emu_t *emu, uintptr_t fnc);
void vFuipi(x64emu_t *emu, uintptr_t fnc);
void vFuipu(x64emu_t *emu, uintptr_t fnc);
void vFuipp(x64emu_t *emu, uintptr_t fnc);
void vFuuii(x64emu_t *emu, uintptr_t fnc);
void vFuuiu(x64emu_t *emu, uintptr_t fnc);
void vFuuip(x64emu_t *emu, uintptr_t fnc);
void vFuuui(x64emu_t *emu, uintptr_t fnc);
void vFuuuu(x64emu_t *emu, uintptr_t fnc);
void vFuuuf(x64emu_t *emu, uintptr_t fnc);
void vFuuud(x64emu_t *emu, uintptr_t fnc);
void vFuuup(x64emu_t *emu, uintptr_t fnc);
void vFuupi(x64emu_t *emu, uintptr_t fnc);
void vFuupp(x64emu_t *emu, uintptr_t fnc);
void vFufff(x64emu_t *emu, uintptr_t fnc);
void vFuddd(x64emu_t *emu, uintptr_t fnc);
void vFupii(x64emu_t *emu, uintptr_t fnc);
void vFuppi(x64emu_t *emu, uintptr_t fnc);
void vFffff(x64emu_t *emu, uintptr_t fnc);
void vFdddd(x64emu_t *emu, uintptr_t fnc);
void vFpiii(x64emu_t *emu, uintptr_t fnc);
void vFpiip(x64emu_t *emu, uintptr_t fnc);
void vFpipp(x64emu_t *emu, uintptr_t fnc);
void vFpupp(x64emu_t *emu, uintptr_t fnc);
void vFpdii(x64emu_t *emu, uintptr_t fnc);
void vFpddd(x64emu_t *emu, uintptr_t fnc);
void vFppii(x64emu_t *emu, uintptr_t fnc);
void vFppip(x64emu_t *emu, uintptr_t fnc);
void vFppui(x64emu_t *emu, uintptr_t fnc);
void vFppup(x64emu_t *emu, uintptr_t fnc);
void vFpppi(x64emu_t *emu, uintptr_t fnc);
void vFpppu(x64emu_t *emu, uintptr_t fnc);
void vFpppp(x64emu_t *emu, uintptr_t fnc);
void cFpiii(x64emu_t *emu, uintptr_t fnc);
void iFEiip(x64emu_t *emu, uintptr_t fnc);
void iFEiiN(x64emu_t *emu, uintptr_t fnc);
void iFEipp(x64emu_t *emu, uintptr_t fnc);
void iFEipV(x64emu_t *emu, uintptr_t fnc);
void iFEupp(x64emu_t *emu, uintptr_t fnc);
void iFEpip(x64emu_t *emu, uintptr_t fnc);
void iFEppi(x64emu_t *emu, uintptr_t fnc);
void iFEppL(x64emu_t *emu, uintptr_t fnc);
void iFEppp(x64emu_t *emu, uintptr_t fnc);
void iFEppV(x64emu_t *emu, uintptr_t fnc);
void iFEpOu(x64emu_t *emu, uintptr_t fnc);
void iFiiii(x64emu_t *emu, uintptr_t fnc);
void iFiiiu(x64emu_t *emu, uintptr_t fnc);
void iFiuii(x64emu_t *emu, uintptr_t fnc);
void iFipii(x64emu_t *emu, uintptr_t fnc);
void iFippi(x64emu_t *emu, uintptr_t fnc);
void iFippp(x64emu_t *emu, uintptr_t fnc);
void iFuipp(x64emu_t *emu, uintptr_t fnc);
void iFuuff(x64emu_t *emu, uintptr_t fnc);
void iFuppp(x64emu_t *emu, uintptr_t fnc);
void iFpiii(x64emu_t *emu, uintptr_t fnc);
void iFpiiu(x64emu_t *emu, uintptr_t fnc);
void iFpiid(x64emu_t *emu, uintptr_t fnc);
void iFpiiL(x64emu_t *emu, uintptr_t fnc);
void iFpiip(x64emu_t *emu, uintptr_t fnc);
void iFpiup(x64emu_t *emu, uintptr_t fnc);
void iFpipi(x64emu_t *emu, uintptr_t fnc);
void iFpipp(x64emu_t *emu, uintptr_t fnc);
void iFpCCC(x64emu_t *emu, uintptr_t fnc);
void iFpWWu(x64emu_t *emu, uintptr_t fnc);
void iFpuip(x64emu_t *emu, uintptr_t fnc);
void iFpuui(x64emu_t *emu, uintptr_t fnc);
void iFpuuu(x64emu_t *emu, uintptr_t fnc);
void iFpuup(x64emu_t *emu, uintptr_t fnc);
void iFpuLL(x64emu_t *emu, uintptr_t fnc);
void iFpuLp(x64emu_t *emu, uintptr_t fnc);
void iFpupV(x64emu_t *emu, uintptr_t fnc);
void iFppii(x64emu_t *emu, uintptr_t fnc);
void iFppiu(x64emu_t *emu, uintptr_t fnc);
void iFppiL(x64emu_t *emu, uintptr_t fnc);
void iFppip(x64emu_t *emu, uintptr_t fnc);
void iFppuw(x64emu_t *emu, uintptr_t fnc);
void iFppui(x64emu_t *emu, uintptr_t fnc);
void iFppuu(x64emu_t *emu, uintptr_t fnc);
void iFppup(x64emu_t *emu, uintptr_t fnc);
void iFpplp(x64emu_t *emu, uintptr_t fnc);
void iFppLp(x64emu_t *emu, uintptr_t fnc);
void iFpppi(x64emu_t *emu, uintptr_t fnc);
void iFpppu(x64emu_t *emu, uintptr_t fnc);
void iFpppL(x64emu_t *emu, uintptr_t fnc);
void iFpppp(x64emu_t *emu, uintptr_t fnc);
void IFEpIi(x64emu_t *emu, uintptr_t fnc);
void IFSIii(x64emu_t *emu, uintptr_t fnc);
void uFifff(x64emu_t *emu, uintptr_t fnc);
void uFuuuu(x64emu_t *emu, uintptr_t fnc);
void uFpipp(x64emu_t *emu, uintptr_t fnc);
void uFpCCC(x64emu_t *emu, uintptr_t fnc);
void uFpuip(x64emu_t *emu, uintptr_t fnc);
void uFpuuu(x64emu_t *emu, uintptr_t fnc);
void uFpppi(x64emu_t *emu, uintptr_t fnc);
void UFpipp(x64emu_t *emu, uintptr_t fnc);
void lFipiI(x64emu_t *emu, uintptr_t fnc);
void lFipLI(x64emu_t *emu, uintptr_t fnc);
void lFipLl(x64emu_t *emu, uintptr_t fnc);
void LFpuuu(x64emu_t *emu, uintptr_t fnc);
void LFpLLp(x64emu_t *emu, uintptr_t fnc);
void LFpLpp(x64emu_t *emu, uintptr_t fnc);
void LFppii(x64emu_t *emu, uintptr_t fnc);
void LFppLp(x64emu_t *emu, uintptr_t fnc);
void pFEipp(x64emu_t *emu, uintptr_t fnc);
void pFEupp(x64emu_t *emu, uintptr_t fnc);
void pFEpii(x64emu_t *emu, uintptr_t fnc);
void pFEpip(x64emu_t *emu, uintptr_t fnc);
void pFEppi(x64emu_t *emu, uintptr_t fnc);
void pFEppL(x64emu_t *emu, uintptr_t fnc);
void pFEppp(x64emu_t *emu, uintptr_t fnc);
void pFiiiu(x64emu_t *emu, uintptr_t fnc);
void pFiiup(x64emu_t *emu, uintptr_t fnc);
void pFippL(x64emu_t *emu, uintptr_t fnc);
void pFuiii(x64emu_t *emu, uintptr_t fnc);
void pFpiii(x64emu_t *emu, uintptr_t fnc);
void pFpiip(x64emu_t *emu, uintptr_t fnc);
void pFpiLL(x64emu_t *emu, uintptr_t fnc);
void pFpipi(x64emu_t *emu, uintptr_t fnc);
void pFpipp(x64emu_t *emu, uintptr_t fnc);
void pFpCWp(x64emu_t *emu, uintptr_t fnc);
void pFpCuW(x64emu_t *emu, uintptr_t fnc);
void pFpCuu(x64emu_t *emu, uintptr_t fnc);
void pFpuii(x64emu_t *emu, uintptr_t fnc);
void pFpuWp(x64emu_t *emu, uintptr_t fnc);
void pFpuuu(x64emu_t *emu, uintptr_t fnc);
void pFpuup(x64emu_t *emu, uintptr_t fnc);
void pFpupi(x64emu_t *emu, uintptr_t fnc);
void pFplpp(x64emu_t *emu, uintptr_t fnc);
void pFppii(x64emu_t *emu, uintptr_t fnc);
void pFppiL(x64emu_t *emu, uintptr_t fnc);
void pFppip(x64emu_t *emu, uintptr_t fnc);
void pFppuu(x64emu_t *emu, uintptr_t fnc);
void pFppuL(x64emu_t *emu, uintptr_t fnc);
void pFppup(x64emu_t *emu, uintptr_t fnc);
void pFppLL(x64emu_t *emu, uintptr_t fnc);
void pFpppi(x64emu_t *emu, uintptr_t fnc);
void pFpppu(x64emu_t *emu, uintptr_t fnc);
void pFpppL(x64emu_t *emu, uintptr_t fnc);
void pFpppp(x64emu_t *emu, uintptr_t fnc);
void pFSppi(x64emu_t *emu, uintptr_t fnc);
void vFEpuup(x64emu_t *emu, uintptr_t fnc);
void vFEpLLp(x64emu_t *emu, uintptr_t fnc);
void vFEpppp(x64emu_t *emu, uintptr_t fnc);
void vFiiiii(x64emu_t *emu, uintptr_t fnc);
void vFiiiiu(x64emu_t *emu, uintptr_t fnc);
void vFiiuup(x64emu_t *emu, uintptr_t fnc);
void vFiipii(x64emu_t *emu, uintptr_t fnc);
void vFiuiip(x64emu_t *emu, uintptr_t fnc);
void vFiuipi(x64emu_t *emu, uintptr_t fnc);
void vFiuuuu(x64emu_t *emu, uintptr_t fnc);
void vFiffff(x64emu_t *emu, uintptr_t fnc);
void vFidddd(x64emu_t *emu, uintptr_t fnc);
void vFilill(x64emu_t *emu, uintptr_t fnc);
void vFipipu(x64emu_t *emu, uintptr_t fnc);
void vFipipp(x64emu_t *emu, uintptr_t fnc);
void vFipupi(x64emu_t *emu, uintptr_t fnc);
void vFuiiii(x64emu_t *emu, uintptr_t fnc);
void vFuiiiu(x64emu_t *emu, uintptr_t fnc);
void vFuiiip(x64emu_t *emu, uintptr_t fnc);
void vFuiiup(x64emu_t *emu, uintptr_t fnc);
void vFuiIII(x64emu_t *emu, uintptr_t fnc);
void vFuiuii(x64emu_t *emu, uintptr_t fnc);
void vFuiuiu(x64emu_t *emu, uintptr_t fnc);
void vFuiuip(x64emu_t *emu, uintptr_t fnc);
void vFuiuuu(x64emu_t *emu, uintptr_t fnc);
void vFuiuup(x64emu_t *emu, uintptr_t fnc);
void vFuiupi(x64emu_t *emu, uintptr_t fnc);
void vFuiupu(x64emu_t *emu, uintptr_t fnc);
void vFuifff(x64emu_t *emu, uintptr_t fnc);
void vFuiddd(x64emu_t *emu, uintptr_t fnc);
void vFuipii(x64emu_t *emu, uintptr_t fnc);
void vFuipip(x64emu_t *emu, uintptr_t fnc);
void vFuipup(x64emu_t *emu, uintptr_t fnc);
void vFuippp(x64emu_t *emu, uintptr_t fnc);
void vFuuiii(x64emu_t *emu, uintptr_t fnc);
void vFuuiui(x64emu_t *emu, uintptr_t fnc);
void vFuuiuu(x64emu_t *emu, uintptr_t fnc);
void vFuuiup(x64emu_t *emu, uintptr_t fnc);
void vFuuipi(x64emu_t *emu, uintptr_t fnc);
void vFuuipu(x64emu_t *emu, uintptr_t fnc);
void vFuuipp(x64emu_t *emu, uintptr_t fnc);
void vFuuuii(x64emu_t *emu, uintptr_t fnc);
void vFuuuiu(x64emu_t *emu, uintptr_t fnc);
void vFuuuip(x64emu_t *emu, uintptr_t fnc);
void vFuuuui(x64emu_t *emu, uintptr_t fnc);
void vFuuuuu(x64emu_t *emu, uintptr_t fnc);
void vFuuuup(x64emu_t *emu, uintptr_t fnc);
void vFuupii(x64emu_t *emu, uintptr_t fnc);
void vFuffff(x64emu_t *emu, uintptr_t fnc);
void vFudddd(x64emu_t *emu, uintptr_t fnc);
void vFupupi(x64emu_t *emu, uintptr_t fnc);
void vFuppip(x64emu_t *emu, uintptr_t fnc);
void vFupppp(x64emu_t *emu, uintptr_t fnc);
void vFfffff(x64emu_t *emu, uintptr_t fnc);
void vFddddp(x64emu_t *emu, uintptr_t fnc);
void vFpiiii(x64emu_t *emu, uintptr_t fnc);
void vFpipii(x64emu_t *emu, uintptr_t fnc);
void vFpuipp(x64emu_t *emu, uintptr_t fnc);
void vFpddii(x64emu_t *emu, uintptr_t fnc);
void vFppiii(x64emu_t *emu, uintptr_t fnc);
void vFppiip(x64emu_t *emu, uintptr_t fnc);
void vFppWui(x64emu_t *emu, uintptr_t fnc);
void vFpppii(x64emu_t *emu, uintptr_t fnc);
void vFppppi(x64emu_t *emu, uintptr_t fnc);
void vFppppp(x64emu_t *emu, uintptr_t fnc);
void iFEippp(x64emu_t *emu, uintptr_t fnc);
void iFEpipi(x64emu_t *emu, uintptr_t fnc);
void iFEpipp(x64emu_t *emu, uintptr_t fnc);
void iFEpipV(x64emu_t *emu, uintptr_t fnc);
void iFEpLpp(x64emu_t *emu, uintptr_t fnc);
void iFEpLpV(x64emu_t *emu, uintptr_t fnc);
void iFEppip(x64emu_t *emu, uintptr_t fnc);
void iFEppiV(x64emu_t *emu, uintptr_t fnc);
void iFEpppp(x64emu_t *emu, uintptr_t fnc);
void iFEpppV(x64emu_t *emu, uintptr_t fnc);
void iFiiupp(x64emu_t *emu, uintptr_t fnc);
void iFipiii(x64emu_t *emu, uintptr_t fnc);
void iFipppi(x64emu_t *emu, uintptr_t fnc);
void iFipppp(x64emu_t *emu, uintptr_t fnc);
void iFpiiii(x64emu_t *emu, uintptr_t fnc);
void iFpiiip(x64emu_t *emu, uintptr_t fnc);
void iFpiiuu(x64emu_t *emu, uintptr_t fnc);
void iFpiipi(x64emu_t *emu, uintptr_t fnc);
void iFpiipp(x64emu_t *emu, uintptr_t fnc);
void iFpipii(x64emu_t *emu, uintptr_t fnc);
void iFpippi(x64emu_t *emu, uintptr_t fnc);
void iFpippp(x64emu_t *emu, uintptr_t fnc);
void iFpCCCC(x64emu_t *emu, uintptr_t fnc);
void iFpuuui(x64emu_t *emu, uintptr_t fnc);
void iFpuuLL(x64emu_t *emu, uintptr_t fnc);
void iFpuupp(x64emu_t *emu, uintptr_t fnc);
void iFppiip(x64emu_t *emu, uintptr_t fnc);
void iFppiup(x64emu_t *emu, uintptr_t fnc);
void iFppipi(x64emu_t *emu, uintptr_t fnc);
void iFppipp(x64emu_t *emu, uintptr_t fnc);
void iFppupi(x64emu_t *emu, uintptr_t fnc);
void iFpppii(x64emu_t *emu, uintptr_t fnc);
void iFpppiL(x64emu_t *emu, uintptr_t fnc);
void iFpppip(x64emu_t *emu, uintptr_t fnc);
void iFpppLi(x64emu_t *emu, uintptr_t fnc);
void iFppppi(x64emu_t *emu, uintptr_t fnc);
void iFppppp(x64emu_t *emu, uintptr_t fnc);
void IFppIII(x64emu_t *emu, uintptr_t fnc);
void uFEppuu(x64emu_t *emu, uintptr_t fnc);
void uFiuuuu(x64emu_t *emu, uintptr_t fnc);
void uFuiiiu(x64emu_t *emu, uintptr_t fnc);
void uFpCCCC(x64emu_t *emu, uintptr_t fnc);
void uFpuuuu(x64emu_t *emu, uintptr_t fnc);
void uFppiip(x64emu_t *emu, uintptr_t fnc);
void uFppppp(x64emu_t *emu, uintptr_t fnc);
void LFLpppp(x64emu_t *emu, uintptr_t fnc);
void LFpLLLp(x64emu_t *emu, uintptr_t fnc);
void LFpLppL(x64emu_t *emu, uintptr_t fnc);
void LFppppp(x64emu_t *emu, uintptr_t fnc);
void pFEpiii(x64emu_t *emu, uintptr_t fnc);
void pFEpipL(x64emu_t *emu, uintptr_t fnc);
void pFEpipp(x64emu_t *emu, uintptr_t fnc);
void pFEpupp(x64emu_t *emu, uintptr_t fnc);
void pFEppii(x64emu_t *emu, uintptr_t fnc);
void pFEppip(x64emu_t *emu, uintptr_t fnc);
void pFEpppp(x64emu_t *emu, uintptr_t fnc);
void pFuiiiu(x64emu_t *emu, uintptr_t fnc);
void pFuiipp(x64emu_t *emu, uintptr_t fnc);
void pFpiiuu(x64emu_t *emu, uintptr_t fnc);
void pFpiipp(x64emu_t *emu, uintptr_t fnc);
void pFpippp(x64emu_t *emu, uintptr_t fnc);
void pFpCuup(x64emu_t *emu, uintptr_t fnc);
void pFpCppp(x64emu_t *emu, uintptr_t fnc);
void pFpuiii(x64emu_t *emu, uintptr_t fnc);
void pFpuiip(x64emu_t *emu, uintptr_t fnc);
void pFpuWWW(x64emu_t *emu, uintptr_t fnc);
void pFpuuWW(x64emu_t *emu, uintptr_t fnc);
void pFpuuup(x64emu_t *emu, uintptr_t fnc);
void pFppipi(x64emu_t *emu, uintptr_t fnc);
void pFppipp(x64emu_t *emu, uintptr_t fnc);
void pFppuuu(x64emu_t *emu, uintptr_t fnc);
void pFppuup(x64emu_t *emu, uintptr_t fnc);
void pFppLLp(x64emu_t *emu, uintptr_t fnc);
void pFpppip(x64emu_t *emu, uintptr_t fnc);
void pFpppuu(x64emu_t *emu, uintptr_t fnc);
void pFpppup(x64emu_t *emu, uintptr_t fnc);
void pFppppi(x64emu_t *emu, uintptr_t fnc);
void pFppppp(x64emu_t *emu, uintptr_t fnc);
void vFEiiipp(x64emu_t *emu, uintptr_t fnc);
void vFEpLLpp(x64emu_t *emu, uintptr_t fnc);
void vFiiiiii(x64emu_t *emu, uintptr_t fnc);
void vFiiiuil(x64emu_t *emu, uintptr_t fnc);
void vFiuippp(x64emu_t *emu, uintptr_t fnc);
void vFiffiff(x64emu_t *emu, uintptr_t fnc);
void vFiddidd(x64emu_t *emu, uintptr_t fnc);
void vFuiiiii(x64emu_t *emu, uintptr_t fnc);
void vFuiiiip(x64emu_t *emu, uintptr_t fnc);
void vFuiiuii(x64emu_t *emu, uintptr_t fnc);
void vFuiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuiuiii(x64emu_t *emu, uintptr_t fnc);
void vFuiuiip(x64emu_t *emu, uintptr_t fnc);
void vFuiuiuu(x64emu_t *emu, uintptr_t fnc);
void vFuiuuip(x64emu_t *emu, uintptr_t fnc);
void vFuiuuuu(x64emu_t *emu, uintptr_t fnc);
void vFuiupii(x64emu_t *emu, uintptr_t fnc);
void vFuiupiu(x64emu_t *emu, uintptr_t fnc);
void vFuiffff(x64emu_t *emu, uintptr_t fnc);
void vFuidddd(x64emu_t *emu, uintptr_t fnc);
void vFuipiup(x64emu_t *emu, uintptr_t fnc);
void vFuuiiii(x64emu_t *emu, uintptr_t fnc);
void vFuuiuii(x64emu_t *emu, uintptr_t fnc);
void vFuuiuiu(x64emu_t *emu, uintptr_t fnc);
void vFuuiuup(x64emu_t *emu, uintptr_t fnc);
void vFuuippp(x64emu_t *emu, uintptr_t fnc);
void vFuuuiup(x64emu_t *emu, uintptr_t fnc);
void vFuuuipi(x64emu_t *emu, uintptr_t fnc);
void vFuuuipp(x64emu_t *emu, uintptr_t fnc);
void vFuuuuii(x64emu_t *emu, uintptr_t fnc);
void vFuuuuip(x64emu_t *emu, uintptr_t fnc);
void vFuuuuuu(x64emu_t *emu, uintptr_t fnc);
void vFuuuuff(x64emu_t *emu, uintptr_t fnc);
void vFuuuppi(x64emu_t *emu, uintptr_t fnc);
void vFuuuppp(x64emu_t *emu, uintptr_t fnc);
void vFuuffff(x64emu_t *emu, uintptr_t fnc);
void vFuudddd(x64emu_t *emu, uintptr_t fnc);
void vFuffiip(x64emu_t *emu, uintptr_t fnc);
void vFufffff(x64emu_t *emu, uintptr_t fnc);
void vFuddiip(x64emu_t *emu, uintptr_t fnc);
void vFupupip(x64emu_t *emu, uintptr_t fnc);
void vFuppppp(x64emu_t *emu, uintptr_t fnc);
void vFffffff(x64emu_t *emu, uintptr_t fnc);
void vFdddddd(x64emu_t *emu, uintptr_t fnc);
void vFpipipV(x64emu_t *emu, uintptr_t fnc);
void vFpipppi(x64emu_t *emu, uintptr_t fnc);
void vFpdddii(x64emu_t *emu, uintptr_t fnc);
void vFppiiii(x64emu_t *emu, uintptr_t fnc);
void vFppiipi(x64emu_t *emu, uintptr_t fnc);
void vFppupii(x64emu_t *emu, uintptr_t fnc);
void vFpppppp(x64emu_t *emu, uintptr_t fnc);
void iFEiippi(x64emu_t *emu, uintptr_t fnc);
void iFEpilpV(x64emu_t *emu, uintptr_t fnc);
void iFEpippi(x64emu_t *emu, uintptr_t fnc);
void iFEpuppp(x64emu_t *emu, uintptr_t fnc);
void iFEppppp(x64emu_t *emu, uintptr_t fnc);
void iFiiiiii(x64emu_t *emu, uintptr_t fnc);
void iFiiiiip(x64emu_t *emu, uintptr_t fnc);
void iFiuiipi(x64emu_t *emu, uintptr_t fnc);
void iFuppipp(x64emu_t *emu, uintptr_t fnc);
void iFuppppp(x64emu_t *emu, uintptr_t fnc);
void iFpiiiii(x64emu_t *emu, uintptr_t fnc);
void iFpiiipp(x64emu_t *emu, uintptr_t fnc);
void iFpiippp(x64emu_t *emu, uintptr_t fnc);
void iFpipppp(x64emu_t *emu, uintptr_t fnc);
void iFpupuui(x64emu_t *emu, uintptr_t fnc);
void iFppiiuu(x64emu_t *emu, uintptr_t fnc);
void iFppIppp(x64emu_t *emu, uintptr_t fnc);
void iFppuiii(x64emu_t *emu, uintptr_t fnc);
void iFppuiiL(x64emu_t *emu, uintptr_t fnc);
void iFppuIII(x64emu_t *emu, uintptr_t fnc);
void iFppuupp(x64emu_t *emu, uintptr_t fnc);
void iFppupip(x64emu_t *emu, uintptr_t fnc);
void iFpppiuu(x64emu_t *emu, uintptr_t fnc);
void iFpppipi(x64emu_t *emu, uintptr_t fnc);
void iFpppipp(x64emu_t *emu, uintptr_t fnc);
void iFppppii(x64emu_t *emu, uintptr_t fnc);
void iFpppppi(x64emu_t *emu, uintptr_t fnc);
void iFpppppL(x64emu_t *emu, uintptr_t fnc);
void iFpppppp(x64emu_t *emu, uintptr_t fnc);
void uFpippup(x64emu_t *emu, uintptr_t fnc);
void UFpippup(x64emu_t *emu, uintptr_t fnc);
void LFSpLiip(x64emu_t *emu, uintptr_t fnc);
void pFEpippp(x64emu_t *emu, uintptr_t fnc);
void pFEpuipp(x64emu_t *emu, uintptr_t fnc);
void pFEpuupp(x64emu_t *emu, uintptr_t fnc);
void pFEpuppp(x64emu_t *emu, uintptr_t fnc);
void pFEppppp(x64emu_t *emu, uintptr_t fnc);
void pFiCiiCi(x64emu_t *emu, uintptr_t fnc);
void pFpiiiiu(x64emu_t *emu, uintptr_t fnc);
void pFpippip(x64emu_t *emu, uintptr_t fnc);
void pFpCuuCC(x64emu_t *emu, uintptr_t fnc);
void pFpCuuWW(x64emu_t *emu, uintptr_t fnc);
void pFpCuuup(x64emu_t *emu, uintptr_t fnc);
void pFpuuuuu(x64emu_t *emu, uintptr_t fnc);
void pFppiiii(x64emu_t *emu, uintptr_t fnc);
void pFpppppp(x64emu_t *emu, uintptr_t fnc);
void pFSpiiii(x64emu_t *emu, uintptr_t fnc);
void vFiiiiiip(x64emu_t *emu, uintptr_t fnc);
void vFiiiiuup(x64emu_t *emu, uintptr_t fnc);
void vFiiupuip(x64emu_t *emu, uintptr_t fnc);
void vFiiffffp(x64emu_t *emu, uintptr_t fnc);
void vFiupuuup(x64emu_t *emu, uintptr_t fnc);
void vFuiiiiii(x64emu_t *emu, uintptr_t fnc);
void vFuiiiuip(x64emu_t *emu, uintptr_t fnc);
void vFuiiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuiuiiii(x64emu_t *emu, uintptr_t fnc);
void vFuiuiiip(x64emu_t *emu, uintptr_t fnc);
void vFuiuiiuu(x64emu_t *emu, uintptr_t fnc);
void vFuiupiiu(x64emu_t *emu, uintptr_t fnc);
void vFuipiiii(x64emu_t *emu, uintptr_t fnc);
void vFuipffff(x64emu_t *emu, uintptr_t fnc);
void vFuipdddd(x64emu_t *emu, uintptr_t fnc);
void vFuuiiiii(x64emu_t *emu, uintptr_t fnc);
void vFuuiiiip(x64emu_t *emu, uintptr_t fnc);
void vFuuiiiui(x64emu_t *emu, uintptr_t fnc);
void vFuuiiiuu(x64emu_t *emu, uintptr_t fnc);
void vFuuiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuuiuiii(x64emu_t *emu, uintptr_t fnc);
void vFuuipppp(x64emu_t *emu, uintptr_t fnc);
void vFuuuiiii(x64emu_t *emu, uintptr_t fnc);
void vFuuuiiip(x64emu_t *emu, uintptr_t fnc);
void vFuuuiuii(x64emu_t *emu, uintptr_t fnc);
void vFuuuiupi(x64emu_t *emu, uintptr_t fnc);
void vFuuuuiip(x64emu_t *emu, uintptr_t fnc);
void vFuuuuuuu(x64emu_t *emu, uintptr_t fnc);
void vFuuuufff(x64emu_t *emu, uintptr_t fnc);
void vFuuuffff(x64emu_t *emu, uintptr_t fnc);
void vFuuudddd(x64emu_t *emu, uintptr_t fnc);
void vFuuffiip(x64emu_t *emu, uintptr_t fnc);
void vFuuddiip(x64emu_t *emu, uintptr_t fnc);
void vFuffffff(x64emu_t *emu, uintptr_t fnc);
void vFudddddd(x64emu_t *emu, uintptr_t fnc);
void vFpipipii(x64emu_t *emu, uintptr_t fnc);
void vFpddiidd(x64emu_t *emu, uintptr_t fnc);
void vFppiiipi(x64emu_t *emu, uintptr_t fnc);
void vFpppiiii(x64emu_t *emu, uintptr_t fnc);
void vFppppipi(x64emu_t *emu, uintptr_t fnc);
void iFEpLiLpV(x64emu_t *emu, uintptr_t fnc);
void iFEppLpIi(x64emu_t *emu, uintptr_t fnc);
void iFEpppiiu(x64emu_t *emu, uintptr_t fnc);
void iFEpppppp(x64emu_t *emu, uintptr_t fnc);
void iFiiiiiip(x64emu_t *emu, uintptr_t fnc);
void iFpiiuuiu(x64emu_t *emu, uintptr_t fnc);
void iFpiupiii(x64emu_t *emu, uintptr_t fnc);
void iFpuuiuui(x64emu_t *emu, uintptr_t fnc);
void iFpupuuui(x64emu_t *emu, uintptr_t fnc);
void iFpuppppp(x64emu_t *emu, uintptr_t fnc);
void iFppiiuui(x64emu_t *emu, uintptr_t fnc);
void iFppiipii(x64emu_t *emu, uintptr_t fnc);
void iFppipipi(x64emu_t *emu, uintptr_t fnc);
void iFppipppp(x64emu_t *emu, uintptr_t fnc);
void iFpppiiii(x64emu_t *emu, uintptr_t fnc);
void iFpppiiuu(x64emu_t *emu, uintptr_t fnc);
void iFpppiipi(x64emu_t *emu, uintptr_t fnc);
void iFpppiuwu(x64emu_t *emu, uintptr_t fnc);
void iFppppiii(x64emu_t *emu, uintptr_t fnc);
void iFppppdpi(x64emu_t *emu, uintptr_t fnc);
void iFppppppp(x64emu_t *emu, uintptr_t fnc);
void uFuippppp(x64emu_t *emu, uintptr_t fnc);
void pFEppppip(x64emu_t *emu, uintptr_t fnc);
void pFifffppp(x64emu_t *emu, uintptr_t fnc);
void pFuupupup(x64emu_t *emu, uintptr_t fnc);
void pFpCuwwWW(x64emu_t *emu, uintptr_t fnc);
void pFpCuWCCC(x64emu_t *emu, uintptr_t fnc);
void pFpCuuwwp(x64emu_t *emu, uintptr_t fnc);
void pFpCuuuuu(x64emu_t *emu, uintptr_t fnc);
void pFppuuppp(x64emu_t *emu, uintptr_t fnc);
void pFppppuuu(x64emu_t *emu, uintptr_t fnc);
void pFpppppuu(x64emu_t *emu, uintptr_t fnc);
void pFppppppp(x64emu_t *emu, uintptr_t fnc);
void vFiiiiuuip(x64emu_t *emu, uintptr_t fnc);
void vFiupuiuup(x64emu_t *emu, uintptr_t fnc);
void vFiupuuuup(x64emu_t *emu, uintptr_t fnc);
void vFuiiiiiii(x64emu_t *emu, uintptr_t fnc);
void vFuiiiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuiiipiup(x64emu_t *emu, uintptr_t fnc);
void vFuiuiiiii(x64emu_t *emu, uintptr_t fnc);
void vFuiuiiiip(x64emu_t *emu, uintptr_t fnc);
void vFuuiiiiii(x64emu_t *emu, uintptr_t fnc);
void vFuuiiiuip(x64emu_t *emu, uintptr_t fnc);
void vFuuiiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuuiiuupp(x64emu_t *emu, uintptr_t fnc);
void vFuuiuiiii(x64emu_t *emu, uintptr_t fnc);
void vFuuiuiiip(x64emu_t *emu, uintptr_t fnc);
void vFuuuiiiii(x64emu_t *emu, uintptr_t fnc);
void vFuuuiuiii(x64emu_t *emu, uintptr_t fnc);
void vFuuuipipp(x64emu_t *emu, uintptr_t fnc);
void vFuuuuuuuu(x64emu_t *emu, uintptr_t fnc);
void vFuuuuufff(x64emu_t *emu, uintptr_t fnc);
void vFffffffff(x64emu_t *emu, uintptr_t fnc);
void vFpippiiuu(x64emu_t *emu, uintptr_t fnc);
void vFpippiipi(x64emu_t *emu, uintptr_t fnc);
void vFppiiipii(x64emu_t *emu, uintptr_t fnc);
void vFppppiipi(x64emu_t *emu, uintptr_t fnc);
void iFEpippppp(x64emu_t *emu, uintptr_t fnc);
void iFiiiiiiip(x64emu_t *emu, uintptr_t fnc);
void iFiiupiupi(x64emu_t *emu, uintptr_t fnc);
void iFuiifpppp(x64emu_t *emu, uintptr_t fnc);
void iFpiiiiipi(x64emu_t *emu, uintptr_t fnc);
void iFpuuiiiii(x64emu_t *emu, uintptr_t fnc);
void iFpupppppp(x64emu_t *emu, uintptr_t fnc);
void iFppIIIppp(x64emu_t *emu, uintptr_t fnc);
void iFpppiippp(x64emu_t *emu, uintptr_t fnc);
void iFpppipipi(x64emu_t *emu, uintptr_t fnc);
void iFpppipppp(x64emu_t *emu, uintptr_t fnc);
void iFppppiipi(x64emu_t *emu, uintptr_t fnc);
void iFpppppppp(x64emu_t *emu, uintptr_t fnc);
void uFuipppppp(x64emu_t *emu, uintptr_t fnc);
void pFuiiiuuuu(x64emu_t *emu, uintptr_t fnc);
void pFuupupipp(x64emu_t *emu, uintptr_t fnc);
void pFpCuwwWWu(x64emu_t *emu, uintptr_t fnc);
void pFpCuuuCup(x64emu_t *emu, uintptr_t fnc);
void pFpppuuLLu(x64emu_t *emu, uintptr_t fnc);
void vFuiiiiiiii(x64emu_t *emu, uintptr_t fnc);
void vFuiiiiiuip(x64emu_t *emu, uintptr_t fnc);
void vFuiiiiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuiuiiiiip(x64emu_t *emu, uintptr_t fnc);
void vFuiupuffup(x64emu_t *emu, uintptr_t fnc);
void vFuuiiiiiii(x64emu_t *emu, uintptr_t fnc);
void vFuuiuiiiii(x64emu_t *emu, uintptr_t fnc);
void vFuuiuiiiip(x64emu_t *emu, uintptr_t fnc);
void vFuuiuiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuuuiiiiip(x64emu_t *emu, uintptr_t fnc);
void vFuuuuuuuuu(x64emu_t *emu, uintptr_t fnc);
void vFuupiuiuuf(x64emu_t *emu, uintptr_t fnc);
void vFuffffffff(x64emu_t *emu, uintptr_t fnc);
void vFffuuuufff(x64emu_t *emu, uintptr_t fnc);
void vFddddddddd(x64emu_t *emu, uintptr_t fnc);
void vFpipppiipi(x64emu_t *emu, uintptr_t fnc);
void vFppiiipiii(x64emu_t *emu, uintptr_t fnc);
void vFpppppippp(x64emu_t *emu, uintptr_t fnc);
void iFEpiiiiipi(x64emu_t *emu, uintptr_t fnc);
void iFiiiiiiiip(x64emu_t *emu, uintptr_t fnc);
void iFiiiipiiip(x64emu_t *emu, uintptr_t fnc);
void iFdddpppppp(x64emu_t *emu, uintptr_t fnc);
void iFpipLpiiip(x64emu_t *emu, uintptr_t fnc);
void iFppiuiippL(x64emu_t *emu, uintptr_t fnc);
void iFpppiiuuii(x64emu_t *emu, uintptr_t fnc);
void iFpppiipiiu(x64emu_t *emu, uintptr_t fnc);
void iFppppppppp(x64emu_t *emu, uintptr_t fnc);
void pFEppiiuuLi(x64emu_t *emu, uintptr_t fnc);
void pFEppuippuu(x64emu_t *emu, uintptr_t fnc);
void pFpiiiiuuuu(x64emu_t *emu, uintptr_t fnc);
void pFpCuWCCuuu(x64emu_t *emu, uintptr_t fnc);
void pFpuuwwWWww(x64emu_t *emu, uintptr_t fnc);
void pFppiiuuuLL(x64emu_t *emu, uintptr_t fnc);
void pFppipppppp(x64emu_t *emu, uintptr_t fnc);
void vFiiiiiiiiiu(x64emu_t *emu, uintptr_t fnc);
void vFuiiiiiiiii(x64emu_t *emu, uintptr_t fnc);
void vFuiiiiiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuiuiiiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuuiiiiiiii(x64emu_t *emu, uintptr_t fnc);
void vFuuiiiiiuip(x64emu_t *emu, uintptr_t fnc);
void vFuuiiiiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuuiuiiiiip(x64emu_t *emu, uintptr_t fnc);
void vFuuiuiiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuuuuuuuiii(x64emu_t *emu, uintptr_t fnc);
void vFuuuuuuuuuu(x64emu_t *emu, uintptr_t fnc);
void vFuupiiupuuf(x64emu_t *emu, uintptr_t fnc);
void vFuffiiffiip(x64emu_t *emu, uintptr_t fnc);
void vFuddiiddiip(x64emu_t *emu, uintptr_t fnc);
void vFffffffffff(x64emu_t *emu, uintptr_t fnc);
void iFiiiiiiiiip(x64emu_t *emu, uintptr_t fnc);
void iFpuupiuiipp(x64emu_t *emu, uintptr_t fnc);
void iFppuuiiiiii(x64emu_t *emu, uintptr_t fnc);
void iFppuuiiuupi(x64emu_t *emu, uintptr_t fnc);
void iFppppiiuuii(x64emu_t *emu, uintptr_t fnc);
void pFpCuWCCuuCW(x64emu_t *emu, uintptr_t fnc);
void pFpuuuwwwwWW(x64emu_t *emu, uintptr_t fnc);
void pFppuiipuuii(x64emu_t *emu, uintptr_t fnc);
void pFpppppppppp(x64emu_t *emu, uintptr_t fnc);
void vFuiiiiiiiiip(x64emu_t *emu, uintptr_t fnc);
void vFuiiiiiiiuip(x64emu_t *emu, uintptr_t fnc);
void vFuiiiiiiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuiuiiiiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuuiuiiiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuuuuuuuuuuu(x64emu_t *emu, uintptr_t fnc);
void vFuuffiiffiip(x64emu_t *emu, uintptr_t fnc);
void vFuufffffffff(x64emu_t *emu, uintptr_t fnc);
void vFuuddiiddiip(x64emu_t *emu, uintptr_t fnc);
void vFuffffffffff(x64emu_t *emu, uintptr_t fnc);
void vFpipipiipiii(x64emu_t *emu, uintptr_t fnc);
void vFpipppiiiipi(x64emu_t *emu, uintptr_t fnc);
void iFEppppiiiiuu(x64emu_t *emu, uintptr_t fnc);
void iFiiiiiiiiiip(x64emu_t *emu, uintptr_t fnc);
void iFpipllippppp(x64emu_t *emu, uintptr_t fnc);
void iFppppiiuuiiL(x64emu_t *emu, uintptr_t fnc);
void pFEppuiipuuii(x64emu_t *emu, uintptr_t fnc);
void vFuuiiiiiiiuip(x64emu_t *emu, uintptr_t fnc);
void vFuuiiiiiiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuuuuuuuuuuuu(x64emu_t *emu, uintptr_t fnc);
void vFffffffffffff(x64emu_t *emu, uintptr_t fnc);
void vFpipppiiiipii(x64emu_t *emu, uintptr_t fnc);
void vFpippppiiiipi(x64emu_t *emu, uintptr_t fnc);
void iFEppppiiiiuui(x64emu_t *emu, uintptr_t fnc);
void iFpipppppppppp(x64emu_t *emu, uintptr_t fnc);
void iFpppllipppppp(x64emu_t *emu, uintptr_t fnc);
void iFpppppppppppp(x64emu_t *emu, uintptr_t fnc);
void pFEppiiuuuipii(x64emu_t *emu, uintptr_t fnc);
void pFpCuuWWwwCCup(x64emu_t *emu, uintptr_t fnc);
void pFpuuuWWWWWWWW(x64emu_t *emu, uintptr_t fnc);
void pFppiiuuuiupLp(x64emu_t *emu, uintptr_t fnc);
void vFuiiiiiiiiiuup(x64emu_t *emu, uintptr_t fnc);
void vFuuuuuuuuuuuuu(x64emu_t *emu, uintptr_t fnc);
void vFuffffffffffff(x64emu_t *emu, uintptr_t fnc);
void iFddddpppddpppp(x64emu_t *emu, uintptr_t fnc);
void iFpippuuuiipppp(x64emu_t *emu, uintptr_t fnc);
void iFpupiiiipppppp(x64emu_t *emu, uintptr_t fnc);
void pFpCuuwwWWWWuup(x64emu_t *emu, uintptr_t fnc);
void pFppppppppppppp(x64emu_t *emu, uintptr_t fnc);
void vFuffiiffiiffiip(x64emu_t *emu, uintptr_t fnc);
void vFuddiiddiiddiip(x64emu_t *emu, uintptr_t fnc);
void vFuuiiiiuuiiiiiii(x64emu_t *emu, uintptr_t fnc);
void vFfffffffffffffff(x64emu_t *emu, uintptr_t fnc);
void pFpppppppppppppppp(x64emu_t *emu, uintptr_t fnc);
void vFppuiiiiipuiiiiiiii(x64emu_t *emu, uintptr_t fnc);
void pFipppppppppppppppppppppp(x64emu_t *emu, uintptr_t fnc);
#if defined(HAVE_LD80BITS)
void DFD(x64emu_t *emu, uintptr_t fnc);
@@ -127,6 +979,13 @@ void KFKp(x64emu_t *emu, uintptr_t fnc);
#endif
void iFEv(x64emu_t *emu, uintptr_t fnc);
void lFEv(x64emu_t *emu, uintptr_t fnc);
void pFEv(x64emu_t *emu, uintptr_t fnc);
void pFppv(x64emu_t *emu, uintptr_t fnc);
void iFEvpp(x64emu_t *emu, uintptr_t fnc);
void iFEpvpp(x64emu_t *emu, uintptr_t fnc);
void iFEpvvppp(x64emu_t *emu, uintptr_t fnc);
void iFEpLvvpp(x64emu_t *emu, uintptr_t fnc);
void iFEpuvvppp(x64emu_t *emu, uintptr_t fnc);
#endif //__WRAPPER_H_
Loaded 100 of 166 files, more files were not shown because too many files have changed in this diff. Show more