Compare commits

...
Author SHA1 Message Date
Ryan Houdek c330da4992 FEXServerClient: Workaround sun_path 108 byte limit
We really don't want to do this, but in the case that the AF_UNIX path
is longer than the 108-byte limit that sun_path provides we don't really
have a choice. The alternative choice would be to switch /entirely/ away
from AF_UNIX and instead use pipes. We need a bandage fix for now, so
throw the socket in to a temp folder if the path is too long.
2026-07-02 16:49:28 -07:00
Ryan Houdek a04b0241c2 Docs: Update for release FEX-2605 2026-05-08 19:28:30 -07:00
Ryan Houdek 670fd19d33 Merge pull request #5486 from Sonicadvance1/151
Allocator: Mark large unmapped regions as DONTDUMP
2026-05-08 19:28:13 -07:00
Ryan Houdek a66544f3f4 Allocator: Mark large unmapped regions as DONTDUMP
coredump applications aren't smart enough to only dump resident pages,
so explicitly mark our 128TB and other mapped VA ranges as DONTDUMP.

This will speed up coredumps.
2026-05-08 16:27:04 -07:00
Ryan Houdek 1bfb3aefcc Merge pull request #5485 from Sonicadvance1/150
Windows: Setup `tu_override_uncached_as_cache_coherent` inside of dlls
2026-05-08 15:58:43 -07:00
Ryan Houdek b7bfbc3fcd Windows: Setup tu_override_uncached_as_cache_coherent inside of dlls
To not have this environment variable accidently be enabled on arm64
native Wine games, we need to set it from inside of FEX.

Requires the FEX dlls to set them directly rather than launch scripts.
2026-05-08 13:39:51 -07:00
Ryan Houdek e517f3259c Merge pull request #5484 from neobrain/fix_code_cache_no_guest_wrappers
CodeCache: Fix crash when guest library wrappers aren't installed
2026-05-07 10:59:32 -07:00
Tony Wasserka 8afda92a64 CodeCache: Fix crash when guest library wrappers aren't installed 2026-05-07 18:56:35 +02:00
Ryan Houdek ed216c8d4d Merge pull request #5449 from neobrain/opt_code_cache_writing
CodeCache: Slightly optimize cache file writing
2026-05-06 18:06:51 -07:00
Ryan Houdek 7506cb4ea1 Merge pull request #5483 from neobrain/fix_guest_wrapper_code_cache
CodeCache: Delay cache loading for guest library wrappers until after LoadLib
2026-05-06 18:04:55 -07:00
Tony Wasserka 60bc5944db CodeCache: Slightly optimize cache file writing
ftruncate only requires one call (and one extra seek) instead up to 64 manual
zero writes.
2026-05-06 17:08:15 +02:00
Tony Wasserka 8f0572283a Windows/CRT: Implement ftruncate and _chsize 2026-05-06 17:08:04 +02:00
Tony Wasserka b13b46eefe CodeCache: Delay cache loading for guest library wrappers until after LoadLib
These libraries need to be initialized before relocating their caches,
since the guest function hashes won't be registered before.
2026-05-05 16:29:39 +02:00
LC 4db2a98d7f Merge pull request #5481 from Sonicadvance1/148
win32: Query DCZID_EL0 so clzero works
2026-05-05 08:42:31 -04:00
LC 05ebb07753 Merge pull request #5482 from Sonicadvance1/149
OpcodeDispatcher: Optimize MMX pshufw
2026-05-05 08:41:22 -04:00
Ryan Houdek 694e68b838 Merge pull request #5468 from peppergrayxyz/proc_self_stat
read /proc/self/stat using %lu
2026-05-04 20:21:16 -07:00
Pepper Gray 78320e1433 read /proc/self/stat using %lu
building on clang/musl causes warnings:

```
FEX/Source/Tools/FEXInterpreter/ELFCodeLoader.h:782:29: warning: format specifies type 'unsigned long long *' but the argument has type 'uint64_t *' (aka 'unsigned long *') [-Wformat]
  776 |                             "%llu %llu %llu %*u %*u "   // 26 to 30
      |                              ~~~~
      |                              %lu
  777 |                             "%*u %*u %*u %*u %*u "      // 31 to 35
  778 |                             "%*u %*u %*d %*d %*u "      // 36 to 40
  779 |                             "%*u %*u %*u %*d %llu "     // 40 to 45
  780 |                             "%llu %llu %llu %llu %llu " // 46 to 50
  781 |                             "%llu",                     // 51
  782 |                             &map.start_code, &map.end_code, &map.start_stack, &map.start_data, &map.end_data, &map.start_brk,
      |                             ^~~~~~~~~~~~~~~
```

according to the [man page](https://man7.org/linux/man-pages/man5/proc_pid_stat.5.html)
`/proc/self/stat` uses `%lu`:

read the values as unsigned long (%lu) and then write them to
prctl_mm_map (platform specific format).

fixes: #5467
Signed-off-by: Pepper Gray <hello@peppergray.xyz>
2026-05-05 04:24:31 +02:00
Ryan Houdek 082e7b2695 InstcountCI: Update 2026-05-04 17:52:54 -07:00
Ryan Houdek cdbffb80c7 unittests: Adds a full coverage pshufw test 2026-05-04 17:52:53 -07:00
Ryan Houdek cb6c8cce55 OpcodeDispatcher: Optimize MMX pshufw
Found through writing a shuffle solver rather than an LLM.

Fixes #3785
2026-05-04 17:52:53 -07:00
Ryan Houdek 47e173e549 Merge pull request #5472 from peppergrayxyz/format
use portable format specifiers
2026-05-04 14:18:28 -07:00
Ryan Houdek 162bd4be97 win32: Query DCZID_EL0 so clzero works
EL0 registers are readable without going through the registry, but we
were failing to populate this register, which was causing clzero to not
be supported.
2026-05-04 12:42:18 -07:00
Ryan Houdek f0764aeafe Merge pull request #5480 from neobrain/refactor_musl_sigmask
SignalDelegator: Simplify support for musl's sigset_t
2026-05-04 10:39:42 -07:00
Ryan Houdek 1efed71696 Merge pull request #5479 from neobrain/refactor_drop_compile_service
FEXCore: Drop unused CompileService
2026-05-04 10:36:44 -07:00
Tony Wasserka 06d77c1c19 SignalDelegator: Simplify support for musl's sigset_t 2026-05-04 16:28:47 +02:00
Tony Wasserka 942d0c631a FEXCore: Drop unused CompileService 2026-05-04 15:52:34 +02:00
Pepper Gray abae5dd93b use portable format specifiers
building with clang/musl causes these warnings:

```
FEX/Source/Tools/FEXServer/ProcessPipe.cpp:100:96: warning: format specifies type 'ssize_t' (aka 'long') but the argument has type 'rlim_t' (aka 'unsigned long long') [-Wformat]
```

- cast platform specific MaxFDs members to uintmax_t and print as PRIuMAX
- use %zu for GetNumFilesOpen (size_t)

fix: #5471
Signed-off-by: Pepper Gray <hello@peppergray.xyz>
2026-05-04 11:20:55 +02:00
Ryan Houdek 93015a0266 Merge pull request #5458 from peppergrayxyz/largefile64
make 64bit symbols visible to enhance portability (musl)
2026-05-03 23:36:59 -07:00
Ryan Houdek d238db69d3 Merge pull request #5477 from peppergrayxyz/unistd
include missing header unistd.h
2026-05-03 15:18:41 -07:00
Ryan Houdek e0ead236b6 Merge pull request #5473 from peppergrayxyz/ObjectCacheRefCounter
remove dead code (ObjectCacheRefCounter)
2026-05-03 15:16:57 -07:00
Pepper Gray c548262664 include missing header unistd.h
build on clang/musl fails with:

```
FEX/unittests/APITests/Allocator.cpp:17:5: error: use of undeclared identifier 'close'
FEX/unittests/APITests/Allocator.cpp:23:5: error: use of undeclared identifier 'lseek'; did you mean 'fseek'?
FEX/unittests/APITests/Allocator.cpp:23:11: error: cannot initialize a parameter of type 'FILE *' (aka 'struct _IO_FILE *') with an lvalue of type 'int'
FEX/unittests/APITests/Allocator.cpp:24:5: error: use of undeclared identifier 'write'; did you mean '_IO_cookie_io_functions_t::write'?
FEX/unittests/APITests/Allocator.cpp:24:5: error: invalid use of non-static data member 'write'
```

include header to provide defintions

fix: #5476
Signed-off-by: Pepper Gray <hello@peppergray.xyz>
2026-05-03 15:49:40 +02:00
Pepper Gray bfc51e577f remove dead code (ObjectCacheRefCounter)
building using libc++ failes due to shared_mutex ObjectCacheRefCounter
inflating InternalThreadState beyond FEX_PAGE_SIZE, thus triggering
the static assert:

```
FEXCore/Debug/InternalThreadState.h:133:15: error: static assertion failed
FEX/FEXCore/include/FEXCore/Debug/InternalThreadState.h:133:145: note: expression evaluates to '7680 < 4096'
FEX/FEXCore/include/FEXCore/Debug/InternalThreadState.h:136:58: note: expression evaluates to '12288 == 8192'
```

remove `ObjectCacheRefCounter` as it is not used anywhere.

fix: #5456
Signed-off-by: Pepper Gray <hello@peppergray.xyz>
2026-05-03 15:13:47 +02:00
Ryan Houdek 85773995e1 Merge pull request #5470 from peppergrayxyz/header_redirect
fix include redirect for <poll.h> and <signal.h>
2026-05-03 04:41:18 -07:00
Pepper Gray 00b4777290 fix include redirect for <poll.h> and <signal.h>
building on musl/clang causes redirecting incorrect #includes warnings:

```
warning: redirecting incorrect #include <sys/poll.h> to <poll.h> [-W#warnings]
warning: redirecting incorrect #include <sys/signal.h> to <signal.h> [-W#warnings]
```

include headers instead of sys/headers.

fix: #5469
Signed-off-by: Pepper Gray <hello@peppergray.xyz>
2026-05-03 13:22:32 +02:00
Ryan Houdek 197e6de194 Merge pull request #5462 from peppergrayxyz/uc_sigmask
determine sigset_t fieldname to enhance portability (musl)
2026-05-03 03:48:53 -07:00
Ryan Houdek 9908ea4c2f Merge pull request #5466 from peppergrayxyz/libgen_h
include <libgen.h> for basename
2026-05-03 03:46:43 -07:00
Ryan Houdek c402b15bd3 Merge pull request #5464 from peppergrayxyz/tgkill
add header and classpath for tgkill
2026-05-03 03:46:07 -07:00
Ryan Houdek a3f3118ac5 Merge pull request #5460 from peppergrayxyz/sigset_t
use <signal.h> instead of glibc header to enhance portability (musl)
2026-05-03 03:18:20 -07:00
Pepper Gray b1aab0e498 determine sigset_t fieldname to enhance portability (musl)
musl build fails due to access to internal glibc member:

```
FEX/Source/Tools/LinuxEmulation/LinuxSyscalls/SignalDelegator.cpp:655:39: error: no member named '__val' in '__sigset_t'
  655 |       .SigMask = _context->uc_sigmask.__val[0],
      |                  ~~~~~~~~~~~~~~~~~~~~ ^
1 error generated.
```

add check to determine private glibc or musl member name or throw an error.

fixes: #5461
Signed-off-by: Pepper Gray <hello@peppergray.xyz>
2026-05-03 12:17:09 +02:00
Pepper Gray 927c0ce54a include <libgen.h> for basename
building on clang/musl build fails due to missing symbol:

```
/run/host/home/pepper/dev/ghrepos/FEX/Source/Tools/FEXOfflineCompiler/Main.cpp:321:35: error: use of undeclared identifier 'basename'
  321 |   auto CommandName = std::string {basename(argv[0])} + " " + (argc > 1 ? argv[1] : "");
      |                                   ^~~~~~~~
/run/host/home/pepper/dev/ghrepos/FEX/Source/Tools/FEXOfflineCompiler/Main.cpp:327:43: error: use of undeclared identifier 'basename'
  327 |     fmt::print("Usage: {} <command>\n\n", basename(argv[0]));
      |                                           ^~~~~~~~
```

include missing header.

fixes: #5465
Signed-off-by: Pepper Gray <hello@peppergray.xyz>
2026-05-03 12:10:07 +02:00
Pepper Gray 57d9dc037d add header and classpath for tgkill
building on clang/musl fails with:

```
FEX/Source/Tools/LinuxEmulation/LinuxSyscalls/GdbServer.cpp:1174:5: error: use of undeclared identifier 'tgkill'
 1174 |     tgkill(::getpid(), ::getpid(), SIGKILL);
      |     ^~~~~~
1 error generated.
```

include and use `FHU::Syscalls::tgkill`.

fixes: #5463
Signed-off-by: Pepper Gray <hello@peppergray.xyz>
2026-05-03 11:50:23 +02:00
Pepper Gray e3cfe28848 use <signal.h> instead of glibc header to enhance portability (musl)
building using musl fails with:

```
FEX/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.h:33:10: fatal error: 'bits/types/sigset_t.h' file not found
   33 | #include <bits/types/sigset_t.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
```

`<bits/types/sigset_t.h>` is a glibc internal header, use <signal.h> instead.

fixes: #5459
Signed-off-by: Pepper Gray <hello@peppergray.xyz>
2026-05-03 11:03:38 +02:00
Pepper Gray ac91f583b8 make 64bit symbols visible to enhance portability (musl)
building using clang/musl fails with:

```
FEX/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/Types.h:548:5: error: member access into incomplete type 'const struct statfs64'
  548 |     COPY(f_bsize);
      |     ^
```

add `_LARGEFILE64_SOURCE` to define large-file feature macros

fix: #5457
Signed-off-by: Pepper Gray <hello@peppergray.xyz>
2026-05-03 10:52:09 +02:00
Ryan Houdek 215658bf29 Merge pull request #5455 from peppergrayxyz/sys_prctl
use <sys/prctl.h> to enhance portability (clang)
2026-05-02 15:11:33 -07:00
Pepper Gray 92b1a6ea8a use <sys/prctl.h> to enhance portability (clang)
using <sys/prctl.h> and <linux/prctl.h> simultaneously causes clang to
fail:

```
In file included from FEX/FEXCore/Source/Utils/AllocatorHooks.cpp:6:
/usr/include/sys/prctl.h:88:8: error: redefinition of 'prctl_mm_map'
   88 | struct prctl_mm_map {
      |        ^
/usr/include/linux/prctl.h:134:8: note: previous definition is here
  134 | struct prctl_mm_map {
      |        ^
1 error generated.
```

prefer <sys/prctl.h> and do not include <linux/prctl.h>

fix: #5454
Signed-off-by: Pepper Gray <hello@peppergray.xyz>
2026-05-02 15:36:40 +02:00
Ryan Houdek 8ab00758be Merge pull request #5448 from bylaws/claudefix6
X87: Fix FXTRACT with Inf and NaN inputs
2026-04-30 14:42:08 -07:00
Ryan Houdek e91bda7765 Merge pull request #5447 from bylaws/claudefix5
SoftFloat: Fix FSCALE(0, +Inf) to raise IE and return a quiet NaN
2026-04-30 14:41:24 -07:00
Ryan Houdek 9db211ac97 Merge pull request #5446 from bylaws/claudefix4
OpcodeDispatcher: Fix FIST 16-bit IE for denormal inputs
2026-04-30 14:40:41 -07:00
Ryan Houdek b1381fd3b7 Merge pull request #5444 from bylaws/claudefix2
VectorOps: Fix MAXPS/MAXPD NaN and signed-zero tie selection
2026-04-30 14:39:56 -07:00
Ryan Houdek e5f6a7d85e Merge pull request #5450 from neobrain/fix_code_cache_portable
CodeCache: Make FEXServer call FEXOfflineCompiler by absolute path
2026-04-30 14:17:16 -07:00
Ryan Houdek feae76fc4f Merge pull request #5451 from Sonicadvance1/146
arm64ec: Fixes crash in many games with SDL+Dualsense
2026-04-30 14:16:06 -07:00
Ryan Houdek 015f3cffb9 arm64ec: Fixes crash in many games with SDL+Dualsense
We were pointing to an incorrect function pointer and exploding when a
pending suspend doorbell had occured.
2026-04-30 12:59:53 -07:00
Tony Wasserka 3e5c17ae80 CodeCache: Make FEXServer call FEXOfflineCompiler by absolute path
In portable mode, FEXOfflineCompiler may not be in PATH (and if it is, it's
most likely not a compatible version). Instead, use the executable next to
the FEXServer binary.
2026-04-30 17:14:22 +02:00
Billy Laws 3e278b42f8 InstcountCI: Update 2026-04-29 02:54:34 +00:00
Billy Laws fa953445e9 InstcountCI: Update 2026-04-29 02:53:07 +00:00
Billy Laws a412b1d3b7 InstcountCI: Update 2026-04-29 02:43:19 +00:00
Billy Laws fc680388e3 X87: Fix FXTRACT with Inf and NaN inputs
Both the default F80 softfloat wrappers (FXTRACT_SIG/FXTRACT_EXP) and
the reduced-precision F64 dispatcher fell through to the generic
exponent/significand extraction for Inf and NaN inputs, producing
finite garbage. The F80 wrapper returns input unchanged in the
significand slot and +Inf (or NaN) in the exponent slot; the F64
dispatcher detects the exponent-all-ones case and selects the proper
Inf/NaN result before the existing zero-case fold.
2026-04-29 02:34:41 +00:00
Billy Laws 7c260b45e1 unittests/ASM: Adds tests for FXTRACT Inf/NaN 2026-04-29 02:29:23 +00:00
Ryan Houdek 098c4c57b4 Merge pull request #5443 from bylaws/claudefix1
X86Features: Fix AVX/RAND/PCMLULQDQ feature detection on intel
2026-04-28 19:25:15 -07:00
Billy Laws 7c826e35b4 SoftFloat: Fix FSCALE(0, +Inf) to raise IE
The lhs==0 short-circuit in X80SoftFloat::FSCALE returned lhs
unchanged without calling extF80_mul, so the 0*Inf invalid-operation
case never set softfloat_flag_invalid. Detect +Inf rhs explicitly
in the zero-lhs path and raise the flag, returning QNaN to match
hardware.
2026-04-29 02:17:03 +00:00
Billy Laws 1bd2ff3fc3 unittests/ASM: Adds test for FSCALE(0, +Inf) raising IE 2026-04-29 02:16:57 +00:00
Billy Laws e2fc91fc15 OpcodeDispatcher: Fix FIST 16-bit IE for denormal inputs
The special-value check masked the biased exponent with 0x7fff and
then used TestNZ, so it triggered on Exp==0 (denormals) instead of
Exp==0x7fff (NaN/Inf). Replace the TestNZ with SubWithFlags against
0x7fff so EQ only fires for genuine NaN/Inf.
2026-04-29 02:10:35 +00:00
Billy Laws cf20647b25 unittests/ASM: Adds test for 16-bit FIST with denormal input not setting IE 2026-04-29 02:09:54 +00:00
Billy Laws 8d7071e549 VectorOps: Fix MAXPS/MAXPD NaN and signed-zero tie selection
fcmgt returns false on NaN, so the existing polarity in the non-SVE
fcmgt+bit sequences and in the SVE predicate-merge picked the wrong
source on NaN/tie. Swap the compare operands and flip bit<->bif / add
a predicate not to match x86 second source wins behaviour.
2026-04-29 02:00:58 +00:00
Billy Laws fb006b2c6d unittests/ASM: Adds test for MAXPS/MAXPD NaN and signed-zero tie 2026-04-29 01:57:41 +00:00
Billy Laws 9039eeb3cd X86Features: Fix AVX/RAND/PCMLULQDQ feature detection on intel 2026-04-29 01:57:18 +00:00
Billy Laws dd0702d30f unittests/ASM: Mark SSE4a/CLZERO as required for tests using them 2026-04-29 01:56:35 +00:00
LC 886faf0bd4 Merge pull request #5442 from neobrain/refactor_code_cache_check
CodeCache: Move bounds check to FEXOfflineCompiler
2026-04-28 19:47:52 -04:00
Tony Wasserka 86e28c6d34 CodeCache: Move bounds check to FEXOfflineCompiler
The previous check site would easily fail when loading caches for binaries
with multiple executable sections.

It makes much more sense to refuse generating caches anyway: The condition
effectively checked for invalid code map entries, so FEXOfflineCompiler
should reject them as bad inputs.
2026-04-28 17:31:20 +02:00
LC 821efab8aa Merge pull request #5440 from Sonicadvance1/145
OpcodeDispatcher: Ensure FIST* operations avoid TSO/GPR
2026-04-28 07:55:10 -04:00
Ryan Houdek 5295365dd0 InstcountCI: Update 2026-04-27 17:55:49 -07:00
Ryan Houdek 788959a98c OpcodeDispatcher: Ensure FIST* operations avoid TSO/GPR
Noticed this while benchmarking that the FIST* operations were
converting to a GPR, and then storing to memory using an atomic TSO
operation. This should be instead listening to the vector TSO
configuration option. This gives a 3.8x - 6.05x improvement in my
microbench.

Additionally when possible, make sure to use vector conversion
instructions when possible. It's lower cost to avoid the FPR->GPR
transfer, but we can only use it for 64-bit FIST operations. Microbench
couldn't show a difference for that on my platform, but that's because
it's float pipeline bounded regardless. Should help X-class Cortex and
newer Cortex-A.
2026-04-27 17:48:45 -07:00
LC dd145aaa88 Merge pull request #5439 from Sonicadvance1/144
Fix push/pop fs/gs segments and unittests
2026-04-27 19:43:44 -04:00
Ryan Houdek 34b3adc23d unittests/ASM: Adds unit test to ensure push/pop segment of o16 works
Only ensures we are pushing and popping the correct size, not any of the
selector data within it, as 64-bit systems with the FSGSBase extension
don't use them selectors anyway.

Can't test the 32-bit side currently because we would corrupt FS/GS in
CI and the host testharnessrunner can't fix that right now.
2026-04-27 15:21:47 -07:00
Simon Scherer ab14882761 FEXCore: Fix 2byte stack access for 0x66 PUSH/POP FS/GS 2026-04-27 15:21:11 -07:00
LC 7dc1f54fb6 Merge pull request #5435 from Sonicadvance1/143
unittests/ASM: Add unittests to ensure correct cmpxchg8b/16b flag setting
2026-04-25 10:34:07 -04:00
Ryan Houdek c09fb03eda unittests/ASM: Add unittests to ensure correct cmpxchg8b/16b flag setting 2026-04-25 00:46:40 -07:00
Ryan Houdek dbf2761fb7 InstcountCI: Update 2026-04-25 00:45:05 -07:00
Ryan Houdek fd1378f778 InstcountCI: Fix incorrect instruction 2026-04-25 00:43:50 -07:00
Simon Scherer 819dcee3ad FEXCore: Fix wrong shift value to extract NZCV in CmpPairZ 2026-04-25 00:41:24 -07:00
LC 4b02c04afc Merge pull request #5429 from Sonicadvance1/142
Steam/CompatTool: Fixes Graphics Provider path handling
2026-04-23 20:13:13 -04:00
Ryan Houdek deed99e7a3 Merge pull request #5425 from pmatos/f64-atan-fyl2x
JIT-inline F64ATAN and F64FYL2X for reduced precision x87 path
2026-04-23 15:16:04 -07:00
Ryan Houdek 7bffc4a177 Steam/CompatTool: Fixes Graphics Provider path handling
Graphics provider needs to be a path to a json file in the root of the
rootfs. Make sure to strip the filepath off to get the directory.

Misunderstood the assignment before.
2026-04-23 15:13:42 -07:00
Ryan Houdek 701555e400 Merge pull request #5428 from Sonicadvance1/141
Steam/CompatTool: Support `STEAM_COMPAT_GRAPHICS_PROVIDER` for rootfs path
2026-04-21 12:50:22 -07:00
Ryan Houdek 49fa86d0b5 Steam/CompatTool: Support STEAM_COMPAT_GRAPHICS_PROVIDER for rootfs path
If we have been provided a graphics provider path through an environment
variable, then use that path directly rather than searching.
2026-04-21 12:37:40 -07:00
Paulo Matos adbace8810 instcountci: JIT-inline F64ATAN and F64FYL2X for reduced precision x87 path 2026-04-21 20:23:45 +02:00
Paulo Matos 050138bcea asm_tests: JIT-inline F64ATAN and F64FYL2X for reduced precision x87 path 2026-04-21 20:23:45 +02:00
Paulo Matos db50b04663 JIT-inline F64ATAN and F64FYL2X for reduced precision x87 path 2026-04-21 12:09:55 +02:00
LC 59755ec115 Merge pull request #5426 from Sonicadvance1/139
Snapdragon X2 Elite fixes
2026-04-20 11:53:51 -04:00
Ryan Houdek 856fb1e636 Snapdragon X2 Elite fixes
- RNDRRS is still broken on this CPU
- Fault granularity checking needs to use loads
  - stlxp does monitor check before alignment check, use loads for all
    for consistency
  - Fault granularity is still 16B which matches LSE2 requirements.
- X2E still only ships a 19.2Mhz cycle counter, so still only
  ARMv9.0-a hardware
- Adds product name to CPUID
  - Oryon-3 being CPU PartID 2 isn't a mistake.
  - No distinction between Oryon-1 and Oryon-2, both are partid 1.

cpuinfo:
```
processor   : 0
BogoMIPS    : 38.40
Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm uscat ilrcpc flagm ssbs sb paca pacg dcpodp sve2 sveaes svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 rng ecv afp rpres
CPU implementer   : 0x51
CPU architecture: 8
CPU variant : 0x1
CPU part    : 0x002
CPU revision      : 1
```
2026-04-19 14:34:44 -07:00
Ryan Houdek d41d52b889 Merge pull request #5419 from pmatos/f64-scale-f2xm1
JIT-inline F64SCALE and F64F2XM1 for reduced precision x87 path
2026-04-17 14:38:22 -07:00
Paulo Matos 18f69fb16d instcountci: JIT-inline F64SCALE and F64F2XM1 for reduced precision x87 path 2026-04-17 17:28:13 +02:00
Paulo Matos d165711f2e asm_tests: JIT-inline F64SCALE and F64F2XM1 for reduced precision x87 path 2026-04-16 11:24:24 +02:00
Paulo Matos 6bf19ffe37 JIT-inline F64SCALE and F64F2XM1 for reduced precision x87 path 2026-04-16 11:24:19 +02:00
LC 441116e1e6 Merge pull request #5421 from Sonicadvance1/136
Scripts: Move arch check first in InstallFEX
2026-04-15 16:24:04 -04:00
Ryan Houdek ce97ef0ab1 Scripts: Move arch check first in InstallFEX
Don't give people false hope that the script might work on distros that
aren't Ubuntu.

Fixes #5420
2026-04-15 13:01:37 -07:00
LC 2ea0de92f4 Merge pull request #5418 from Sonicadvance1/135
ArchHelpers: Allow atomic memory operations in non-JIT handler
2026-04-15 07:22:25 -04:00
Ryan Houdek 14580c4675 ArchHelpers: Allow atomic memory operations in non-JIT handler
`Detroit: Become Human` decided to use unaligned CriticalSections. So
this workarounds that.
2026-04-14 13:38:41 -07:00
104 changed files with 3005 additions and 491 deletions

No files matched your search

+2
View File
@@ -194,6 +194,8 @@ if (ENABLE_GDB_SYMBOLS)
add_compile_definitions(GDB_SYMBOLS_ENABLED=1)
endif()
add_compile_definitions(_LARGEFILE64_SOURCE)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Bin)
+19
View File
@@ -260,6 +260,10 @@ struct FEX_PACKED X80SoftFloat {
if (lhs.Top.Exponent == 0x0 && lhs.Significand == 0x0) {
return lhs;
}
// Inf/NaN pass through unchanged in the significand slot.
if (lhs.Top.Exponent == 0x7FFF) {
return lhs;
}
X80SoftFloat Tmp = lhs;
Tmp.Top.Exponent = 0x3FFF;
Tmp.Top.Sign = lhs.Top.Sign;
@@ -288,6 +292,14 @@ struct FEX_PACKED X80SoftFloat {
X80SoftFloat Result(1, 0x7FFFUL, 0x8000'0000'0000'0000UL);
return Result;
}
// +/-Inf returns +Inf in the exponent slot; NaN propagates.
if (lhs.Top.Exponent == 0x7FFF) {
if ((lhs.Significand & 0x7FFFFFFFFFFFFFFFULL) == 0) {
X80SoftFloat Result(0, 0x7FFFUL, 0x8000'0000'0000'0000UL);
return Result;
}
return lhs;
}
int32_t TrueExp = lhs.Top.Exponent - ExponentBias;
return i32_to_extF80(TrueExp);
@@ -324,6 +336,13 @@ struct FEX_PACKED X80SoftFloat {
#else
extFloat80_t Zero {0, 0};
if (extF80_eq(state, lhs, Zero)) {
// FSCALE(0, +Inf) is 0 * Inf, which is invalid. FSCALE(0, anything
// else) is still 0.
if (rhs.Top.Exponent == 0x7FFF && rhs.Top.Sign == 0 && (rhs.Significand & 0x7FFFFFFFFFFFFFFFULL) == 0) {
state->exceptionFlags |= softfloat_flag_invalid;
X80SoftFloat QNaN(0, 0x7FFFUL, 0xC000000000000000ULL);
return QNaN;
}
return lhs;
}
X80SoftFloat Int = FRNDINT(state, rhs, softfloat_round_minMag);
@@ -12,7 +12,6 @@
#include <cstdint>
#ifndef _WIN32
#include <linux/prctl.h>
#include <sys/prctl.h>
#endif
+3 -1
View File
@@ -92,6 +92,7 @@ namespace ProductNames {
static const char ARM_AppleSilicon[] = "Apple Silicon";
static const char ARM_ORYON_1[] = "Oryon-1";
static const char ARM_ORYON_3[] = "Oryon-3";
static const char ARM_Ampere_1[] = "AmpereOne";
static const char ARM_Ampere_1A[] = "AmpereOneA";
static const char ARM_Ampere_1B[] = "AmpereOneB";
@@ -186,8 +187,9 @@ void CPUIDEmu::SetupHostHybridFlag() {
// CPU priority order
// This is mostly arbitrary but will sort by some sort of CPU priority by performance
// Relative list so things they will commonly end up in big.little configurations sort of relate
static constexpr std::array<CPUMIDR, 67> CPUMIDRs = {{
static constexpr std::array<CPUMIDR, 68> CPUMIDRs = {{
// Typically big CPU cores
{0x51, 0x002, 1, ProductNames::ARM_ORYON_3}, // Qualcomm Oryon-3
{0x51, 0x001, 1, ProductNames::ARM_ORYON_1}, // Qualcomm Oryon-1
{0x61, 0x039, 1, ProductNames::ARM_Avalanche_M2Max}, // Apple Avalanche (M2 Max)
+4 -17
View File
@@ -300,12 +300,10 @@ bool CodeCache::SaveData(Core::InternalThreadState& Thread, int fd, const Execut
::write(fd, Relocations.data(), Relocations.size() * sizeof(Relocations[0]));
// Pad to next page in file so that the CodeBuffer can be mmap'ed into process on load
char Zero[64] {};
auto Off = lseek(fd, 0, SEEK_CUR);
while (Off != AlignUp(Off, Utils::FEX_PAGE_SIZE)) {
auto BytesToWrite = std::min(AlignUp(Off, Utils::FEX_PAGE_SIZE) - Off, sizeof(Zero));
::write(fd, Zero, BytesToWrite);
Off += BytesToWrite;
{
auto AlignedSize = AlignUp(lseek(fd, 0, SEEK_CUR), Utils::FEX_PAGE_SIZE);
::ftruncate(fd, AlignedSize);
lseek(fd, AlignedSize, SEEK_SET);
}
// Dump the host code (relocated for position-independent serialization)
@@ -383,17 +381,6 @@ bool CodeCache::LoadData(Core::InternalThreadState* Thread, std::byte* MappedCac
MappedCacheFile += std::span {BlockPtr.second.CodePages}.size_bytes();
}
// Consistency check: VMA regions at the top and end should belong to the same file
auto [min_val, max_val] = ranges::minmax_element(BlockList, std::less {}, &decltype(BlockList)::value_type::first);
auto MinBound = CTX.SyscallHandler->LookupExecutableFileSection(Thread, min_val->first + BinarySection.FileStartVA);
auto MaxBound = CTX.SyscallHandler->LookupExecutableFileSection(Thread, max_val->first + BinarySection.FileStartVA);
if (&MinBound->FileInfo != &BinarySection.FileInfo || &MaxBound->FileInfo != &BinarySection.FileInfo) {
ERROR_AND_DIE_FMT("Cached blocks offsets {:#x}-{:#x} out of bounds for guest library {} ({:016x} @ {:#x}) while trying to load "
"section {:#x}-{:#x}!",
min_val->first, max_val->first, BinarySection.FileInfo.Filename, BinarySection.FileInfo.FileId,
BinarySection.FileStartVA, BinarySection.BeginVA, BinarySection.EndVA);
}
// Constrain BlockList to the given ExecutableFileSectionInfo
LOGMAN_THROW_A_FMT(ranges::is_sorted(BlockList, [](auto& a, auto& b) { return a.first < b.first; }), "Expected sorted block list");
auto begin = ranges::lower_bound(BlockList, BinarySection.BeginVA - BinarySection.FileStartVA, std::less {}, &BlockListEntry::first);
@@ -549,6 +549,10 @@ void Dispatcher::EmitDispatcher() {
EmitF64Sin();
EmitF64Cos();
EmitF64Tan();
EmitF64F2XM1();
EmitF64Scale();
EmitF64Atan();
EmitF64FYL2X();
// Interpreter fallbacks
{
@@ -1246,6 +1250,495 @@ void Dispatcher::EmitF64Tan() {
dc64(0x4160'0000'0000'0000ULL); // 2^23
}
void Dispatcher::EmitF64Scale() {
// Computes result = src1 * 2^trunc(src2).
// Input: VTMP1 = base (src1), VTMP2 = exponent (src2). Output: VTMP1.
F64ScaleHandlerAddress = GetCursorAddress<uint64_t>();
ARMEmitter::ForwardLabel Fallback;
// save nzcv
mrs(TMP1, ARMEmitter::SystemRegister::NZCV);
str(TMP1.W(), STATE.R(), offsetof(FEXCore::Core::CpuStateFrame, State.flags[24]));
// n = trunc(src2).
frintz(VTMP2.D(), VTMP2.D());
// NaN check: NaN != NaN sets V flag.
fcmp(VTMP2.D(), VTMP2.D());
(void)b(ARMEmitter::Condition::CC_VS, &Fallback);
fcvtzs(ARMEmitter::Size::i64Bit, TMP1, VTMP2.D());
// Range check: int_n in [-1022, 1023].
cmn(ARMEmitter::Size::i64Bit, TMP1, 1022);
(void)b(ARMEmitter::Condition::CC_LT, &Fallback);
cmp(ARMEmitter::Size::i64Bit, TMP1, 1023);
(void)b(ARMEmitter::Condition::CC_GT, &Fallback);
// 2^n, then result = src1 * 2^n.
add(ARMEmitter::Size::i64Bit, TMP1, TMP1, 1023);
lsl(ARMEmitter::Size::i64Bit, TMP1, TMP1, 52);
fmov(ARMEmitter::Size::i64Bit, VTMP2.D(), TMP1);
fmul(VTMP1.D(), VTMP1.D(), VTMP2.D());
// restore nzcv
ldr(TMP1.W(), STATE.R(), offsetof(FEXCore::Core::CpuStateFrame, State.flags[24]));
msr(ARMEmitter::SystemRegister::NZCV, TMP1);
ret();
// Fallback path.
(void)Bind(&Fallback);
str<ARMEmitter::IndexType::PRE>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, -16);
ldr(TMP1, STATE_PTR(CpuStateFrame, Pointers.FallbackHandlerPointers[FEXCore::Core::OPINDEX_F64SCALE].ABIHandler));
ldr(TMP4, STATE_PTR(CpuStateFrame, Pointers.FallbackHandlerPointers[FEXCore::Core::OPINDEX_F64SCALE].Func));
blr(TMP1);
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, 16);
ret();
}
void Dispatcher::EmitF64F2XM1() {
// JIT-inlined double-precision 2^x - 1 for x in [-1, 1].
// Uses argument reduction: split x into n = round(x) and r = x - n,
// then compute 2^x - 1 = 2^n * (2^r - 1) + (2^n - 1).
// 2^r - 1 is approximated via a 13-term Horner polynomial in r.
// Input in VTMP1.D(), output in VTMP1.D().
F64F2XM1HandlerAddress = GetCursorAddress<uint64_t>();
constexpr auto Accum = ARMEmitter::VReg::v2;
ARMEmitter::ForwardLabel Fallback;
ARMEmitter::ForwardLabel OneLabel;
ARMEmitter::ForwardLabel C1Label, C2Label, C3Label, C4Label, C5Label, C6Label;
ARMEmitter::ForwardLabel C7Label, C8Label, C9Label, C10Label, C11Label, C12Label, C13Label;
// Save q2.
str<ARMEmitter::IndexType::PRE>(ARMEmitter::QReg::q2, ARMEmitter::Reg::rsp, -16);
// save nzcv
mrs(TMP1, ARMEmitter::SystemRegister::NZCV);
str(TMP1.W(), STATE.R(), offsetof(FEXCore::Core::CpuStateFrame, State.flags[24]));
// Range check: |x| > 1.0 -> fallback.
fabs(VTMP2.D(), VTMP1.D());
ldr(Accum.D(), &OneLabel);
fcmp(VTMP2.D(), Accum.D());
(void)b(ARMEmitter::Condition::CC_HI, &Fallback);
// Argument reduction: n = round(x), r = x - n.
frinta(VTMP2.D(), VTMP1.D());
fcvtzs(ARMEmitter::Size::i64Bit, TMP1, VTMP2.D());
fsub(Accum.D(), VTMP1.D(), VTMP2.D());
// scale = 2^n, scale_m1 = 2^n - 1.
// TMP1 = scale bits, TMP3 = scale_m1 bits, Accum = r.
add(ARMEmitter::Size::i64Bit, TMP1, TMP1, 1023);
lsl(ARMEmitter::Size::i64Bit, TMP1, TMP1, 52);
fmov(ARMEmitter::Size::i64Bit, VTMP2.D(), TMP1);
ldr(VTMP1.D(), &OneLabel);
fsub(VTMP1.D(), VTMP2.D(), VTMP1.D());
fmov(ARMEmitter::Size::i64Bit, TMP3, VTMP1.D());
// Horner polynomial: p = c1 + r * (c2 + r * (... + r * c13)).
ldr(VTMP1.D(), &C13Label);
ldr(VTMP2.D(), &C12Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C11Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C10Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C9Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C8Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C7Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C6Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C5Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C4Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C3Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C2Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C1Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
// q = r * p, then result = scale * q + scale_m1.
fmul(VTMP1.D(), Accum.D(), VTMP1.D());
fmov(ARMEmitter::Size::i64Bit, Accum.D(), TMP1);
fmov(ARMEmitter::Size::i64Bit, VTMP2.D(), TMP3);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
// restore nzcv
ldr(TMP1.W(), STATE.R(), offsetof(FEXCore::Core::CpuStateFrame, State.flags[24]));
msr(ARMEmitter::SystemRegister::NZCV, TMP1);
// Restore q2 and return.
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::QReg::q2, ARMEmitter::Reg::rsp, 16);
ret();
// Fallback path.
(void)Bind(&Fallback);
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::QReg::q2, ARMEmitter::Reg::rsp, 16);
str<ARMEmitter::IndexType::PRE>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, -16);
ldr(TMP1, STATE_PTR(CpuStateFrame, Pointers.FallbackHandlerPointers[FEXCore::Core::OPINDEX_F64F2XM1].ABIHandler));
ldr(TMP4, STATE_PTR(CpuStateFrame, Pointers.FallbackHandlerPointers[FEXCore::Core::OPINDEX_F64F2XM1].Func));
blr(TMP1);
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, 16);
ret();
// Constant pool
Align(16);
(void)Bind(&OneLabel);
dc64(0x3FF0'0000'0000'0000ULL); // 1.0
(void)Bind(&C1Label);
dc64(0x3FE6'2E42'FEFA'39EFULL); // ln(2)
(void)Bind(&C2Label);
dc64(0x3FCE'BFBD'FF82'C58EULL);
(void)Bind(&C3Label);
dc64(0x3FAC'6B08'D704'A0BEULL);
(void)Bind(&C4Label);
dc64(0x3F83'B2AB'6FBA'4E76ULL);
(void)Bind(&C5Label);
dc64(0x3F55'D87F'E78A'672FULL);
(void)Bind(&C6Label);
dc64(0x3F24'3091'2F86'C785ULL);
(void)Bind(&C7Label);
dc64(0x3EEF'FCBF'C588'B0C2ULL);
(void)Bind(&C8Label);
dc64(0x3EB6'2C02'23A5'C821ULL);
(void)Bind(&C9Label);
dc64(0x3E7B'5253'D395'E7C0ULL);
(void)Bind(&C10Label);
dc64(0x3E3E'4CF5'158B'8EC5ULL);
(void)Bind(&C11Label);
dc64(0x3DFE'8CAC'7351'BB20ULL);
(void)Bind(&C12Label);
dc64(0x3DBC'3BD6'50FC'2981ULL);
(void)Bind(&C13Label);
dc64(0x3D78'1619'3166'D0F5ULL);
}
// JIT-inlined double-precision atan2 for the F64 reduced precision x87 path.
// Input: VTMP1 = y, VTMP2 = x. Output: VTMP1 = atan2(y, x).
// Algorithm: 20-term Horner polynomial from ARM optimized-routines atan_data.c.
// atan(z) = z + z^3 * P(z^2), with range reduction to [0,1] and quadrant adjustment.
void Dispatcher::EmitF64Atan() {
F64AtanHandlerAddress = GetCursorAddress<uint64_t>();
constexpr auto Accum = ARMEmitter::VReg::v2;
ARMEmitter::ForwardLabel Fallback;
ARMEmitter::ForwardLabel NoSwap, PosX, NegY;
ARMEmitter::ForwardLabel PiOver2Label, PiLabel;
ARMEmitter::ForwardLabel C0Label, C1Label, C2Label, C3Label, C4Label, C5Label, C6Label;
ARMEmitter::ForwardLabel C7Label, C8Label, C9Label, C10Label, C11Label, C12Label, C13Label;
ARMEmitter::ForwardLabel C14Label, C15Label, C16Label, C17Label, C18Label, C19Label;
// Stack layout: [sp] = q2 (16B), [sp+16] = y bits (8B), [sp+24] = x bits (8B).
str<ARMEmitter::IndexType::PRE>(ARMEmitter::QReg::q2, ARMEmitter::Reg::rsp, -32);
mrs(TMP1, ARMEmitter::SystemRegister::NZCV);
str(TMP1.W(), STATE.R(), offsetof(FEXCore::Core::CpuStateFrame, State.flags[24]));
fmov(ARMEmitter::Size::i64Bit, TMP1, VTMP2.D());
fmov(ARMEmitter::Size::i64Bit, TMP2, VTMP1.D());
str(TMP2, ARMEmitter::Reg::rsp, 16);
str(TMP1, ARMEmitter::Reg::rsp, 24);
// Compute |x|, |y|, pack sign/swap flags into TMP1 = (sign_x<<2)|(sign_y<<1)|swap.
fabs(Accum.D(), VTMP2.D());
fabs(VTMP2.D(), VTMP1.D());
fcmp(VTMP2.D(), Accum.D());
lsr(ARMEmitter::Size::i64Bit, TMP1, TMP1, 63);
lsr(ARMEmitter::Size::i64Bit, TMP2, TMP2, 63);
cset(ARMEmitter::Size::i64Bit, TMP3, ARMEmitter::Condition::CC_HI);
lsl(ARMEmitter::Size::i64Bit, TMP1, TMP1, 2);
orr(ARMEmitter::Size::i64Bit, TMP1, TMP1, TMP2, ARMEmitter::ShiftType::LSL, 1);
orr(ARMEmitter::Size::i64Bit, TMP1, TMP1, TMP3);
// z = min(|y|,|x|) / max(|y|,|x|); NaN guard catches 0/0, inf/inf, NaN inputs.
fcsel(ARMEmitter::ScalarRegSize::i64Bit, VTMP1, Accum, VTMP2, ARMEmitter::Condition::CC_HI);
fcsel(ARMEmitter::ScalarRegSize::i64Bit, Accum, VTMP2, Accum, ARMEmitter::Condition::CC_HI);
fdiv(VTMP2.D(), VTMP1.D(), Accum.D());
fcmp(VTMP2.D(), VTMP2.D());
(void)b(ARMEmitter::Condition::CC_VS, &Fallback);
// P(z^2) via 20-term Horner.
fmul(Accum.D(), VTMP2.D(), VTMP2.D());
fmov(ARMEmitter::Size::i64Bit, TMP3, VTMP2.D());
ldr(VTMP1.D(), &C19Label);
ldr(VTMP2.D(), &C18Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C17Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C16Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C15Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C14Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C13Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C12Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C11Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C10Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C9Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C8Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C7Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C6Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C5Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C4Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C3Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C2Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C1Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
ldr(VTMP2.D(), &C0Label);
fmadd(VTMP1.D(), Accum.D(), VTMP1.D(), VTMP2.D());
// atan_abs = z + z^3 * P(z^2).
fmov(ARMEmitter::Size::i64Bit, VTMP2.D(), TMP3);
fmul(VTMP1.D(), Accum.D(), VTMP1.D());
fmadd(VTMP1.D(), VTMP2.D(), VTMP1.D(), VTMP2.D());
// Quadrant adjustment driven by packed flags in TMP1.
(void)tbz(TMP1, 0, &NoSwap);
ldr(VTMP2.D(), &PiOver2Label);
fsub(VTMP1.D(), VTMP2.D(), VTMP1.D());
(void)Bind(&NoSwap);
(void)tbz(TMP1, 2, &PosX);
ldr(VTMP2.D(), &PiLabel);
fsub(VTMP1.D(), VTMP2.D(), VTMP1.D());
(void)Bind(&PosX);
(void)tbz(TMP1, 1, &NegY);
fneg(VTMP1.D(), VTMP1.D());
(void)Bind(&NegY);
ldr(TMP1.W(), STATE.R(), offsetof(FEXCore::Core::CpuStateFrame, State.flags[24]));
msr(ARMEmitter::SystemRegister::NZCV, TMP1);
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::QReg::q2, ARMEmitter::Reg::rsp, 32);
ret();
// Fallback path: restore original inputs from stack stash and dispatch the ABI handler.
(void)Bind(&Fallback);
ldr(TMP1.W(), STATE.R(), offsetof(FEXCore::Core::CpuStateFrame, State.flags[24]));
msr(ARMEmitter::SystemRegister::NZCV, TMP1);
ldr(TMP2, ARMEmitter::Reg::rsp, 16);
ldr(TMP1, ARMEmitter::Reg::rsp, 24);
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::QReg::q2, ARMEmitter::Reg::rsp, 32);
fmov(ARMEmitter::Size::i64Bit, VTMP1.D(), TMP2);
fmov(ARMEmitter::Size::i64Bit, VTMP2.D(), TMP1);
str<ARMEmitter::IndexType::PRE>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, -16);
ldr(TMP1, STATE_PTR(CpuStateFrame, Pointers.FallbackHandlerPointers[FEXCore::Core::OPINDEX_F64ATAN].ABIHandler));
ldr(TMP4, STATE_PTR(CpuStateFrame, Pointers.FallbackHandlerPointers[FEXCore::Core::OPINDEX_F64ATAN].Func));
blr(TMP1);
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, 16);
ret();
Align(16);
(void)Bind(&C19Label);
dc64(0x3EF3'5885'1160'A528ULL);
(void)Bind(&C18Label);
dc64(0xBF2A'B24D'A7BE'7402ULL);
(void)Bind(&C17Label);
dc64(0x3F51'7739'E210'171AULL);
(void)Bind(&C16Label);
dc64(0xBF6D'0062'B42F'E3BFULL);
(void)Bind(&C15Label);
dc64(0x3F81'4E9D'C19A'4A4EULL);
(void)Bind(&C14Label);
dc64(0xBF90'0513'8172'2A59ULL);
(void)Bind(&C13Label);
dc64(0x3F98'6089'7B29'E5EFULL);
(void)Bind(&C12Label);
dc64(0xBFA0'0E6E'ECE7'DE80ULL);
(void)Bind(&C11Label);
dc64(0x3FA3'38E3'1EB2'FBBCULL);
(void)Bind(&C10Label);
dc64(0xBFA5'D301'40AE'5E99ULL);
(void)Bind(&C9Label);
dc64(0x3FA8'42DB'E9B0'D916ULL);
(void)Bind(&C8Label);
dc64(0xBFAA'EBFE'7B41'8581ULL);
(void)Bind(&C7Label);
dc64(0x3FAE'1D0F'9696'F63BULL);
(void)Bind(&C6Label);
dc64(0xBFB1'1100'EE08'4227ULL);
(void)Bind(&C5Label);
dc64(0x3FB3'B139'B6A8'8BA1ULL);
(void)Bind(&C4Label);
dc64(0xBFB7'45D1'60A7'E368ULL);
(void)Bind(&C3Label);
dc64(0x3FBC'71C7'1BC3'951CULL);
(void)Bind(&C2Label);
dc64(0xBFC2'4924'9247'8F88ULL);
(void)Bind(&C1Label);
dc64(0x3FC9'9999'9999'96C1ULL);
(void)Bind(&C0Label);
dc64(0xBFD5'5555'5555'5555ULL);
(void)Bind(&PiOver2Label);
dc64(0x3FF9'21FB'5444'2D18ULL);
(void)Bind(&PiLabel);
dc64(0x4009'21FB'5444'2D18ULL);
}
// JIT-inlined double-precision y * log2(x) for the F64 reduced precision x87 path.
// Input: VTMP1 = x, VTMP2 = y. Output: VTMP1 = y * log2(x).
// Algorithm: atanh-based log via s = f/(2+f) with 9-term polynomial, scaled by 1/ln(2),
// then multiplied by y.
void Dispatcher::EmitF64FYL2X() {
F64FYL2XHandlerAddress = GetCursorAddress<uint64_t>();
constexpr auto Accum = ARMEmitter::VReg::v2;
ARMEmitter::ForwardLabel Fallback;
ARMEmitter::ForwardLabel NoNorm;
ARMEmitter::ForwardLabel Sqrt2Label, Log2eLabel;
ARMEmitter::ForwardLabel BiasLabel;
ARMEmitter::ForwardLabel P0Label, P1Label, P2Label, P3Label, P4Label, P5Label, P6Label, P7Label, P8Label;
str<ARMEmitter::IndexType::PRE>(ARMEmitter::QReg::q2, ARMEmitter::Reg::rsp, -16);
mrs(TMP1, ARMEmitter::SystemRegister::NZCV);
str(TMP1.W(), STATE.R(), offsetof(FEXCore::Core::CpuStateFrame, State.flags[24]));
// Reject x <= 0, subnormal, inf and NaN before any FPR is clobbered,
// so VTMP1/VTMP2 still hold the original inputs at the fallback.
fmov(ARMEmitter::Size::i64Bit, TMP1, VTMP1.D());
(void)tbnz(TMP1, 63, &Fallback);
lsr(ARMEmitter::Size::i64Bit, TMP2, TMP1, 52);
(void)cbz(ARMEmitter::Size::i64Bit, TMP2, &Fallback);
cmp(ARMEmitter::Size::i64Bit, TMP2, 0x7FF);
(void)b(ARMEmitter::Condition::CC_EQ, &Fallback);
fmov(ARMEmitter::Size::i64Bit, TMP3, VTMP2.D());
// Extract k and normalize mantissa m into [1.0, 2.0).
sub(ARMEmitter::Size::i64Bit, TMP2, TMP2, 1023);
ubfx(ARMEmitter::Size::i64Bit, TMP1, TMP1, 0, 52);
ldr(TMP4, &BiasLabel);
orr(ARMEmitter::Size::i64Bit, TMP1, TMP1, TMP4);
fmov(ARMEmitter::Size::i64Bit, VTMP1.D(), TMP1);
// If m > sqrt(2), halve m and increment k.
ldr(VTMP2.D(), &Sqrt2Label);
fcmp(VTMP1.D(), VTMP2.D());
(void)b(ARMEmitter::Condition::CC_LE, &NoNorm);
fmov(ARMEmitter::ScalarRegSize::i64Bit, VTMP2, 0.5f);
fmul(VTMP1.D(), VTMP1.D(), VTMP2.D());
add(ARMEmitter::Size::i64Bit, TMP2, TMP2, 1);
(void)Bind(&NoNorm);
// f = m - 1; s = f / (2 + f); TMP1 stashes s, VTMP1 holds s^2.
fmov(ARMEmitter::ScalarRegSize::i64Bit, VTMP2, 1.0f);
fsub(VTMP1.D(), VTMP1.D(), VTMP2.D());
fmov(ARMEmitter::ScalarRegSize::i64Bit, VTMP2, 2.0f);
fadd(VTMP2.D(), VTMP1.D(), VTMP2.D());
fdiv(Accum.D(), VTMP1.D(), VTMP2.D());
fmul(VTMP1.D(), Accum.D(), Accum.D());
fmov(ARMEmitter::Size::i64Bit, TMP1, Accum.D());
// 9-term Horner from 1/19 down to 1/3.
ldr(Accum.D(), &P8Label);
ldr(VTMP2.D(), &P7Label);
fmadd(Accum.D(), VTMP1.D(), Accum.D(), VTMP2.D());
ldr(VTMP2.D(), &P6Label);
fmadd(Accum.D(), VTMP1.D(), Accum.D(), VTMP2.D());
ldr(VTMP2.D(), &P5Label);
fmadd(Accum.D(), VTMP1.D(), Accum.D(), VTMP2.D());
ldr(VTMP2.D(), &P4Label);
fmadd(Accum.D(), VTMP1.D(), Accum.D(), VTMP2.D());
ldr(VTMP2.D(), &P3Label);
fmadd(Accum.D(), VTMP1.D(), Accum.D(), VTMP2.D());
ldr(VTMP2.D(), &P2Label);
fmadd(Accum.D(), VTMP1.D(), Accum.D(), VTMP2.D());
ldr(VTMP2.D(), &P1Label);
fmadd(Accum.D(), VTMP1.D(), Accum.D(), VTMP2.D());
ldr(VTMP2.D(), &P0Label);
fmadd(Accum.D(), VTMP1.D(), Accum.D(), VTMP2.D());
// ln(1+f) = 2 * s * (1 + s^2 * P(s^2)).
fmul(Accum.D(), VTMP1.D(), Accum.D());
fmov(ARMEmitter::ScalarRegSize::i64Bit, VTMP2, 1.0f);
fadd(Accum.D(), Accum.D(), VTMP2.D());
fmov(ARMEmitter::Size::i64Bit, VTMP2.D(), TMP1);
fmul(Accum.D(), VTMP2.D(), Accum.D());
fadd(Accum.D(), Accum.D(), Accum.D());
// log2(x) = k + ln(1+f)/ln(2); multiply by y.
ldr(VTMP1.D(), &Log2eLabel);
fmul(VTMP1.D(), Accum.D(), VTMP1.D());
scvtf(ARMEmitter::Size::i64Bit, VTMP2.D(), TMP2);
fadd(VTMP1.D(), VTMP1.D(), VTMP2.D());
fmov(ARMEmitter::Size::i64Bit, VTMP2.D(), TMP3);
fmul(VTMP1.D(), VTMP1.D(), VTMP2.D());
ldr(TMP1.W(), STATE.R(), offsetof(FEXCore::Core::CpuStateFrame, State.flags[24]));
msr(ARMEmitter::SystemRegister::NZCV, TMP1);
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::QReg::q2, ARMEmitter::Reg::rsp, 16);
ret();
// Fallback path: VTMP1/VTMP2 still hold the original x/y.
(void)Bind(&Fallback);
ldr(TMP1.W(), STATE.R(), offsetof(FEXCore::Core::CpuStateFrame, State.flags[24]));
msr(ARMEmitter::SystemRegister::NZCV, TMP1);
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::QReg::q2, ARMEmitter::Reg::rsp, 16);
str<ARMEmitter::IndexType::PRE>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, -16);
ldr(TMP1, STATE_PTR(CpuStateFrame, Pointers.FallbackHandlerPointers[FEXCore::Core::OPINDEX_F64FYL2X].ABIHandler));
ldr(TMP4, STATE_PTR(CpuStateFrame, Pointers.FallbackHandlerPointers[FEXCore::Core::OPINDEX_F64FYL2X].Func));
blr(TMP1);
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, 16);
ret();
// Constant pool: bias=1.0, sqrt(2), log2(e)=1/ln(2), P8..P0 = 1/19, 1/17, 1/15, ..., 1/3.
Align(16);
(void)Bind(&BiasLabel);
dc64(0x3FF0'0000'0000'0000ULL);
(void)Bind(&Sqrt2Label);
dc64(0x3FF6'A09E'667F'3BCDULL);
(void)Bind(&Log2eLabel);
dc64(0x3FF7'1547'652B'82FEULL);
(void)Bind(&P8Label);
dc64(0x3FAA'F286'BCA1'AF28ULL);
(void)Bind(&P7Label);
dc64(0x3FAE'1E1E'1E1E'1E1EULL);
(void)Bind(&P6Label);
dc64(0x3FB1'1111'1111'1111ULL);
(void)Bind(&P5Label);
dc64(0x3FB3'B13B'13B1'3B14ULL);
(void)Bind(&P4Label);
dc64(0x3FB7'45D1'745D'1746ULL);
(void)Bind(&P3Label);
dc64(0x3FBC'71C7'1C71'C71CULL);
(void)Bind(&P2Label);
dc64(0x3FC2'4924'9249'2492ULL);
(void)Bind(&P1Label);
dc64(0x3FC9'9999'9999'999AULL);
(void)Bind(&P0Label);
dc64(0x3FD5'5555'5555'5555ULL);
}
uint64_t Dispatcher::GenerateABICall(FallbackABI ABI) {
auto Address = GetCursorAddress<uint64_t>();
constexpr static auto FallbackPointerReg = TMP4;
@@ -1693,6 +2186,10 @@ void Dispatcher::InitThreadPointers(FEXCore::Core::InternalThreadState* Thread)
Ptrs.F64SinHandler = F64SinHandlerAddress;
Ptrs.F64CosHandler = F64CosHandlerAddress;
Ptrs.F64TanHandler = F64TanHandlerAddress;
Ptrs.F64F2XM1Handler = F64F2XM1HandlerAddress;
Ptrs.F64ScaleHandler = F64ScaleHandlerAddress;
Ptrs.F64AtanHandler = F64AtanHandlerAddress;
Ptrs.F64FYL2XHandler = F64FYL2XHandlerAddress;
// Fill in the fallback handlers
InterpreterOps::FillFallbackIndexPointers(Ptrs.FallbackHandlerPointers, &ABIPointers[0]);
@@ -99,10 +99,14 @@ private:
uint64_t LUDIVHandlerAddress {};
uint64_t LDIVHandlerAddress {};
// F64 trig shared handlers
// F64 reduced-precision shared handlers
uint64_t F64SinHandlerAddress {};
uint64_t F64CosHandlerAddress {};
uint64_t F64TanHandlerAddress {};
uint64_t F64F2XM1HandlerAddress {};
uint64_t F64ScaleHandlerAddress {};
uint64_t F64AtanHandlerAddress {};
uint64_t F64FYL2XHandlerAddress {};
void EmitDispatcher();
uint64_t GenerateABICall(FallbackABI ABI);
@@ -117,6 +121,10 @@ private:
void EmitF64Sin();
void EmitF64Cos();
void EmitF64Tan();
void EmitF64F2XM1();
void EmitF64Scale();
void EmitF64Atan();
void EmitF64FYL2X();
FEX_CONFIG_OPT(DisableL2Cache, DISABLEL2CACHE);
};
+1 -1
View File
@@ -274,7 +274,7 @@ DEF_OP(CmpPairZ) {
// Restore NzCV
if (CTX->HostFeatures.SupportsFlagM) {
rmif(TMP1, 0, 0xb /* NzCV */);
rmif(TMP1, 28, 0xb /* NzCV */);
} else {
cset(ARMEmitter::Size::i32Bit, TMP2, ARMEmitter::Condition::CC_EQ);
bfi(ARMEmitter::Size::i32Bit, TMP1, TMP2, 30 /* lsb: Z */, 1);
@@ -1434,8 +1434,8 @@ DEF_OP(VFMin) {
bif(Dst.Q(), Vector2.Q(), VTMP1.Q());
} else if (Dst == Vector2) {
// Destination is already Vector2, Invert arguments and insert Vector1 on false.
fcmgt(SubRegSize, VTMP1.Q(), Vector1.Q(), Vector2.Q());
bif(Dst.Q(), Vector1.Q(), VTMP1.Q());
fcmgt(SubRegSize, VTMP1.Q(), Vector2.Q(), Vector1.Q());
bit(Dst.Q(), Vector1.Q(), VTMP1.Q());
} else {
// Dst is not either source, need a move.
fcmgt(SubRegSize, VTMP1.Q(), Vector2.Q(), Vector1.Q());
@@ -1466,7 +1466,8 @@ DEF_OP(VFMax) {
const auto Mask = PRED_TMP_32B;
const auto ComparePred = ARMEmitter::PReg::p0;
fcmgt(SubRegSize, ComparePred, Mask.Zeroing(), Vector2.Z(), Vector1.Z());
fcmgt(SubRegSize, ComparePred, Mask.Zeroing(), Vector1.Z(), Vector2.Z());
not_(ComparePred, Mask.Zeroing(), ComparePred);
if (Dst == Vector1) {
// Trivial case where Vector1 is also the destination.
@@ -1488,17 +1489,17 @@ DEF_OP(VFMax) {
if (Dst == Vector1) {
// Destination is already Vector1, need to insert Vector2 on true.
fcmgt(SubRegSize, VTMP1.Q(), Vector2.Q(), Vector1.Q());
bit(Dst.Q(), Vector2.Q(), VTMP1.Q());
fcmgt(SubRegSize, VTMP1.Q(), Vector1.Q(), Vector2.Q());
bif(Dst.Q(), Vector2.Q(), VTMP1.Q());
} else if (Dst == Vector2) {
// Destination is already Vector2, Invert arguments and insert Vector1 on true.
fcmgt(SubRegSize, VTMP1.Q(), Vector1.Q(), Vector2.Q());
bit(Dst.Q(), Vector1.Q(), VTMP1.Q());
} else {
// Dst is not either source, need a move.
fcmgt(SubRegSize, VTMP1.Q(), Vector2.Q(), Vector1.Q());
fcmgt(SubRegSize, VTMP1.Q(), Vector1.Q(), Vector2.Q());
mov(Dst.Q(), Vector1.Q());
bit(Dst.Q(), Vector2.Q(), VTMP1.Q());
bif(Dst.Q(), Vector2.Q(), VTMP1.Q());
}
}
}
@@ -4650,5 +4651,65 @@ DEF_OP(F64TAN) {
fmov(Dst.D(), VTMP1.D());
}
// Src1=y(ST1), Src2=x(ST0). Marshal into VTMP1/VTMP2 and dispatch the shared handler.
DEF_OP(F64ATAN) {
const auto Op = IROp->C<IR::IROp_F64ATAN>();
const auto Src1 = GetVReg(Op->Src1);
const auto Src2 = GetVReg(Op->Src2);
const auto Dst = GetVReg(Node);
fmov(VTMP1.D(), Src1.D());
fmov(VTMP2.D(), Src2.D());
ldr(TMP1, STATE_PTR(CpuStateFrame, Pointers.F64AtanHandler));
str<ARMEmitter::IndexType::PRE>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, -16);
blr(TMP1);
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, 16);
fmov(Dst.D(), VTMP1.D());
}
// Src=x(ST0), Src2=y(ST1). Marshal into VTMP1/VTMP2 and dispatch the shared handler.
DEF_OP(F64FYL2X) {
const auto Op = IROp->C<IR::IROp_F64FYL2X>();
const auto Src = GetVReg(Op->Src);
const auto Src2 = GetVReg(Op->Src2);
const auto Dst = GetVReg(Node);
fmov(VTMP1.D(), Src.D());
fmov(VTMP2.D(), Src2.D());
ldr(TMP1, STATE_PTR(CpuStateFrame, Pointers.F64FYL2XHandler));
str<ARMEmitter::IndexType::PRE>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, -16);
blr(TMP1);
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, 16);
fmov(Dst.D(), VTMP1.D());
}
DEF_OP(F64SCALE) {
const auto Op = IROp->C<IR::IROp_F64SCALE>();
const auto Src1 = GetVReg(Op->Src1);
const auto Src2 = GetVReg(Op->Src2);
const auto Dst = GetVReg(Node);
fmov(VTMP1.D(), Src1.D());
fmov(VTMP2.D(), Src2.D());
ldr(TMP1, STATE_PTR(CpuStateFrame, Pointers.F64ScaleHandler));
str<ARMEmitter::IndexType::PRE>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, -16);
blr(TMP1);
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, 16);
fmov(Dst.D(), VTMP1.D());
}
DEF_OP(F64F2XM1) {
const auto Op = IROp->C<IR::IROp_F64F2XM1>();
const auto Src = GetVReg(Op->Src);
const auto Dst = GetVReg(Node);
fmov(VTMP1.D(), Src.D());
ldr(TMP1, STATE_PTR(CpuStateFrame, Pointers.F64F2XM1Handler));
str<ARMEmitter::IndexType::PRE>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, -16);
blr(TMP1);
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, 16);
fmov(Dst.D(), VTMP1.D());
}
} // namespace FEXCore::CPU
@@ -1011,10 +1011,522 @@ Ref OpDispatchBuilder::PShufWLane(IR::OpSize Size, FEXCore::IR::IndexNamedVector
}
void OpDispatchBuilder::PSHUFW8ByteOp(OpcodeArgs) {
uint16_t Shuffle = Op->Src[1].Data.Literal.Value;
uint8_t Shuffle = Op->Src[1].Data.Literal.Value;
const auto Size = OpSizeFromSrc(Op);
const auto TBLIndex = FEXCore::IR::INDEXED_NAMED_VECTOR_PSHUFLW;
Ref Src = LoadSourceFPR(Op, Op->Src[0], Op->Flags);
Ref Dest = PShufWLane(Size, FEXCore::IR::INDEXED_NAMED_VECTOR_PSHUFLW, true, Src, Shuffle);
// Single MMX 64-bit shuffle. Shuffle selector can fit full selection.
Ref Dest {};
switch (Shuffle) {
// Single-instruction shuffle operations.
case 0b00'00'00'00: Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 0); break;
case 0b00'10'01'00: Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 0, Src, Src); break;
case 0b01'00'01'00: Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Src, Src); break;
case 0b00'11'10'01: Dest = _VExtr(OpSize::i64Bit, OpSize::i16Bit, Src, Src, 1); break;
case 0b01'00'11'10: Dest = _VRev64(OpSize::i64Bit, OpSize::i32Bit, Src); break;
case 0b01'01'01'01: Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 1); break;
case 0b01'10'01'00: Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 1, Src, Src); break;
case 0b10'10'01'00: Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 2, Src, Src); break;
case 0b10'10'10'10: Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 2); break;
case 0b11'00'01'00: Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 0, Src, Src); break;
case 0b11'01'01'00: Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 1, Src, Src); break;
case 0b11'10'00'00: Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 0, Src, Src); break;
case 0b11'10'01'00: Dest = Src; break;
case 0b11'10'01'01: Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 1, Src, Src); break;
case 0b11'10'01'10: Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 2, Src, Src); break;
case 0b11'10'01'11: Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 3, Src, Src); break;
case 0b11'10'10'00: Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 2, Src, Src); break;
case 0b11'10'11'00: Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 3, Src, Src); break;
case 0b11'10'11'10: Dest = _VDupElement(OpSize::i64Bit, OpSize::i32Bit, Src, 1); break;
case 0b11'11'01'00: Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 3, Src, Src); break;
case 0b11'11'11'11: Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 3); break;
// Two instruction shuffle operations.
case 0b00'00'00'01:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 0);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 1, Dest, Src);
break;
case 0b00'00'00'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 0);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 2, Dest, Src);
break;
case 0b00'00'00'11:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 0);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 3, Dest, Src);
break;
case 0b00'00'01'00:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 0);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 1, Dest, Src);
break;
case 0b00'00'10'00:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 0);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 2, Dest, Src);
break;
case 0b00'00'11'00:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 0);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 3, Dest, Src);
break;
case 0b00'00'11'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 0);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i32Bit, 0, 1, Dest, Src);
break;
case 0b00'01'00'00:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 0);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 1, Dest, Src);
break;
case 0b00'01'00'01:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i32Bit, Src, 0);
Dest = _VExtr(OpSize::i64Bit, OpSize::i16Bit, Dest, Dest, 1);
break;
case 0b00'01'00'11:
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Src, Src);
Dest = _VExtr(OpSize::i64Bit, OpSize::i8Bit, Dest, Src, 6);
break;
case 0b00'01'01'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 1, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 0, Dest, Src);
break;
case 0b00'01'01'01:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 1);
Dest = _VExtr(OpSize::i64Bit, OpSize::i16Bit, Src, Dest, 1);
break;
case 0b00'10'00'00:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 0);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 2, Dest, Src);
break;
case 0b00'10'00'10:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 0, Src, Src);
Dest = _VDupElement(OpSize::i64Bit, OpSize::i32Bit, Dest, 1);
break;
case 0b00'10'01'01:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 1, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 0, Dest, Src);
break;
case 0b00'10'01'10:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 2, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 0, Dest, Src);
break;
case 0b00'10'01'11:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 3, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 0, Dest, Src);
break;
case 0b00'10'10'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 2, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 0, Dest, Src);
break;
case 0b00'10'10'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 2);
Dest = _VExtr(OpSize::i64Bit, OpSize::i16Bit, Src, Dest, 1);
break;
case 0b00'10'11'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 3, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 0, Dest, Src);
break;
case 0b00'10'11'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i32Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 0, Dest, Src);
break;
case 0b00'11'00'00:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 0);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 3, Dest, Src);
break;
case 0b00'11'01'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 3, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 0, Dest, Src);
break;
case 0b00'11'10'11:
Dest = _VZip2(OpSize::i64Bit, OpSize::i32Bit, Src, Src);
Dest = _VExtr(OpSize::i64Bit, OpSize::i16Bit, Src, Dest, 1);
break;
case 0b00'11'11'11:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 3);
Dest = _VExtr(OpSize::i64Bit, OpSize::i16Bit, Src, Dest, 1);
break;
case 0b01'00'00'00:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 0);
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Dest, Src);
break;
case 0b01'00'00'10:
Dest = _VRev64(OpSize::i64Bit, OpSize::i32Bit, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 0, Dest, Src);
break;
case 0b01'00'01'01:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 1);
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Dest, Src);
break;
case 0b01'00'01'10:
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 2, Dest, Src);
break;
case 0b01'00'01'11:
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 3, Dest, Src);
break;
case 0b01'00'10'00:
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 2, Dest, Src);
break;
case 0b01'00'10'01:
Dest = _VExtr(OpSize::i64Bit, OpSize::i8Bit, Src, Src, 2);
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Dest, Src);
break;
case 0b01'00'10'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 2);
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Dest, Src);
break;
case 0b01'00'11'00:
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 3, Dest, Src);
break;
case 0b01'00'11'01:
Dest = _VRev64(OpSize::i64Bit, OpSize::i32Bit, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 1, Dest, Src);
break;
case 0b01'00'11'11:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 3);
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Dest, Src);
break;
case 0b01'01'00'01:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 0, Dest, Src);
break;
case 0b01'01'01'00:
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 1, Dest, Src);
break;
case 0b01'01'01'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 2, Dest, Src);
break;
case 0b01'01'01'11:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 3, Dest, Src);
break;
case 0b01'01'10'01:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 2, Dest, Src);
break;
case 0b01'01'11'01:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 3, Dest, Src);
break;
case 0b01'01'11'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i32Bit, 0, 1, Dest, Src);
break;
case 0b01'10'00'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 0, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 1, Dest, Src);
break;
case 0b01'10'01'01:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 2, Dest, Src);
break;
case 0b01'10'01'10:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 2, Src, Src);
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Dest, Dest);
break;
case 0b01'10'01'11:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 3, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 1, Dest, Src);
break;
case 0b01'10'10'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 2, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 1, Dest, Src);
break;
case 0b01'10'10'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 2);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 1, Dest, Src);
break;
case 0b01'10'11'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 3, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 1, Dest, Src);
break;
case 0b01'10'11'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i32Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 1, Dest, Src);
break;
case 0b01'11'01'00:
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 3, Dest, Src);
break;
case 0b01'11'01'01:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 3, Dest, Src);
break;
case 0b01'11'01'11:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 3, Src, Src);
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Dest, Dest);
break;
case 0b01'11'10'01:
Dest = _VExtr(OpSize::i64Bit, OpSize::i8Bit, Src, Src, 2);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 0, Dest, Dest);
break;
case 0b01'11'11'10:
Dest = _VRev64(OpSize::i64Bit, OpSize::i32Bit, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 1, Dest, Dest);
break;
case 0b01'11'11'11:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 3);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 1, Dest, Src);
break;
case 0b10'00'00'00:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 0);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 2, Dest, Src);
break;
case 0b10'00'01'00:
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 2, Dest, Src);
break;
case 0b10'00'10'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 2, Src, Src);
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Dest, Dest);
break;
case 0b10'00'10'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 2);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 0, Dest, Src);
break;
case 0b10'00'11'10:
Dest = _VRev64(OpSize::i64Bit, OpSize::i32Bit, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 0, Dest, Dest);
break;
case 0b10'01'00'00:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 0);
Dest = _VExtr(OpSize::i64Bit, OpSize::i8Bit, Src, Dest, 6);
break;
case 0b10'01'00'01:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 1);
Dest = _VExtr(OpSize::i64Bit, OpSize::i8Bit, Src, Dest, 6);
break;
case 0b10'01'00'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 2);
Dest = _VExtr(OpSize::i64Bit, OpSize::i8Bit, Src, Dest, 6);
break;
case 0b10'01'00'11:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 3);
Dest = _VExtr(OpSize::i64Bit, OpSize::i8Bit, Src, Dest, 6);
break;
case 0b10'01'01'00:
Dest = _VExtr(OpSize::i64Bit, OpSize::i8Bit, Src, Src, 6);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i32Bit, 0, 0, Dest, Src);
break;
case 0b10'01'01'01:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 2, Dest, Src);
break;
case 0b10'01'10'01:
Dest = _VExtr(OpSize::i64Bit, OpSize::i8Bit, Src, Src, 2);
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Dest, Dest);
break;
case 0b10'01'10'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 2);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 1, Dest, Src);
break;
case 0b10'01'11'10:
Dest = _VExtr(OpSize::i64Bit, OpSize::i8Bit, Src, Src, 6);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i32Bit, 0, 1, Dest, Src);
break;
case 0b10'10'00'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 0, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 2, Dest, Src);
break;
case 0b10'10'00'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 2);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 0, Dest, Src);
break;
case 0b10'10'01'01:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 1, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 2, Dest, Src);
break;
case 0b10'10'01'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 2);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 1, Dest, Src);
break;
case 0b10'10'01'11:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 3, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 2, Dest, Src);
break;
case 0b10'10'10'00:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 2);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 0, Dest, Src);
break;
case 0b10'10'10'01:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 2);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 1, Dest, Src);
break;
case 0b10'10'10'11:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 2);
Dest = _VExtr(OpSize::i64Bit, OpSize::i8Bit, Dest, Src, 6);
break;
case 0b10'10'11'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 3, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 2, Dest, Src);
break;
case 0b10'10'11'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 2);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 3, Dest, Src);
break;
case 0b10'11'01'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 3, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 2, Dest, Src);
break;
case 0b10'11'10'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 2);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 3, Dest, Src);
break;
case 0b10'11'10'11:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i32Bit, Src, 1);
Dest = _VExtr(OpSize::i64Bit, OpSize::i16Bit, Dest, Dest, 1);
break;
case 0b10'11'11'11:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 3);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 2, Dest, Src);
break;
case 0b11'00'00'00:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 0);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 3, Dest, Src);
break;
case 0b11'00'01'01:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 1, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 0, Dest, Src);
break;
case 0b11'00'01'10:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 2, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 0, Dest, Src);
break;
case 0b11'00'01'11:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 3, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 0, Dest, Src);
break;
case 0b11'00'10'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 2, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 0, Dest, Src);
break;
case 0b11'00'11'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 3, Src, Src);
Dest = _VZip(OpSize::i64Bit, OpSize::i32Bit, Dest, Dest);
break;
case 0b11'00'11'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i32Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 0, Dest, Src);
break;
case 0b11'00'11'11:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 3);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 0, Dest, Src);
break;
case 0b11'01'00'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 0, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 1, Dest, Src);
break;
case 0b11'01'01'01:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 3, Dest, Src);
break;
case 0b11'01'01'10:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 2, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 1, Dest, Src);
break;
case 0b11'01'01'11:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 3, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 1, Dest, Src);
break;
case 0b11'01'10'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 2, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 1, Dest, Src);
break;
case 0b11'01'11'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 3, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 1, Dest, Src);
break;
case 0b11'01'11'01:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 1, Src, Src);
Dest = _VDupElement(OpSize::i64Bit, OpSize::i32Bit, Dest, 1);
break;
case 0b11'01'11'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i32Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 1, Dest, Src);
break;
case 0b11'01'11'11:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 3);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 1, Dest, Src);
break;
case 0b11'10'00'01:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 1, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 0, Dest, Src);
break;
case 0b11'10'00'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i32Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 0, Dest, Src);
break;
case 0b11'10'00'11:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 3, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 0, Dest, Src);
break;
case 0b11'10'10'01:
Dest = _VExtr(OpSize::i64Bit, OpSize::i8Bit, Src, Src, 2);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i32Bit, 1, 1, Dest, Src);
break;
case 0b11'10'10'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 2);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 3, 3, Dest, Src);
break;
case 0b11'10'10'11:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 3, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 2, Dest, Src);
break;
case 0b11'10'11'01:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i32Bit, Src, 1);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 1, Dest, Src);
break;
case 0b11'10'11'11:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 3);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 2, Dest, Src);
break;
case 0b11'11'00'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 0, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 3, Dest, Src);
break;
case 0b11'11'00'11:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 3);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 0, Dest, Src);
break;
case 0b11'11'01'01:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 1, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 3, Dest, Src);
break;
case 0b11'11'01'10:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 2, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 3, Dest, Src);
break;
case 0b11'11'01'11:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 3);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 1, Dest, Src);
break;
case 0b11'11'10'00:
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 2, Src, Src);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 2, 3, Dest, Src);
break;
case 0b11'11'10'11:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 3);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 1, 2, Dest, Src);
break;
case 0b11'11'11'00:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 3);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 0, Dest, Src);
break;
case 0b11'11'11'01:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 3);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 1, Dest, Src);
break;
case 0b11'11'11'10:
Dest = _VDupElement(OpSize::i64Bit, OpSize::i16Bit, Src, 3);
Dest = _VInsElement(OpSize::i64Bit, OpSize::i16Bit, 0, 2, Dest, Src);
break;
default:
auto LookupIndexes = LoadAndCacheIndexedNamedVectorConstant(Size, TBLIndex, Shuffle * 16);
Dest = _VTBL1(Size, Src, LookupIndexes);
break;
}
StoreResultFPR(Op, Dest);
}
@@ -163,7 +163,7 @@ void OpDispatchBuilder::FIST(OpcodeArgs, bool Truncate) {
// Check for NaN/Infinity: exponent = 0x7fff
SaveNZCV();
_TestNZ(OpSize::i64Bit, Exponent, Constant(0x7fff));
SubWithFlags(OpSize::i64Bit, Exponent, 0x7fff);
Ref IsSpecial = _NZCVSelect01(CondClass::EQ);
// For overflow detection, check if exponent indicates a value >= 2^15
@@ -178,7 +178,8 @@ void OpDispatchBuilder::FIST(OpcodeArgs, bool Truncate) {
Data = _F80CVTInt(Size, Data, Truncate);
StoreResultGPR_WithOpSize(Op, Op->Dest, Data, Size, OpSize::i8Bit);
StoreResultGPR_WithOpSize(Op, Op->Dest, Data, Size, OpSize::i8Bit,
CTX->IsVectorAtomicTSOEnabled() ? MemoryAccessType::DEFAULT : MemoryAccessType::NONTSO);
if ((Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) != 0) {
_PopStackDestroy();
@@ -106,12 +106,24 @@ void OpDispatchBuilder::FISTF64(OpcodeArgs, bool Truncate) {
const auto Size = OpSizeFromSrc(Op);
Ref data = _ReadStackValue(0);
if (Truncate) {
data = _Float_ToGPR_ZS(Size == OpSize::i32Bit ? OpSize::i32Bit : OpSize::i64Bit, OpSize::i64Bit, data);
bool CanUseFloatReg = Size == OpSize::i64Bit;
if (CanUseFloatReg) {
// If possible, it's faster to keep the data in an FPR than doing a GPR transfer.
if (Truncate) {
data = _Vector_FToZS(OpSize::i128Bit, OpSize::i64Bit, data);
} else {
data = _Vector_FToS(OpSize::i128Bit, OpSize::i64Bit, data);
}
StoreResultFPR_WithOpSize(Op, Op->Dest, data, OpSize::i64Bit, OpSize::i8Bit);
} else {
data = _Float_ToGPR_S(Size == OpSize::i32Bit ? OpSize::i32Bit : OpSize::i64Bit, OpSize::i64Bit, data);
if (Truncate) {
data = _Float_ToGPR_ZS(Size == OpSize::i32Bit ? OpSize::i32Bit : OpSize::i64Bit, OpSize::i64Bit, data);
} else {
data = _Float_ToGPR_S(Size == OpSize::i32Bit ? OpSize::i32Bit : OpSize::i64Bit, OpSize::i64Bit, data);
}
StoreResultGPR_WithOpSize(Op, Op->Dest, data, Size, OpSize::i8Bit,
CTX->IsVectorAtomicTSOEnabled() ? MemoryAccessType::DEFAULT : MemoryAccessType::NONTSO);
}
StoreResultGPR_WithOpSize(Op, Op->Dest, data, Size, OpSize::i8Bit);
if ((Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) != 0) {
_PopStackDestroy();
@@ -370,6 +382,8 @@ void OpDispatchBuilder::X87FXTRACTF64(OpcodeArgs) {
// Split node into SIG and EXP while handling the special zero case.
// i.e. if val == 0.0, then sig = 0.0, exp = -inf
// if val == -0.0, then sig = -0.0, exp = -inf
// if val is +/-Inf, then sig = val, exp = +inf
// if val is NaN, then sig = val, exp = val
// otherwise we just extract the 64-bit sig and exp as normal.
Ref Node = _ReadStackValue(0);
@@ -379,6 +393,11 @@ void OpDispatchBuilder::X87FXTRACTF64(OpcodeArgs) {
Ref ExpZV = _VCastFromGPR(OpSize::i64Bit, OpSize::i64Bit, Constant(0xfff0'0000'0000'0000UL));
Ref SigZV = Node;
// Inf/NaN case
Ref ExpInfOnlyV = _VCastFromGPR(OpSize::i64Bit, OpSize::i64Bit, Constant(0x7ff0'0000'0000'0000UL));
Ref ExpNanV = Node;
Ref SigInfV = Node;
// non zero case
Ref ExpNZ = _Bfe(OpSize::i64Bit, 11, 52, Gpr);
ExpNZ = Sub(OpSize::i64Bit, ExpNZ, Constant(1023));
@@ -388,12 +407,24 @@ void OpDispatchBuilder::X87FXTRACTF64(OpcodeArgs) {
SigNZ = _Or(OpSize::i64Bit, SigNZ, Constant(0x3ff0'0000'0000'0000LL));
Ref SigNZV = _VCastFromGPR(OpSize::i64Bit, OpSize::i64Bit, SigNZ);
// Comparison and select to push onto stack
SaveNZCV();
// Mantissa non-zero => NaN (exp result = input); else Inf (exp result = +Inf)
Ref Mantissa = _And(OpSize::i64Bit, Gpr, Constant(0x000f'ffff'ffff'ffffULL));
_TestNZ(OpSize::i64Bit, Mantissa, Constant(~0ULL));
Ref ExpInfV = _NZCVSelectV(OpSize::i64Bit, CondClass::EQ, ExpInfOnlyV, ExpNanV);
// Biased exponent == 0x7ff => Inf/NaN path, else non-zero-case.
Ref BiasedExp = _Bfe(OpSize::i64Bit, 11, 52, Gpr);
SubWithFlags(OpSize::i64Bit, BiasedExp, 0x7ff);
Ref ExpNZOrInf = _NZCVSelectV(OpSize::i64Bit, CondClass::EQ, ExpInfV, ExpNZV);
Ref SigNZOrInf = _NZCVSelectV(OpSize::i64Bit, CondClass::EQ, SigInfV, SigNZV);
// Zero folds on top.
_TestNZ(OpSize::i64Bit, Gpr, Constant(0x7fff'ffff'ffff'ffffUL));
Ref Sig = _NZCVSelectV(OpSize::i64Bit, CondClass::EQ, SigZV, SigNZV);
Ref Exp = _NZCVSelectV(OpSize::i64Bit, CondClass::EQ, ExpZV, ExpNZV);
Ref Sig = _NZCVSelectV(OpSize::i64Bit, CondClass::EQ, SigZV, SigNZOrInf);
Ref Exp = _NZCVSelectV(OpSize::i64Bit, CondClass::EQ, ExpZV, ExpNZOrInf);
_PopStackDestroy();
_PushStack(Exp, Invalid(), OpSize::iInvalid);
@@ -31,19 +31,19 @@ constexpr std::array<X86InstInfo[2], ENTRY_MAX> Secondary_ArchSelect_LUT = {{
},
{
{"PUSH FS", TYPE_INST, GenFlagsSrcSize(SIZE_16BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .OpDispatch = &IR::OpDispatchBuilder::Bind<&IR::OpDispatchBuilder::PUSHSegmentOp, FEXCore::X86Tables::DecodeFlags::FLAG_FS_PREFIX> } },
{"PUSH FS", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .OpDispatch = &IR::OpDispatchBuilder::Bind<&IR::OpDispatchBuilder::PUSHSegmentOp, FEXCore::X86Tables::DecodeFlags::FLAG_FS_PREFIX> } },
{"PUSH FS", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .OpDispatch = &IR::OpDispatchBuilder::Bind<&IR::OpDispatchBuilder::PUSHSegmentOp, FEXCore::X86Tables::DecodeFlags::FLAG_FS_PREFIX> } },
},
{
{"POP FS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_DEF) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .OpDispatch = &IR::OpDispatchBuilder::Bind<&IR::OpDispatchBuilder::POPSegmentOp, FEXCore::X86Tables::DecodeFlags::FLAG_FS_PREFIX> } },
{"POP FS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_64BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .OpDispatch = &IR::OpDispatchBuilder::Bind<&IR::OpDispatchBuilder::POPSegmentOp, FEXCore::X86Tables::DecodeFlags::FLAG_FS_PREFIX> } },
{"POP FS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_64BITDEF) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .OpDispatch = &IR::OpDispatchBuilder::Bind<&IR::OpDispatchBuilder::POPSegmentOp, FEXCore::X86Tables::DecodeFlags::FLAG_FS_PREFIX> } },
},
{
{"PUSH GS", TYPE_INST, GenFlagsSrcSize(SIZE_16BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .OpDispatch = &IR::OpDispatchBuilder::Bind<&IR::OpDispatchBuilder::PUSHSegmentOp, FEXCore::X86Tables::DecodeFlags::FLAG_GS_PREFIX> } },
{"PUSH GS", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .OpDispatch = &IR::OpDispatchBuilder::Bind<&IR::OpDispatchBuilder::PUSHSegmentOp, FEXCore::X86Tables::DecodeFlags::FLAG_GS_PREFIX> } },
{"PUSH GS", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .OpDispatch = &IR::OpDispatchBuilder::Bind<&IR::OpDispatchBuilder::PUSHSegmentOp, FEXCore::X86Tables::DecodeFlags::FLAG_GS_PREFIX> } },
},
{
{"POP GS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_DEF) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .OpDispatch = &IR::OpDispatchBuilder::Bind<&IR::OpDispatchBuilder::POPSegmentOp, FEXCore::X86Tables::DecodeFlags::FLAG_GS_PREFIX> } },
{"POP GS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_64BIT) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .OpDispatch = &IR::OpDispatchBuilder::Bind<&IR::OpDispatchBuilder::POPSegmentOp, FEXCore::X86Tables::DecodeFlags::FLAG_GS_PREFIX> } },
{"POP GS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_64BITDEF) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .OpDispatch = &IR::OpDispatchBuilder::Bind<&IR::OpDispatchBuilder::POPSegmentOp, FEXCore::X86Tables::DecodeFlags::FLAG_GS_PREFIX> } },
},
}};
+4 -4
View File
@@ -2758,7 +2758,7 @@
"F64": {
"FPR = F64ATAN FPR:$Src1, FPR:$Src2": {
"DestSize": "OpSize::i64Bit",
"JITDispatch": false
"JITDispatch": true
},
"FPR = F64FPREM FPR:$Src1, FPR:$Src2": {
"DestSize": "OpSize::i64Bit",
@@ -2770,15 +2770,15 @@
},
"FPR = F64SCALE FPR:$Src1, FPR:$Src2": {
"DestSize": "OpSize::i64Bit",
"JITDispatch": false
"JITDispatch": true
},
"FPR = F64F2XM1 FPR:$Src": {
"DestSize": "OpSize::i64Bit",
"JITDispatch": false
"JITDispatch": true
},
"FPR = F64FYL2X FPR:$Src, FPR:$Src2": {
"DestSize": "OpSize::i64Bit",
"JITDispatch": false
"JITDispatch": true
},
"FPR = F64TAN FPR:$Src": {
"DestSize": "OpSize::i64Bit",
+10
View File
@@ -262,9 +262,19 @@ fextl::vector<MemoryRegion> StealMemoryRegion(uintptr_t Begin, uintptr_t End) {
}
// Block remaining memory gaps
bool SupportsDontDump = true;
for (auto RegionIt = Regions.begin(); RegionIt != Regions.end(); ++RegionIt) {
auto Alloc = ::mmap(RegionIt->Ptr, RegionIt->Size, PROT_NONE, MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE | MAP_FIXED_NOREPLACE, -1, 0);
if (SupportsDontDump) {
// Mark these regions as don't dump so that coredump doesn't try dumping large unmapped regions.
// Ideally coredump would be smart enough to only dump resident pages, but here we are.
auto Result = madvise(RegionIt->Ptr, RegionIt->Size, MADV_DONTDUMP);
if (Result == -1) {
SupportsDontDump = false;
}
}
LogMan::Throw::AFmt(Alloc != MAP_FAILED, "StealMemoryRegion: mmap({}, {:x}) failed: {}", fmt::ptr(RegionIt->Ptr), RegionIt->Size, errno);
LogMan::Throw::AFmt(Alloc == RegionIt->Ptr, "mmap returned {} instead of {}", Alloc, fmt::ptr(RegionIt->Ptr));
}
-1
View File
@@ -2,7 +2,6 @@
#ifdef ENABLE_FEX_ALLOCATOR
#include <rpmalloc/rpmalloc.h>
#ifndef _WIN32
#include <linux/prctl.h>
#include <sys/prctl.h>
#include <sys/mman.h>
#else
+12 -1
View File
@@ -2005,8 +2005,19 @@ std::optional<int32_t> HandleUnalignedAccess(FEXCore::Core::InternalThreadState*
Thread->ExclusiveStore.Size = 0;
return 4;
}
} else if ((Instr & ArchHelpers::Arm64::ATOMIC_MEM_MASK) == ArchHelpers::Arm64::ATOMIC_MEM_INST) { // Atomic memory op
if (ArchHelpers::Arm64::HandleAtomicMemOp(Instr, GPRs, StrictSplitLockMutex)) {
// Skip this instruction now
return 4;
} else {
uint8_t Op = (PC[0] >> 12) & 0xF;
LogMan::Msg::EFmt("Unhandled JIT SIGBUS Atomic mem op 0x{:02x}: PC: 0x{:x} Instruction: 0x{:08x}\n", Op, ProgramCounter, PC[0]);
return std::nullopt;
}
}
return 0;
LogMan::Msg::EFmt("Unhandled non-JIT atomic");
return std::nullopt;
}
const auto Frame = Thread->CurrentFrame;
+4
View File
@@ -379,6 +379,10 @@ struct JITPointers {
uint64_t F64SinHandler {};
uint64_t F64CosHandler {};
uint64_t F64TanHandler {};
uint64_t F64F2XM1Handler {};
uint64_t F64ScaleHandler {};
uint64_t F64AtanHandler {};
uint64_t F64FYL2XHandler {};
/** @} */
// Copy of process-wide named vector constants data.
@@ -15,7 +15,6 @@
namespace FEXCore {
class LookupCache;
class CompileService;
struct JITSymbolBuffer;
} // namespace FEXCore
@@ -102,10 +101,6 @@ struct alignas(FEXCore::Utils::FEX_PAGE_SIZE) InternalThreadState : public FEXCo
NonMovableUniquePtr<FEXCore::IR::PassManager> PassManager;
NonMovableUniquePtr<JITSymbolBuffer> SymbolBuffer;
std::shared_ptr<FEXCore::CompileService> CompileService;
std::shared_mutex ObjectCacheRefCounter {};
// This pointer is owned by the frontend.
FEXCore::SHMStats::ThreadStats* ThreadStats {};
@@ -2,7 +2,6 @@
#pragma once
#ifndef _WIN32
#include <linux/prctl.h>
#include <sys/mman.h>
#include <sys/user.h>
#include <sys/prctl.h>
+5 -5
View File
@@ -361,6 +361,11 @@ def IsSupportedKernel():
return version_check(GetKernelVersion()) >= version_check("5.15")
def main():
if not IsSupportedDistro():
Distro = GetDistro()
print ( "'{} {}' is not a supported distro".format(Distro[0], Distro[1]))
ExitWithStatus(-1)
# Only run on supported arch
if not IsSupportedArch():
print ( "{} is not a supported architecture".format(GetArch()))
@@ -371,11 +376,6 @@ def main():
print ( "Kernel {} is too old. FEX needs 5.15 minimum".format(GetKernelVersion()))
ExitWithStatus(-1)
if not IsSupportedDistro():
Distro = GetDistro()
print ( "'{} {}' is not a supported distro".format(Distro[0], Distro[1]))
ExitWithStatus(-1)
if GetDistro()[0] == "ubuntu":
print ("Getting PPA status: {}".format(("NotInstalled", "Installed")[GetPPAStatus()]))
+24 -10
View File
@@ -17,9 +17,9 @@
#include <fcntl.h>
#include <linux/limits.h>
#include <unistd.h>
#include <sys/poll.h>
#include <poll.h>
#include <sys/prctl.h>
#include <sys/signal.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -137,21 +137,31 @@ fextl::string GetServerSocketName() {
return ServerSocketPath;
}
fextl::string GetServerSocketPath() {
fextl::string GetServerSocketPath(bool ForceTmp) {
fextl::string name {};
fextl::string Folder {};
#ifndef FEX_STEAM_SUPPORT
FEX_CONFIG_OPT(ServerSocketPath, SERVERSOCKETPATH);
name = ServerSocketPath();
if (!ForceTmp) {
name = ServerSocketPath();
if (name.starts_with("/")) {
return name;
if (name.starts_with("/")) {
return name;
}
}
auto Folder = GetTempFolder();
Folder = GetTempFolder();
#else
// Under Steam the FEXServer's socket is a game-specific directory.
auto Folder = GetServerLockFolder();
if (ForceTmp) {
// If we're forcing temporary directory usage then the server socket path has exceeded sun_path 108 byte limit.
// Let's be a bit nice and put some more metadata in the server socket path.
const auto SteamID = getenv("SteamAppId") ?: "";
return fextl::fmt::format("{}/{}.FEXServer.Socket", GetTempFolder(), SteamID);
} else {
// Under Steam the FEXServer's socket is a game-specific directory.
Folder = GetServerLockFolder();
}
#endif
if (name.empty()) {
@@ -203,7 +213,11 @@ int ConnectToServer(ConnectionOption ConnectionOption) {
// Try again with a path-based socket, since abstract sockets will fail if we have been
// placed in a new netns as part of a sandbox.
auto ServerSocketPath = GetServerSocketPath();
auto ServerSocketPath = GetServerSocketPath(false);
if (ServerSocketPath.size() > sizeof(sockaddr_un::sun_path) - 1) {
LogMan::Msg::EFmt("Socket path '{}' too large for Unix domain sockets. Moving to tmp", ServerSocketPath);
ServerSocketPath = FEXServerClient::GetServerSocketPath(true);
}
addr.sun_family = AF_UNIX;
SizeOfSocketString = std::min(ServerSocketPath.size(), sizeof(addr.sun_path) - 1);
+1 -1
View File
@@ -64,7 +64,7 @@ fextl::string GetServerRootFSLockFile();
fextl::string GetTempFolder();
fextl::string GetServerMountFolder();
fextl::string GetServerSocketName();
fextl::string GetServerSocketPath();
fextl::string GetServerSocketPath(bool ForceTmp);
int GetServerFD();
bool SetupClient(std::string_view InterpreterPath);
+2 -1
View File
@@ -539,6 +539,7 @@ static void HandleErrata(FEXCore::HostFeatures* HostFeatures, uint64_t MIDR) {
constexpr uint32_t Implementer_QCOM = 0x51;
constexpr uint32_t PartNum_Oryon1 = 0x001;
constexpr uint32_t PartNum_Oryon3 = 0x002;
auto GetMIDRImplementer = [](uint32_t MIDR) -> uint32_t {
return (MIDR >> 24) & 0xFF;
@@ -552,7 +553,7 @@ static void HandleErrata(FEXCore::HostFeatures* HostFeatures, uint64_t MIDR) {
const uint32_t MIDR_PartNum = GetMIDRPartNum(MIDR);
#ifdef ARCHITECTURE_arm64
if (MIDR_Implementer == Implementer_QCOM && MIDR_PartNum == PartNum_Oryon1) {
if (MIDR_Implementer == Implementer_QCOM && (MIDR_PartNum == PartNum_Oryon1 || MIDR_PartNum == PartNum_Oryon3)) {
// Work around an errata in Qualcomm's Oryon.
// While this CPU implements the RAND extension:
// - The RNDR register works.
+3 -3
View File
@@ -30,15 +30,15 @@ public:
auto data_7 = cpuid(0x7);
Feat_fsgsbase = data_7.ebx & (1U << 0);
Feat_bmi1 = data_7.ebx & (1U << 3);
Feat_avx &= data_7.ebx & (1U << 5);
Feat_avx = Feat_avx && (data_7.ebx & (1U << 5));
Feat_bmi2 = data_7.ebx & (1U << 8);
Feat_clwb = data_7.ebx & (1U << 24);
Feat_rand &= data_7.ebx & (1U << 18);
Feat_rand = Feat_rand && (data_7.ebx & (1U << 18));
Feat_adx = data_7.ebx & (1U << 19);
Feat_clflopt = data_7.ebx & (1U << 23);
Feat_sha = data_7.ebx & (1U << 29);
Feat_vaes = data_7.ecx & (1U << 9);
Feat_pclmulqdq &= data_7.ecx & (1U << 10);
Feat_pclmulqdq = Feat_pclmulqdq && (data_7.ecx & (1U << 10));
Feat_rdpid = data_7.ecx & (1U << 22);
}
+15 -14
View File
@@ -26,24 +26,25 @@ fextl::string GenerateSteamConfigTemplate(const FEX::Config::PortableInformation
return {};
}
// Try and find a mount point.
fextl::string MountPoint {};
// If the graphics provider was provided through an environment variable, then use that.
// Otherwise, try to find a mount point.
const char* GraphicsProvider = getenv("STEAM_COMPAT_GRAPHICS_PROVIDER");
const char* RuntimeDir = getenv("XDG_RUNTIME_DIR");
if (RuntimeDir) {
const char* CacheDir = getenv("XDG_CACHE_HOME");
const auto UserDirectory = fextl::fmt::format("/run/user/{}", geteuid());
if (GraphicsProvider) {
MountPoint = FHU::Filesystem::ParentPath(GraphicsProvider);
} else if (RuntimeDir) {
MountPoint = fextl::fmt::format("{}/fexrootfs/", RuntimeDir);
} else if (FHU::Filesystem::Exists(UserDirectory)) {
MountPoint = fextl::fmt::format("{}/fexrootfs/", UserDirectory);
} else if (CacheDir) {
MountPoint = fextl::fmt::format("{}/fexrootfs/", CacheDir);
} else {
const auto UserDirectory = fextl::fmt::format("/run/user/{}", geteuid());
if (FHU::Filesystem::Exists(UserDirectory)) {
MountPoint = fextl::fmt::format("{}/fexrootfs/", UserDirectory);
} else {
const char* CacheDir = getenv("XDG_CACHE_HOME");
if (CacheDir) {
MountPoint = fextl::fmt::format("{}/fexrootfs/", CacheDir);
} else {
// We tried really hard to find a mount path.
MountPoint = "~/.cache/fexrootfs/";
}
}
// We tried really hard to find a mount path.
MountPoint = "~/.cache/fexrootfs/";
}
// Update the @FEX_COMPAT_TOOL@ config to point to the root of the depot.
+1
View File
@@ -11,3 +11,4 @@ install(TARGETS FEXGetConfig RUNTIME
target_link_libraries(FEXGetConfig PRIVATE ${LIBS})
target_include_directories(FEXGetConfig PRIVATE ${CMAKE_BINARY_DIR}/generated)
target_compile_options(FEXGetConfig PRIVATE ${FEX_TUNE_COMPILE_FLAGS})
+18 -18
View File
@@ -14,7 +14,7 @@
#include <filesystem>
#include <string>
#include <sys/prctl.h>
#include <sys/signal.h>
#include <signal.h>
#include <ucontext.h>
namespace {
@@ -100,35 +100,35 @@ TSOEmulationFacts GetTSOEmulationFacts() {
namespace SIGBUSTest {
static bool* FaultArray {};
__attribute__((naked)) void atomic_store_u16(std::byte* Data, uint16_t Value) {
__attribute__((naked)) void atomic_load_u16(std::byte* Data) {
asm volatile(R"(
stlrh w1, [x0];
ldarh w1, [x0];
ret;
)" ::
: "memory");
: "x1", "memory");
}
__attribute__((naked)) void atomic_store_u32(std::byte* Data, uint32_t Value) {
__attribute__((naked)) void atomic_load_u32(std::byte* Data) {
asm volatile(R"(
stlr w1, [x0];
ldar w1, [x0];
ret;
)" ::
: "memory");
: "x1", "memory");
}
__attribute__((naked)) void atomic_store_u64(std::byte* Data, uint64_t Value) {
__attribute__((naked)) void atomic_load_u64(std::byte* Data) {
asm volatile(R"(
stlr x1, [x0];
ldar x1, [x0];
ret;
)" ::
: "memory");
: "x1", "memory");
}
__attribute__((naked)) void atomic_store_u128(std::byte* Data, uint64_t Value) {
__attribute__((naked)) void atomic_load_u128(std::byte* Data) {
asm volatile(R"(
stlxp w3, x1, x1, [x0];
ldaxp x1, x2, [x0];
ret;
)" ::
: "memory");
: "x1", "x2", "x3", "memory");
}
static void HandleSIGBUS(int, siginfo_t* info, void* context) {
@@ -150,7 +150,7 @@ void TestSIGBUS() {
auto test_fault = [](bool* FaultOffsets, auto AccessFunction, std::byte* AccessArray) {
FaultArray = FaultOffsets;
for (size_t i = 0; i < 64; ++i) {
AccessFunction(AccessArray + i, 1);
AccessFunction(AccessArray + i);
}
};
@@ -176,10 +176,10 @@ void TestSIGBUS() {
bool FaultOffset_64bit[64] {};
bool FaultOffset_128bit[64] {};
test_fault(FaultOffset_16bit, atomic_store_u16, ptr);
test_fault(FaultOffset_32bit, atomic_store_u32, ptr);
test_fault(FaultOffset_64bit, atomic_store_u64, ptr);
test_fault(FaultOffset_128bit, atomic_store_u128, ptr);
test_fault(FaultOffset_16bit, atomic_load_u16, ptr);
test_fault(FaultOffset_32bit, atomic_load_u32, ptr);
test_fault(FaultOffset_64bit, atomic_load_u64, ptr);
test_fault(FaultOffset_128bit, atomic_load_u128, ptr);
munmap(ptr, 4096);
sigaction(SIGBUS, &act, nullptr);
+25 -14
View File
@@ -32,7 +32,6 @@
#include <sys/personality.h>
#include <sys/prctl.h>
#include <sys/random.h>
#include <linux/prctl.h>
#define PAGE_START(x) ((x) & ~(uintptr_t)(4095))
#define PAGE_OFFSET(x) ((x) & 4095)
@@ -767,26 +766,38 @@ public:
// Ensure we don't read past the end into garbage data
stat_buffer[std::clamp(bytes_read, 0L, static_cast<ssize_t>(sizeof(stat_buffer)) - 1)] = '\0';
uint64_t start_code, end_code, start_stack, start_data, end_data, start_brk, arg_start, arg_end, env_start, env_end;
// See man proc_pid_stat
int items_read = sscanf(stat_buffer,
"%*d %*s %*c %*d %*d " // 1 to 5
"%*d %*d %*d %*u %*u " // 6 to 10
"%*u %*u %*u %*u %*u " // 11 to 15
"%*d %*d %*d %*d %*d " // 16 to 20
"%*d %*u %*u %*d %*u " // 21 to 25
"%llu %llu %llu %*u %*u " // 26 to 30
"%*u %*u %*u %*u %*u " // 31 to 35
"%*u %*u %*d %*d %*u " // 36 to 40
"%*u %*u %*u %*d %llu " // 40 to 45
"%llu %llu %llu %llu %llu " // 46 to 50
"%llu", // 51
&map.start_code, &map.end_code, &map.start_stack, &map.start_data, &map.end_data, &map.start_brk,
&map.arg_start, &map.arg_end, &map.env_start, &map.env_end);
"%*d %*s %*c %*d %*d " // 1 to 5
"%*d %*d %*d %*u %*u " // 6 to 10
"%*u %*u %*u %*u %*u " // 11 to 15
"%*d %*d %*d %*d %*d " // 16 to 20
"%*d %*u %*u %*d %*u " // 21 to 25
"%lu %lu %lu %*u %*u " // 26 to 30
"%*u %*u %*u %*u %*u " // 31 to 35
"%*u %*u %*d %*d %*u " // 36 to 40
"%*u %*u %*u %*d %lu " // 40 to 45
"%lu %lu %lu %lu %lu " // 46 to 50
"%lu", // 51
&start_code, &end_code, &start_stack, &start_data, &end_data, &start_brk, &arg_start, &arg_end, &env_start, &env_end);
if (items_read != 10) {
return false;
}
map.start_code = start_code;
map.end_code = end_code;
map.start_stack = start_stack;
map.start_data = start_data;
map.end_data = end_data;
map.start_brk = start_brk;
map.arg_start = arg_start;
map.arg_end = arg_end;
map.env_start = env_start;
map.env_end = env_end;
map.brk = reinterpret_cast<uint64_t>(sbrk(0));
// The kernel will leave these values unchanged, see implementation in sys.c
@@ -63,7 +63,7 @@ $end_info$
#include <utility>
#include <sys/sysinfo.h>
#include <sys/signal.h>
#include <signal.h>
namespace FEX::Logging {
static bool SilentLog {};
@@ -597,9 +597,14 @@ int main(int argc, char** argv, char** const envp) {
SyscallHandler->DefaultProgramBreak(BRKInfo.Base, BRKInfo.Size);
// Request code cache generation
if (FEXCore::Config::Get_ENABLECODECACHINGWIP()) {
// Request code cache generation
FEXServerClient::PopulateCodeCache(FEXServerClient::GetServerFD(), Loader.GetMainElfFD(), FEXCore::Config::Get_MULTIBLOCK());
if (VDSOMapping) {
// Finalize code cache for libVDSO-guest.so. This needs to be done explicitly since VDSO doesn't use LoadLib.
SyscallHandler->TriggerGuestLibWrapperCodeCacheLoad(*ParentThread->Thread, reinterpret_cast<uintptr_t>(VDSOMapping.VDSOBase));
}
}
// Pull RIP and stack pointer from loader and set the thread data to it.
+12
View File
@@ -17,6 +17,7 @@
#include <OptionParser.h>
#include <fmt/printf.h>
#include <libgen.h>
#include <fstream>
#include <optional>
@@ -201,7 +202,18 @@ static std::optional<std::string> GenerateSingleCache(FEXCore::ExecutableFileInf
{
std::vector<std::unique_ptr<ELFCodeLoader>> LoaderMem;
// Refuse to continue if the block list contains any out-of-bounds blocks.
// This often indicates a corrupted code map.
{
auto [min_val, max_val] = std::ranges::minmax_element(BlockList, std::less {});
auto MinBound = SyscallHandler->LookupExecutableFileSection(Thread, *min_val + SyscallHandler->VAFileStart);
auto MaxBound = SyscallHandler->LookupExecutableFileSection(Thread, *max_val + SyscallHandler->VAFileStart);
LOGMAN_THROW_A_FMT(MinBound && MaxBound, "Cached blocks offsets {:#x}-{:#x} out of bounds for library {} ({:016x} @ {:#x})!",
*min_val, *max_val, Binary.Filename, Binary.FileId, SyscallHandler->VAFileStart);
}
fmt::print(stderr, "Compiling code...\n");
FEX_CONFIG_OPT(MaxInst, MAXINST);
for (auto Addr : BlockList) {
if (!CTX->CheckIfBlockIsCacheable(*Thread, Addr + SyscallHandler->VAFileStart, MaxInst)) {
+1 -1
View File
@@ -21,7 +21,7 @@
#include <optional>
#include <poll.h>
#include <sys/prctl.h>
#include <sys/signal.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
+16 -6
View File
@@ -12,6 +12,7 @@
#include <FEXCore/HLE/SourcecodeResolver.h>
#include <fmt/ranges.h>
#include <inttypes.h>
#include <atomic>
#include <cassert>
@@ -64,6 +65,9 @@ static std::string NewCodeMapDirectory;
// Path to directory for processed code maps (suitable for cache generation)
static std::string ReadyCodeMapDirectory;
// Path to FEXOfflineCompiler executable (inferred from FEXServer install location)
const std::string OfflineCompilerPath = (std::filesystem::read_symlink("/proc/self/exe").parent_path() / "FEXOfflineCompiler").string();
void SetWatchFD(int FD) {
WatchFD = FD;
}
@@ -94,8 +98,8 @@ void CheckRaiseFDLimit() {
if (MaxFDs.rlim_cur == MaxFDs.rlim_max) {
fprintf(stderr, "[FEXMountDaemon] Our open FD limit is already set to max and we are wanting to increase it\n");
fprintf(stderr, "[FEXMountDaemon] FEXMountDaemon will now no longer be able to track new instances of FEX\n");
fprintf(stderr, "[FEXMountDaemon] Current limit is %zd(hard %zd) FDs and we are at %zd\n", MaxFDs.rlim_cur, MaxFDs.rlim_max,
GetNumFilesOpen());
fprintf(stderr, "[FEXMountDaemon] Current limit is %" PRIuMAX "(hard %" PRIuMAX ") FDs and we are at %zu\n", (uintmax_t)MaxFDs.rlim_cur,
(uintmax_t)MaxFDs.rlim_max, GetNumFilesOpen());
fprintf(stderr, "[FEXMountDaemon] Ask your administrator to raise your kernel's hard limit on open FDs\n");
return;
}
@@ -109,7 +113,8 @@ void CheckRaiseFDLimit() {
NewLimit.rlim_cur = std::min(NewLimit.rlim_cur, NewLimit.rlim_max);
if (setrlimit(RLIMIT_NOFILE, &NewLimit) != 0) {
fprintf(stderr, "[FEXMountDaemon] Couldn't raise FD limit to %zd even though our hard limit is %zd\n", NewLimit.rlim_cur, NewLimit.rlim_max);
fprintf(stderr, "[FEXMountDaemon] Couldn't raise FD limit to %" PRIu64 " even though our hard limit is %" PRIu64 "\n",
(uintmax_t)NewLimit.rlim_cur, (uintmax_t)NewLimit.rlim_max);
} else {
// Set the new limit
MaxFDs = NewLimit;
@@ -223,7 +228,12 @@ bool InitializeServerSocket(bool abstract) {
if (abstract) {
ServerSocketName = FEXServerClient::GetServerSocketName();
} else {
ServerSocketName = FEXServerClient::GetServerSocketPath();
ServerSocketName = FEXServerClient::GetServerSocketPath(false);
if (ServerSocketName.size() > sizeof(sockaddr_un::sun_path) - 1) {
LogMan::Msg::EFmt("Socket path '{}' too large for Unix domain sockets. Moving to tmp", ServerSocketName);
ServerSocketName = FEXServerClient::GetServerSocketPath(true);
}
// Unlink the socket file if it exists
// We are being asked to create a daemon, not error check
// We don't care if this failed or not
@@ -470,8 +480,8 @@ int32_t EmbedSubprocess(const char* path, char* const* args) {
* Spawn a FEXOfflineCompiler instance to generate a code cache from the given code map
*/
static int RunOfflineCompiler(const char* CodeMap) {
const char* ExecveArgs[] = {"FEXOfflineCompiler", "generate", CodeMap, nullptr};
return EmbedSubprocess("FEXOfflineCompiler", const_cast<char* const*>(&ExecveArgs[0]));
const char* ExecveArgs[] = {OfflineCompilerPath.c_str(), "generate", CodeMap, nullptr};
return EmbedSubprocess(OfflineCompilerPath.c_str(), const_cast<char* const*>(&ExecveArgs[0]));
};
void HandleSocketData(fasio::tcp_socket& Socket) {
+1 -1
View File
@@ -9,7 +9,7 @@
#include <fcntl.h>
#include <filesystem>
#include <sys/poll.h>
#include <poll.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <thread>
@@ -35,6 +35,7 @@ $end_info$
#include <FEXCore/fextl/string.h>
#include <FEXCore/fextl/vector.h>
#include <FEXHeaderUtils/Filesystem.h>
#include <FEXHeaderUtils/Syscalls.h>
#include <atomic>
#include <cstring>
@@ -1171,7 +1172,7 @@ GdbServer::HandledPacketType GdbServer::CommandMultiLetterV(const fextl::string&
}
if (packet.starts_with("vKill")) {
tgkill(::getpid(), ::getpid(), SIGKILL);
FHU::Syscalls::tgkill(::getpid(), ::getpid(), SIGKILL);
}
// TODO: vRun
@@ -649,17 +649,19 @@ void SignalDelegator::HandleGuestSignal(FEX::HLE::ThreadStateObject* ThreadObjec
"capacity size. This will "
"likely crash! Asserting now!");
// Peek into sigset_t implementation details, extracting the __val member for glibc and __bits for musl
auto& [sigmask_val] = _context->uc_sigmask;
static_assert(sizeof(sigmask_val[0]) == sizeof(uint64_t), "Unknown sigset_t layout");
ThreadObject->SignalInfo.DeferredSignalFrames.emplace_back(ThreadStateObject::DeferredSignalState {
.Info = SigInfo,
.Signal = Signal,
.SigMask = _context->uc_sigmask.__val[0],
.SigMask = sigmask_val[0],
});
uint64_t NewMask = GetNewSigMask(Signal);
// Update our host signal mask so we don't hit race conditions with signals
// This allows us to maintain the expected signal mask through the guest signal handling and then all the way back again
memcpy(&_context->uc_sigmask, &NewMask, sizeof(uint64_t));
sigmask_val[0] = GetNewSigMask(Signal);
// Now update the faulting page permissions so it will fault on write.
mprotect(reinterpret_cast<void*>(&Thread->InterruptFaultPage), sizeof(Thread->InterruptFaultPage), PROT_NONE);
@@ -292,6 +292,7 @@ public:
std::optional<FEXCore::ExecutableFileSectionInfo>
LookupExecutableFileSection(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) final override;
void TriggerGuestLibWrapperCodeCacheLoad(FEXCore::Core::InternalThreadState&, uint64_t AnyAddr);
int OpenCodeMapFile() override;
FEXCore::HLE::ExecutableRangeInfo QueryGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Address) override;
@@ -33,7 +33,7 @@ $end_info$
#include <stdint.h>
#include <sched.h>
#include <sys/personality.h>
#include <sys/poll.h>
#include <poll.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
@@ -366,6 +366,26 @@ uint64_t SyscallHandler::GuestMremap(bool Is64Bit, FEXCore::Core::InternalThread
return Result;
}
void SyscallHandler::TriggerGuestLibWrapperCodeCacheLoad(FEXCore::Core::InternalThreadState& Thread, uint64_t AnyAddr) {
if (!EnableCodeCaching) {
return;
}
// TODO: Instead of deferring the entire cache load, only delay applicance of sha256 relocations!
auto lk = FEXCore::GuardSignalDeferringSection<std::shared_lock>(VMATracking.Mutex, &Thread);
auto VMAEntry = VMATracking.FindVMAEntry(reinterpret_cast<uint64_t>(AnyAddr));
for (auto* VMA = VMAEntry->second.Resource->FirstVMA; VMA; VMA = VMA->ResourceNextVMA) {
if (!VMA->Prot.Executable) {
continue;
}
auto SectionInfo = BuildSectionInfo(*VMAEntry->second.Resource, VMA->Base, VMA->Length);
LoadCodeCache(Thread, SectionInfo, CodeCacheConfigId);
}
}
int SyscallHandler::OpenCodeMapFile() {
// Query from FEXServer whether this is the first instance of this executable; if it is, also enable code dumping!
FEX_CONFIG_OPT(RootFSPath, ROOTFS);
@@ -623,7 +643,11 @@ SyscallHandler::TrackMmap(FEXCore::Core::InternalThreadState* Thread, uint64_t a
// Load code cache if present.
// FEXServer was requested to generate library caches on program launch.
if (EnableCodeCaching && Resource && Resource->MappedFile && VMATracking::VMAProt::fromProt(prot).Executable) {
if (Thread) {
if (Resource->MappedFile->Filename.ends_with("-guest.so")) {
// For guest library wrappers, cache loading must be delayed until LoadLib is called.
// Before that, we can't patch up the SHA256 function identifiers.
LogMan::Msg::IFmt("Delaying code cache load for {}", Resource->MappedFile->Filename);
} else if (Thread) {
if (!Resource->RequiresDelayedCacheLoad) {
CachedSection.emplace(BuildSectionInfo(*Resource, addr, Size));
} else {
@@ -30,7 +30,7 @@ $end_info$
#include <optional>
#include <sys/stat.h>
#include <bits/types/sigset_t.h>
#include <signal.h>
#include <linux/seccomp.h>
namespace FEX::HLE {
+2
View File
@@ -259,6 +259,8 @@ void ThunkHandler_impl::LoadLib(std::string_view Name) {
LogMan::Msg::DFmt("Loaded {} syms", i);
}
_SyscallHandler->TriggerGuestLibWrapperCodeCacheLoad(*ThreadObject->Thread, ThreadObject->Thread->CurrentFrame->State.rip);
}
/**
@@ -21,6 +21,10 @@ struct VDSOMapping {
size_t VDSOSize {};
void* X86GeneratedCodePtr {};
size_t X86GeneratedCodeSize {};
explicit operator bool() const {
return VDSOBase != nullptr;
}
};
struct VDSOEntrypoints {
+4 -1
View File
@@ -28,6 +28,7 @@ $end_info$
#include <FEXCore/Utils/SignalScopeGuards.h>
#include "Windows/Common/Allocator.h"
#include "Windows/Common/EnvironmentVariablesHandling.h"
#include "Common/CallRetStack.h"
#include "Common/JITGuardPage.h"
#include "Common/Config.h"
@@ -595,6 +596,8 @@ NTSTATUS ProcessInit() {
const bool IsWine = !!GetProcAddress(NtDll, "wine_get_version");
OvercommitTracker.emplace(IsWine);
FEX::Windows::SetupEnvironmentVariableValues(NtDll);
FEX::Windows::Allocator::SetupHooks(NtDll);
{
@@ -677,7 +680,7 @@ bool ResetToConsistentStateImpl(const ThreadCPUArea CPUArea, EXCEPTION_RECORD* E
// A suspend interrupt can occur in ExitFunctionEC before InSimulation is unset and set SuspendDoorbell. If this
// occurs then it is still our duty to cooperatively suspend with an appropriate context. To support this, after
// unsetting InSimulation a brk #0xCAFE instruction will be raised that we can handle here.
NativeContext->Pc = reinterpret_cast<uintptr_t>(ExitFunctionSuspendResumePoint); // Jump to the suspend resume point.
NativeContext->Pc = reinterpret_cast<uintptr_t>(&ExitFunctionSuspendResumePoint); // Jump to the suspend resume point.
*CPUArea.Area->SuspendDoorbell = 0;
return true;
}
+1
View File
@@ -9,6 +9,7 @@ target_include_directories(CommonWindowsRuntime PRIVATE "${CMAKE_SOURCE_DIR}/Sou
add_library(CommonWindows STATIC
Allocator.cpp
CPUFeatures.cpp
EnvironmentVariablesHandling.cpp
SHMStats.cpp
InvalidationTracker.cpp
ImageTracker.cpp
+9
View File
@@ -31,6 +31,14 @@ uint64_t ReadRegU64(HKEY Key, const char* Name) {
} // namespace
namespace FEX::Windows {
#define GetSysReg(name, reg) \
static uint64_t Get_##name() { \
uint64_t Result {}; \
__asm("mrs %[Res], " #reg : [Res] "=r"(Result)); \
return Result; \
}
GetSysReg(DCZID_EL0, DCZID_EL0);
class CPUFeaturesFromRegistry final : public FEX::CPUFeatures {
public:
explicit CPUFeaturesFromRegistry(HKEY Key) {
@@ -43,6 +51,7 @@ public:
ZFR0.SetReg(ReadRegU64(Key, "CP 4024"));
MMFR1.SetReg(ReadRegU64(Key, "CP 4039"));
ISAR2.SetReg(ReadRegU64(Key, "CP 4032"));
DCZID.SetReg(Get_DCZID_EL0());
FillFeatureFlags();
}
};
+12
View File
@@ -272,6 +272,18 @@ int write(int FileHandle, const void* Buf, unsigned int MaxCharCount) {
return _write(FileHandle, Buf, MaxCharCount);
}
DLLEXPORT_FUNC(int, ftruncate, (int FileHandle, off_t Length)) {
FILE_END_OF_FILE_INFO Info {.EndOfFile = {.QuadPart = Length}};
if (!SetFileInformationByHandle(GetFile(FileHandle)->Handle, FileEndOfFileInfo, &Info, sizeof(Info))) {
return ErrnoReturn(EINVAL);
}
return 0;
}
int _chsize(int FileHandle, long Length) {
return ftruncate(FileHandle, Length);
}
DLLEXPORT_FUNC(int, _isatty, (int _FileHandle)) {
return 0;
}
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
#include <libloaderapi.h>
#include <stdlib.h>
#include <winternl.h>
#include <wine/unixlib.h>
namespace FEX::Windows {
void SetupEnvironmentVariableValues(HMODULE NtDll) {
auto Sym = GetProcAddress(NtDll, "__wine_set_unix_env");
// On an ARM system we are expecting uncached memory to have marked overhead due to atomic memory usage.
// If `tu_override_uncached_as_cache_coherent` isn't already controlled by the user, then set it here.
// This lets the `turnip` mesa driver allocate uncached memory types as cached coherent instead if the hardware supports it.
//
// The only downside for this approach is that the GPU /may/ need to snoop CPU cachelines which could add some additional load
// on to the GPU side, but is unlikely to matter due to x86 emulation using excessive load-acquire/store-release semantic memory operations.
//
// Other UMA ARM platforms will run in to the same problem, with their own workarounds:
// - NVIDIA Tegra/Spark: Their proprietary driver always maps uncached as cached-coherent.
// - Windows Snapdragon: Same as Tegra
// - Asahi,Mali,PowerVR,Exynos,etc: Unknown behaviour
//
// This `__wine_set_unix_env` path may also not be long-term viable.
// Make sure to communicate with the Wine/Proton people if this interface is expected to change!
// A /possible/ workaround for Proton would be to set the environment variable in the launch script.
// - That would have the downside that arm64 native Windows applications would get workaround set, which isn't strictly necessary.
if (Sym && getenv("tu_override_uncached_as_cache_coherent") == nullptr) {
auto WineSetEnv = reinterpret_cast<decltype(__wine_set_unix_env)>(Sym);
WineSetEnv("tu_override_uncached_as_cache_coherent", "true");
}
}
} // namespace FEX::Windows
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: MIT
#pragma once
#include <winternl.h>
namespace FEX::Windows {
void SetupEnvironmentVariableValues(HMODULE NtDll);
}
+3
View File
@@ -29,6 +29,7 @@ $end_info$
#include <FEXCore/Utils/SignalScopeGuards.h>
#include "Windows/Common/Allocator.h"
#include "Windows/Common/EnvironmentVariablesHandling.h"
#include "Common/CallRetStack.h"
#include "Common/JITGuardPage.h"
#include "Common/Config.h"
@@ -563,6 +564,8 @@ void BTCpuProcessInit() {
WineUnixCall = *reinterpret_cast<decltype(WineUnixCall)*>(Sym);
}
FEX::Windows::SetupEnvironmentVariableValues(NtDll);
// wow64.dll will only initialise the cross-process queue if this is set
GetTLS().Wow64Info().CpuFlags = WOW64_CPUFLAGS_SOFTWARE;
+2
View File
@@ -11,6 +11,8 @@ extern "C" {
typedef UINT64 unixlib_handle_t;
extern NTSTATUS(WINAPI* __wine_set_unix_env)(const char*, const char*);
extern NTSTATUS(WINAPI* __wine_unix_call_dispatcher)(unixlib_handle_t, unsigned int, void*);
static inline NTSTATUS __wine_unix_call(unixlib_handle_t handle, unsigned int code, void* args) {
+1 -1
View File
@@ -1,4 +1,4 @@
# FEX-2604
# FEX-2605
## FEXCore
See [FEXCore/Readme.md](../FEXCore/Readme.md) for more details
+2
View File
@@ -1,6 +1,8 @@
#include <catch2/catch_all.hpp>
#include <FEXCore/Utils/Allocator.h>
#include <unistd.h>
namespace {
using FEXCore::Allocator::MemoryRegion;
@@ -0,0 +1,33 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0",
"RBX": "0"
}
}
%endif
; FIST/FISTP to a 16-bit destination must not set IE when the input is a
; denormal that rounds into range. The overflow/NaN-Inf detection should
; only raise IE for exponent == 0x7fff or exponent >= 0x400e.
mov r15, 0xe0000000
fninit
mov dword [r15 + 0], 0x00000001
mov dword [r15 + 4], 0x00000000
mov word [r15 + 8], 0x0000
fld tword [r15 + 0]
fistp word [r15 + 16]
movzx rax, word [r15 + 16]
fnstsw ax
movzx rbx, ax
and rbx, 1
xor rax, rax
hlt
@@ -0,0 +1,30 @@
%ifdef CONFIG
{
"RegData": {
"RBX": "0x0001"
}
}
%endif
; FSCALE(+0, +Inf) is 0 * 2^(+Inf) = 0 * Inf, which must raise the invalid
; operation exception (IE=1).
mov r15, 0xe0000000
fninit
mov dword [r15 + 0], 0x00000000
mov dword [r15 + 4], 0x7ff00000
fld qword [r15 + 0]
fldz
fscale
fstp qword [r15 + 16]
fstp st0
fnstsw ax
movzx rbx, ax
and rbx, 1
hlt
+27
View File
@@ -0,0 +1,27 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0x7ff0000000000000",
"RBX": "0x7ff0000000000000"
}
}
%endif
; FXTRACT(+Inf) must produce exp=+Inf, sig=+Inf.
mov r15, 0xe0000000
fninit
mov dword [r15 + 0], 0x00000000
mov dword [r15 + 4], 0x7ff00000
fld qword [r15 + 0]
fxtract
fstp qword [r15 + 16]
fstp qword [r15 + 24]
mov rax, [r15 + 24]
mov rbx, [r15 + 16]
hlt
@@ -0,0 +1,44 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0x7ff0000000000000",
"RBX": "0x7ff0000000000000",
"RCX": "0x7ff0000000000000",
"RDX": "0xfff0000000000000"
},
"Env": { "FEX_X87REDUCEDPRECISION" : "1" },
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif
; FXTRACT(+/-Inf) under reduced-precision F64 must produce exp=+Inf with the
; significand preserving the input sign.
finit
fld qword [rel pos_inf]
fxtract
fstp qword [rel sig_pos]
fstp qword [rel exp_pos]
fld qword [rel neg_inf]
fxtract
fstp qword [rel sig_neg]
fstp qword [rel exp_neg]
mov rax, [rel exp_pos]
mov rbx, [rel sig_pos]
mov rcx, [rel exp_neg]
mov rdx, [rel sig_neg]
hlt
align 4096
pos_inf: dq 0x7ff0000000000000
neg_inf: dq 0xfff0000000000000
exp_pos: dq 0
sig_pos: dq 0
exp_neg: dq 0
sig_neg: dq 0
+28
View File
@@ -0,0 +1,28 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0x7ff8000000000000",
"RBX": "0x7ff8000000000000"
}
}
%endif
; FXTRACT(QNaN) must propagate the NaN into both the exponent and significand
; slots.
mov r15, 0xe0000000
fninit
mov dword [r15 + 0], 0x00000000
mov dword [r15 + 4], 0x7ff80000
fld qword [r15 + 0]
fxtract
fstp qword [r15 + 16]
fstp qword [r15 + 24]
mov rax, [r15 + 24]
mov rbx, [r15 + 16]
hlt
@@ -0,0 +1,29 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0x7ff8000000000000",
"RBX": "0x7ff8000000000000"
},
"Env": { "FEX_X87REDUCEDPRECISION" : "1" }
}
%endif
; FXTRACT(QNaN) under reduced-precision F64 must propagate the NaN into both
; exponent and significand.
mov r15, 0xe0000000
fninit
mov dword [r15 + 0], 0x00000000
mov dword [r15 + 4], 0x7ff80000
fld qword [r15 + 0]
fxtract
fstp qword [r15 + 16]
fstp qword [r15 + 24]
mov rax, [r15 + 24]
mov rbx, [r15 + 16]
hlt
+128
View File
@@ -0,0 +1,128 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0x40A00000",
"RBX": "0x7FC00000",
"RCX": "0x00000000",
"RDX": "0x80000000",
"RSI": "0x4014000000000000",
"RDI": "0x7FF8000000000000",
"R8": "0x8000000000000000",
"R9": "0x0000000000000000",
"R10": "0x40A00000",
"R11": "0x7FC00000",
"R12": "0x4014000000000000",
"R13": "0x7FF8000000000000"
},
"HostFeatures": ["AVX"],
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif
; MAXPS/MAXPD/MINPS/MINPD must return src2 when either operand is NaN
; or when the inputs are signed-zero ties. Exercise lane 0 with all
; four combinations.
bits 64
mov rbp, 0x100000000
mov dword [rbp + 0], 0x7FC00000
mov dword [rbp + 4], 0x7FC00000
mov dword [rbp + 8], 0x7FC00000
mov dword [rbp + 12], 0x7FC00000
mov dword [rbp + 16], 0x40A00000
mov dword [rbp + 20], 0x40A00000
mov dword [rbp + 24], 0x40A00000
mov dword [rbp + 28], 0x40A00000
mov dword [rbp + 32], 0x00000000
mov dword [rbp + 36], 0x00000000
mov dword [rbp + 40], 0x00000000
mov dword [rbp + 44], 0x00000000
mov dword [rbp + 48], 0x80000000
mov dword [rbp + 52], 0x80000000
mov dword [rbp + 56], 0x80000000
mov dword [rbp + 60], 0x80000000
mov rax, 0x7FF8000000000000
mov qword [rbp + 64], rax
mov qword [rbp + 72], rax
mov rax, 0x4014000000000000
mov qword [rbp + 80], rax
mov qword [rbp + 88], rax
xor eax, eax
mov qword [rbp + 96], rax
mov qword [rbp + 104], rax
mov rax, 0x8000000000000000
mov qword [rbp + 112], rax
mov qword [rbp + 120], rax
movups xmm0, [rbp + 0]
movups xmm1, [rbp + 16]
maxps xmm0, xmm1
movd eax, xmm0
movups xmm0, [rbp + 16]
movups xmm1, [rbp + 0]
maxps xmm0, xmm1
movd ebx, xmm0
movups xmm0, [rbp + 48]
movups xmm1, [rbp + 32]
maxps xmm0, xmm1
movd ecx, xmm0
movups xmm0, [rbp + 32]
movups xmm1, [rbp + 48]
maxps xmm0, xmm1
movd edx, xmm0
movups xmm0, [rbp + 64]
movups xmm1, [rbp + 80]
maxpd xmm0, xmm1
movq rsi, xmm0
movups xmm0, [rbp + 80]
movups xmm1, [rbp + 64]
maxpd xmm0, xmm1
movq rdi, xmm0
movups xmm0, [rbp + 96]
movups xmm1, [rbp + 112]
maxpd xmm0, xmm1
movq r8, xmm0
movups xmm0, [rbp + 112]
movups xmm1, [rbp + 96]
maxpd xmm0, xmm1
movq r9, xmm0
movups xmm0, [rbp + 0]
movups xmm1, [rbp + 16]
minps xmm0, xmm1
movd r10d, xmm0
movups xmm0, [rbp + 16]
movups xmm1, [rbp + 0]
minps xmm0, xmm1
movd r11d, xmm0
movups xmm0, [rbp + 64]
movups xmm1, [rbp + 80]
minpd xmm0, xmm1
movq r12, xmm0
movups xmm0, [rbp + 80]
movups xmm1, [rbp + 64]
minpd xmm0, xmm1
movq r13, xmm0
hlt
+147
View File
@@ -0,0 +1,147 @@
%ifdef CONFIG
{
"RegData": {
"R13": "0x20",
"R14": "0x0000000000010dd4",
"R15": "1"
}
}
%endif
; FEX-Emu had a bug where cmpxchg8b/cmpxchg16b wasn't setting z flag correctly on flagm supporting CPUs.
; This runs through all the configurations to both ensure that the z flag is set correctly, and that the other flags aren't affected.
; There is an additional cmpxchg8b test in another file.
global temp_data
%define FULL_FLAGS ((1 << 0) | (1 << 2) | (1 << 4) | (1 << 6) | (1 << 7))
%define EMPTY_FLAGS
%define DATA_LOW 0x4142434445464748
%define DATA_HIGH 0x5152535455565758
%define DATA_INCORRECT_LOW 0x4142433445464748
%define DATA_INCORRECT_HIGH 0x5152533455565758
; Clobbers: RAX
%macro reset_data 0
mov rax, DATA_LOW
mov [rel temp_data], rax
mov rax, DATA_HIGH
mov [rel temp_data + 8], rax
%endmacro
; Clobbers: RAX
; Args: <immediate constant>
%macro reset_flag 1
mov rax, %1
push rax
popfq
%endmacro
; Clobbers: RAX, RBX, RCX, RDX
; Compares incoming values against memory, and replaces
; Args: <64-bit immediate>, <64-bit immediate>
; Return: Compare result in ZF (ZF==1 == compare_success)
%macro cas_u64x2 2
mov rax, %1
mov rdx, %2
mov rbx, 0
mov rcx, 0
cmpxchg16b [rel temp_data]
%endmacro
; Clobbers: RAX, RBX
; Compares flags with correct result
; Args: <jnz if ZF == 0, jz if ZF == 1>, <Expected other flags>
%macro check_flags 2
pushfq
pop rbx
; Remove IF and Reserved
and rbx, ~(0x202)
; just compare ZF
mov rax, rbx
and rax, (1 << 6)
%if %1 == 0
jz %%.no_error
%else
jnz %%.no_error
%endif
hlt
%%.no_error:
; compare full flags
cmp rbx, %2
je %%.second_no_error
hlt
%%.second_no_error:
; Continue forward
%endmacro
; Args: <Compare Result>, <Expected flags>, <Data to compare low>, <Data to compare high>
%macro do_test 4
reset_flag %2
reset_data
cas_u64x2 %3, %4
; Check flag adding reserved for comparison
check_flags %1, %2
%endmacro
mov r15, 0
mov r14, 0
mov r13, 0
mov rsp, 0xe000_1000
; %define FULL_FLAGS ((1 << 0) | (1 << 2) | (1 << 4) | (1 << 6) | (1 << 7))
%assign eq_val 0
; EQ
%rep 2
%assign flag_0 0
%rep 2
%assign flag_2 0
%rep 2
%assign flag_4 0
%rep 2
%assign flag_7 0
%rep 2
; if eq_val == 0 then zf is expected to be zero, aka non-match
%if eq_val == 0
%assign data_low DATA_LOW
%assign data_high DATA_INCORRECT_HIGH
%else
%assign data_low DATA_LOW
%assign data_high DATA_HIGH
%endif
%assign expected_flags ((flag_0 << 0) | (flag_2 << 2) | (flag_4 << 4) | (flag_7 << 7) | (eq_val << 6))
inc r13
do_test eq_val, expected_flags, data_low, data_high
%assign flag_7 flag_7+1
%endrep
%assign flag_4 flag_4+1
%endrep
%assign flag_2 flag_2+1
%endrep
%assign flag_0 flag_0+1
%endrep
%assign eq_val eq_val+1
%endrep
mov r15, 1
lea r14, [rel .end]
.end:
hlt
align 4096
temp_data:
dq 0
dq 0
+144
View File
@@ -0,0 +1,144 @@
%ifdef CONFIG
{
"RegData": {
"R13": "0x20",
"R14": "0x0000000000010c74",
"R15": "1"
}
}
%endif
; FEX-Emu had a bug where cmpxchg8b/cmpxchg16b wasn't setting z flag correctly on flagm supporting CPUs.
; This runs through all the configurations to both ensure that the z flag is set correctly, and that the other flags aren't affected.
; There is an additional cmpxchg16b test in another file.
global temp_data
%define FULL_FLAGS ((1 << 0) | (1 << 2) | (1 << 4) | (1 << 6) | (1 << 7))
%define EMPTY_FLAGS
%define DATA_LOW 0x4142434445464748
%define DATA_HIGH 0x5152535455565758
%define DATA_INCORRECT_LOW 0x4142433445464748
%define DATA_INCORRECT_HIGH 0x5152533455565758
; Clobbers: RAX
%macro reset_data 0
mov rax, DATA_LOW
mov [rel temp_data], rax
mov rax, DATA_HIGH
mov [rel temp_data + 8], rax
%endmacro
; Clobbers: RAX
; Args: <immediate constant>
%macro reset_flag 1
mov rax, %1
push rax
popfq
%endmacro
; Clobbers: RAX, RBX, RCX, RDX
; Compares incoming values against memory, and replaces
; Args: <64-bit immediate>
; Return: Compare result in ZF (ZF==1 == compare_success)
%macro cas_u32x2 1
mov eax, (%1 & 0xFFFF_FFFF)
mov edx, %1 >> 32
mov ebx, 0
mov ecx, 0
cmpxchg8b [rel temp_data]
%endmacro
; Clobbers: RAX, RBX
; Compares flags with correct result
; Args: <jnz if ZF == 0, jz if ZF == 1>, <Expected other flags>
%macro check_flags 2
pushfq
pop rbx
; Remove IF and Reserved
and rbx, ~(0x202)
; just compare ZF
mov rax, rbx
and rax, (1 << 6)
%if %1 == 0
jz %%.no_error
%else
jnz %%.no_error
%endif
hlt
%%.no_error:
; compare full flags
cmp rbx, %2
je %%.second_no_error
hlt
%%.second_no_error:
; Continue forward
%endmacro
; Args: <Compare Result>, <Expected flags>, <Data to compare>
%macro do_test 3
reset_flag %2
reset_data
cas_u32x2 %3
; Check flag adding reserved for comparison
check_flags %1, %2
%endmacro
mov r15, 0
mov r14, 0
mov r13, 0
mov rsp, 0xe000_1000
; %define FULL_FLAGS ((1 << 0) | (1 << 2) | (1 << 4) | (1 << 6) | (1 << 7))
%assign eq_val 0
; EQ
%rep 2
%assign flag_0 0
%rep 2
%assign flag_2 0
%rep 2
%assign flag_4 0
%rep 2
%assign flag_7 0
%rep 2
; if eq_val == 0 then zf is expected to be zero, aka non-match
%if eq_val == 0
%assign data DATA_INCORRECT_LOW
%else
%assign data DATA_LOW
%endif
%assign expected_flags ((flag_0 << 0) | (flag_2 << 2) | (flag_4 << 4) | (flag_7 << 7) | (eq_val << 6))
inc r13
do_test eq_val, expected_flags, data
%assign flag_7 flag_7+1
%endrep
%assign flag_4 flag_4+1
%endrep
%assign flag_2 flag_2+1
%endrep
%assign flag_0 flag_0+1
%endrep
%assign eq_val eq_val+1
%endrep
mov r15, 1
lea r14, [rel .end]
.end:
hlt
align 4096
temp_data:
dq 0
dq 0
@@ -0,0 +1,78 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "1"
}
}
%endif
; FEX-Emu had a bug where segment registers prefixed with `o16` were still pushing and popping a full 64-bits to the stack.
; With o16 it is supposed to only operate on 16-bits. Run through the instructions and just ensure it is pushing/popping the correct amount.
; Need to save and restore fs/gs base on this test.
rdfsbase rax
mov [rel .data_segment], rax
rdgsbase rax
mov [rel .data_segment + 8], rax
mov rax, 0
mov rbx, 0xe000_0ffe
mov rcx, 0xe000_1000
mov rsp, 0xe000_1000
; Ensure 16-bit FS/GS push/pops are the correct size.
o16 push fs
cmp rsp, rbx
jne .bad
o16 pop fs
cmp rsp, rcx
jne .bad
o16 push gs
cmp rsp, rbx
jne .bad
o16 pop gs
cmp rsp, rcx
jne .bad
; Check 64-bit as well.
mov rbx, 0xe000_0ff8
push fs
cmp rsp, rbx
jne .bad
pop fs
cmp rsp, rcx
jne .bad
push gs
cmp rsp, rbx
jne .bad
pop gs
cmp rsp, rcx
jne .bad
mov rax, 1
jmp .end
.bad:
mov rax, 0
.end:
mov rbx, [rel .data_segment]
wrfsbase rbx
mov rbx, [rel .data_segment + 8]
wrgsbase rbx
hlt
align 4096
.data_segment:
dq 0
dq 0
+284
View File
@@ -0,0 +1,284 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0xd0f9338e"
}
}
%endif
; Tests all versions of pshufw, doing a CRC on the result to make sure it is correct.
mov rax, 0
%assign i 0
%rep 256
pshufw mm0, [rel random_data + (i * 8)], i
movq [rel result], mm0
crc32 rax, qword [rel result]
%assign i i+1
%endrep
hlt
align 16
; 4096 bytes of random data.
random_data:
db 0x5b, 0x27, 0x12, 0x29, 0xab, 0x84, 0xa2, 0x21, 0x6d, 0x27, 0xbe, 0x3d, 0x17, 0x05, 0x99, 0xb0
db 0xf3, 0xe2, 0x19, 0xf4, 0x42, 0xbb, 0x69, 0x02, 0x67, 0x3a, 0xab, 0x86, 0x9e, 0xda, 0x9f, 0xd5
db 0xba, 0xd4, 0x2d, 0x9d, 0x20, 0x3d, 0xf8, 0xb2, 0x29, 0xc3, 0xc3, 0x98, 0xa8, 0x30, 0x92, 0xe9
db 0x5a, 0x75, 0x0c, 0xcb, 0x28, 0x28, 0xb4, 0x90, 0x93, 0x16, 0x45, 0x10, 0x3a, 0x5d, 0x96, 0x67
db 0xf9, 0x31, 0xbe, 0x48, 0x78, 0xe8, 0x5a, 0xf2, 0x66, 0x29, 0xd9, 0x80, 0x50, 0x80, 0xcb, 0x07
db 0xfe, 0xda, 0x19, 0x0f, 0x22, 0xea, 0x18, 0x5e, 0x12, 0xea, 0x3d, 0x1a, 0xbc, 0x91, 0x51, 0x15
db 0xaa, 0x66, 0x92, 0x61, 0xb4, 0xd4, 0xce, 0x14, 0x9c, 0x86, 0x27, 0x3d, 0xd0, 0xc6, 0x51, 0x1c
db 0xa0, 0xd4, 0x0b, 0x2d, 0x25, 0x30, 0x3b, 0x46, 0x23, 0x07, 0xb5, 0x05, 0x4a, 0xaa, 0x5a, 0x0a
db 0x7b, 0x29, 0xe4, 0x52, 0x6f, 0x6f, 0xc8, 0x62, 0xb8, 0x94, 0x6a, 0x30, 0x66, 0xf1, 0x21, 0xec
db 0xd1, 0xf2, 0x68, 0xda, 0xb7, 0x7f, 0x5a, 0x26, 0x38, 0x46, 0x48, 0xda, 0x5d, 0x64, 0x8d, 0x3d
db 0x2f, 0xf6, 0xc3, 0x63, 0xb8, 0x09, 0x3a, 0xd0, 0x5b, 0xeb, 0x67, 0xd0, 0xaa, 0x63, 0x71, 0x19
db 0x7e, 0x4e, 0x33, 0xe2, 0x15, 0xba, 0x87, 0xa7, 0x7b, 0x25, 0xe4, 0xbb, 0xb5, 0x26, 0x9a, 0xf1
db 0xdd, 0x5a, 0x63, 0xd7, 0x16, 0xc0, 0xc3, 0xc8, 0x1b, 0xad, 0x00, 0x52, 0x63, 0x55, 0xc7, 0xe0
db 0xd9, 0xe9, 0xf4, 0x4c, 0x53, 0xfb, 0x73, 0x57, 0xdc, 0xad, 0x0c, 0xca, 0x73, 0x44, 0x6b, 0xf3
db 0xb7, 0x83, 0x3b, 0xfe, 0xf0, 0x15, 0xbf, 0xe5, 0x15, 0xca, 0xdf, 0x35, 0xeb, 0xe7, 0xe3, 0xa2
db 0xbd, 0x20, 0xad, 0xff, 0x1b, 0x67, 0x0a, 0x9f, 0x60, 0x60, 0xff, 0xa7, 0xc9, 0x19, 0xde, 0xb3
db 0x67, 0xf1, 0x4b, 0x77, 0x7f, 0x0b, 0xb1, 0x29, 0xee, 0xcb, 0xd6, 0x5d, 0x0d, 0xb9, 0x54, 0x49
db 0x10, 0xe3, 0xbd, 0x8a, 0xa0, 0x69, 0xa3, 0x07, 0xbe, 0x8e, 0xea, 0xc6, 0x75, 0x27, 0x66, 0xae
db 0x3c, 0xde, 0xc6, 0x13, 0x1b, 0x50, 0x37, 0x56, 0x7c, 0x01, 0xab, 0x8b, 0x46, 0xdc, 0x80, 0xed
db 0xdf, 0x12, 0x6f, 0x64, 0xdf, 0xe6, 0xf9, 0xbf, 0x15, 0x95, 0xd9, 0x80, 0x19, 0x8c, 0x96, 0x33
db 0x89, 0xbe, 0x25, 0x33, 0x34, 0x82, 0x92, 0x96, 0x05, 0x52, 0xa2, 0xcf, 0x5b, 0x3d, 0xfc, 0xd8
db 0x43, 0x89, 0x2e, 0x16, 0x6d, 0xbd, 0x84, 0x97, 0x77, 0xb5, 0xd6, 0x2b, 0x6b, 0xb1, 0xc6, 0x38
db 0x0a, 0xfe, 0xe1, 0xc9, 0x31, 0x32, 0x7f, 0xd5, 0xc1, 0x03, 0x4a, 0xb2, 0x86, 0x4d, 0x8d, 0x77
db 0xd6, 0x62, 0x52, 0x75, 0xed, 0x27, 0x21, 0xe8, 0x69, 0x6f, 0x6a, 0x5b, 0x59, 0x4d, 0xd2, 0x6c
db 0x2a, 0x97, 0x09, 0x03, 0xc5, 0x29, 0x0d, 0xe1, 0x31, 0x2e, 0x62, 0x21, 0x0e, 0xc2, 0x00, 0x7c
db 0xa2, 0x4c, 0x19, 0x63, 0x24, 0xfc, 0x9b, 0x38, 0x11, 0xbf, 0x20, 0x53, 0x53, 0xac, 0x3f, 0xdb
db 0xfd, 0x2b, 0x39, 0x3c, 0x39, 0x6b, 0xb4, 0x52, 0x1f, 0xf8, 0x8f, 0x3b, 0x47, 0x2b, 0x86, 0xcf
db 0xd2, 0x38, 0xe9, 0x08, 0x73, 0x09, 0x32, 0x5f, 0x6c, 0x3a, 0xdb, 0xfc, 0x1d, 0x91, 0xa4, 0x26
db 0xa3, 0x0c, 0xbc, 0x94, 0xf5, 0xbd, 0x29, 0xcf, 0x72, 0x3d, 0xee, 0x48, 0x06, 0x77, 0x63, 0x70
db 0x47, 0xc9, 0x87, 0x21, 0xb1, 0x9a, 0xdd, 0x5f, 0x71, 0x08, 0xe3, 0x3b, 0xf6, 0x07, 0x9f, 0x2f
db 0x20, 0xa3, 0x02, 0xc8, 0x4d, 0xc8, 0x18, 0xfa, 0x69, 0x32, 0x60, 0x97, 0x2d, 0x2f, 0x26, 0x84
db 0x3d, 0x7a, 0xf6, 0x2f, 0xb1, 0xc9, 0xd2, 0xcd, 0x6e, 0x24, 0x18, 0xa8, 0x0d, 0xb0, 0xe2, 0x41
db 0x1e, 0xdf, 0xc7, 0xee, 0xcd, 0x21, 0x5b, 0xc3, 0x26, 0x26, 0xb3, 0xb4, 0x33, 0x58, 0x79, 0xb5
db 0xc3, 0x24, 0x7c, 0xe3, 0xd7, 0x78, 0x33, 0x22, 0xd5, 0x20, 0x21, 0x86, 0xcf, 0xca, 0x44, 0xba
db 0xd8, 0x05, 0x84, 0x37, 0x69, 0x48, 0xb0, 0xe0, 0x7a, 0xe6, 0x74, 0x53, 0x1e, 0xd0, 0x0c, 0x3c
db 0x33, 0x83, 0x15, 0x43, 0x16, 0x0e, 0x93, 0x39, 0x55, 0x2e, 0x55, 0x1c, 0x09, 0xbd, 0x7a, 0xc3
db 0x80, 0x77, 0x4e, 0xd9, 0xf3, 0xa5, 0xee, 0x94, 0xbf, 0x8e, 0xd0, 0xec, 0x39, 0x33, 0x31, 0x8d
db 0x74, 0x94, 0xd2, 0x24, 0x22, 0x4a, 0xde, 0x51, 0x99, 0xc5, 0x68, 0xf2, 0x2e, 0xd3, 0x8d, 0xc5
db 0x32, 0x31, 0x26, 0xe7, 0x87, 0x47, 0x5f, 0xbc, 0x32, 0x80, 0x43, 0x83, 0x34, 0x36, 0xa1, 0x72
db 0x6b, 0x38, 0x10, 0x93, 0xa7, 0xa3, 0x92, 0xb7, 0x3c, 0x61, 0x1c, 0x4e, 0x0b, 0x86, 0x43, 0xa9
db 0x64, 0xf1, 0xf8, 0xd7, 0xd3, 0xf4, 0xd0, 0xe2, 0x17, 0xd4, 0xbb, 0xe9, 0x2c, 0xc8, 0x76, 0xc5
db 0x87, 0x7f, 0x81, 0x55, 0xbe, 0x87, 0x0e, 0x6b, 0xf6, 0x4f, 0x44, 0x37, 0x92, 0x32, 0x7f, 0x30
db 0xa6, 0x66, 0x09, 0x01, 0x7a, 0x6e, 0xb3, 0x3b, 0x7d, 0x8f, 0x32, 0x0e, 0x3c, 0xdc, 0xba, 0x2e
db 0xf8, 0xec, 0xde, 0xd9, 0xb1, 0xf0, 0x3e, 0xbd, 0x20, 0x4d, 0x01, 0x5a, 0xf4, 0xda, 0x99, 0x23
db 0x81, 0x01, 0x5f, 0x50, 0xce, 0xa8, 0xb9, 0xb1, 0x59, 0xe5, 0xde, 0x47, 0x5b, 0xba, 0x94, 0xd3
db 0x21, 0x7c, 0x49, 0xeb, 0xb5, 0x14, 0xe5, 0x56, 0x93, 0x06, 0x3b, 0xd2, 0x3a, 0x11, 0xca, 0x7a
db 0x14, 0x48, 0x54, 0xc7, 0x9f, 0x03, 0x40, 0x2c, 0x0b, 0x42, 0x8e, 0xac, 0xac, 0x08, 0x04, 0x8e
db 0xb3, 0x15, 0xe5, 0x06, 0xa6, 0x5b, 0xf0, 0x57, 0x08, 0xfa, 0x0f, 0x00, 0x7e, 0x4a, 0x16, 0xa8
db 0xb0, 0x4d, 0x07, 0x1b, 0xbc, 0x3d, 0xd0, 0x86, 0x15, 0xcd, 0x7c, 0xb2, 0xcc, 0x37, 0x6d, 0x15
db 0x8b, 0xd1, 0xe6, 0x3e, 0xfb, 0x6e, 0xe4, 0xea, 0xd9, 0x1f, 0x69, 0x2a, 0xbc, 0xda, 0xd9, 0x78
db 0xee, 0xcb, 0xb6, 0xff, 0x53, 0xfd, 0xd2, 0xb9, 0x18, 0x1f, 0xdf, 0x0e, 0x69, 0xfe, 0x36, 0xb0
db 0x77, 0x28, 0x66, 0xe2, 0xf0, 0x80, 0x4c, 0x11, 0x11, 0xba, 0xb7, 0xfd, 0x67, 0x4f, 0x05, 0xed
db 0x0c, 0xcc, 0x3e, 0x4d, 0xd9, 0xbc, 0x52, 0xe3, 0xec, 0xd9, 0x74, 0x29, 0x30, 0xf2, 0x66, 0xd6
db 0xfb, 0xc3, 0x5c, 0xc1, 0xd8, 0xef, 0x86, 0x08, 0x22, 0xb1, 0x6d, 0xfd, 0xee, 0xc7, 0x12, 0x25
db 0xda, 0xee, 0xd6, 0x28, 0x3b, 0x1d, 0xa7, 0x29, 0xdf, 0x45, 0x3a, 0xa4, 0x36, 0xe0, 0xa4, 0xda
db 0xb1, 0x2c, 0x8a, 0xa5, 0x5c, 0x8c, 0x70, 0xd8, 0xcd, 0x0f, 0xb5, 0x63, 0xd3, 0xaf, 0x59, 0x2b
db 0x7d, 0x86, 0x4a, 0xc4, 0xcc, 0x72, 0x9e, 0x89, 0xf4, 0x38, 0x89, 0x81, 0x64, 0x6f, 0xa5, 0xac
db 0x13, 0x59, 0xc4, 0x0f, 0xfb, 0xcc, 0x4c, 0x1d, 0x67, 0x5a, 0xbf, 0x19, 0xfc, 0x06, 0x71, 0xbd
db 0x7f, 0xb6, 0xb1, 0x95, 0xd3, 0x7b, 0x4c, 0x40, 0x91, 0xa9, 0x26, 0xdd, 0x28, 0x69, 0x90, 0xf6
db 0x5d, 0x16, 0x9f, 0xa9, 0x75, 0x5e, 0xad, 0x8f, 0xc8, 0x0b, 0x57, 0x48, 0xf2, 0x74, 0x77, 0x22
db 0x5d, 0xed, 0xc2, 0x79, 0x27, 0x46, 0x0c, 0x9e, 0x6f, 0x9a, 0x9a, 0xdc, 0xe0, 0x3d, 0x24, 0xc9
db 0xce, 0xf3, 0x34, 0x66, 0x45, 0x07, 0x0b, 0x83, 0x8c, 0xb7, 0xd9, 0x1e, 0xac, 0xc6, 0xf7, 0xef
db 0xe7, 0xd1, 0xbc, 0xa3, 0x21, 0x85, 0x3d, 0x25, 0x90, 0x24, 0x48, 0xb1, 0x00, 0xb0, 0xd2, 0xa6
db 0xd8, 0x4e, 0x46, 0x7c, 0xc4, 0x79, 0x40, 0x95, 0x81, 0xb4, 0xb9, 0xa8, 0x70, 0xf0, 0x12, 0xd6
db 0xdc, 0xb2, 0x7c, 0x0f, 0x47, 0xad, 0x7d, 0x46, 0x78, 0x18, 0x6e, 0xdd, 0x5f, 0xe5, 0xd7, 0x63
db 0x11, 0xf0, 0x5b, 0xa0, 0x48, 0x15, 0xe2, 0x55, 0xc6, 0x7f, 0xf4, 0x2e, 0x0e, 0x49, 0x39, 0x65
db 0x3e, 0x69, 0xc1, 0x27, 0x39, 0xb3, 0x10, 0x1b, 0xf2, 0x35, 0x88, 0x0c, 0x1b, 0xac, 0x4a, 0x15
db 0x31, 0x81, 0x63, 0xe5, 0x3d, 0x56, 0x6f, 0x34, 0x06, 0x5b, 0x1d, 0xa0, 0xea, 0x0c, 0x92, 0x6a
db 0x22, 0x2b, 0x2d, 0xbb, 0xaf, 0xc5, 0x6d, 0x44, 0x1b, 0xb0, 0x69, 0x06, 0x27, 0x54, 0xa5, 0x7f
db 0x07, 0xd4, 0xdc, 0xe5, 0x5c, 0x78, 0x9e, 0xf7, 0x4a, 0x47, 0x9b, 0x21, 0xf6, 0x87, 0x89, 0xad
db 0xec, 0xe4, 0xd6, 0x83, 0xd3, 0x7b, 0x34, 0x00, 0x0b, 0x75, 0xba, 0x4c, 0x0f, 0x46, 0xd2, 0x0c
db 0x58, 0x1b, 0x0f, 0x19, 0xb5, 0xf5, 0xba, 0x8f, 0xbd, 0x17, 0x51, 0xaf, 0xa6, 0x1a, 0x97, 0x8c
db 0x44, 0x30, 0x7c, 0x73, 0x50, 0xca, 0x05, 0xe8, 0x3e, 0x19, 0x4a, 0x5a, 0x6b, 0x4d, 0x01, 0x05
db 0xea, 0x1b, 0x70, 0xb6, 0xe6, 0x39, 0x5d, 0x99, 0x3b, 0xae, 0xed, 0x7c, 0xa6, 0xc7, 0x29, 0x6f
db 0xeb, 0x0a, 0xba, 0x03, 0xd3, 0xba, 0x62, 0x21, 0xa0, 0xb7, 0xb5, 0xbf, 0x40, 0xb8, 0x4e, 0xc3
db 0x89, 0xa0, 0xa9, 0xe8, 0xc8, 0x2b, 0xfd, 0x23, 0x32, 0x53, 0xe5, 0x35, 0xc1, 0x23, 0x97, 0xc1
db 0x87, 0x10, 0x41, 0x21, 0xb3, 0xf6, 0x53, 0xcf, 0x28, 0x47, 0x9c, 0x69, 0x42, 0xcf, 0x0e, 0x11
db 0x69, 0x7f, 0xc6, 0xdf, 0xc3, 0xbf, 0x04, 0x7f, 0x3a, 0xc6, 0xa1, 0x3d, 0xc6, 0x5b, 0x56, 0x8b
db 0x52, 0x23, 0x41, 0xd7, 0x35, 0x7f, 0x86, 0xd2, 0x59, 0xcf, 0xae, 0x28, 0xa3, 0xa2, 0x23, 0x4b
db 0x78, 0x78, 0x94, 0x3f, 0x2f, 0xf0, 0xb8, 0x94, 0xa2, 0x62, 0xb9, 0x83, 0xc7, 0x5f, 0x64, 0x45
db 0x54, 0xaf, 0x43, 0x93, 0x7f, 0xa1, 0xe8, 0x71, 0x38, 0xc8, 0x21, 0xf4, 0xa6, 0xab, 0x2b, 0xd3
db 0x44, 0xa2, 0x74, 0x94, 0x99, 0x3f, 0x56, 0xbc, 0x0a, 0x12, 0xe7, 0x6e, 0x1b, 0x7f, 0x98, 0xad
db 0x28, 0xa6, 0xc8, 0x87, 0x7a, 0x88, 0xcb, 0xcf, 0x9f, 0x95, 0xa7, 0xf1, 0x66, 0xfe, 0x43, 0x3d
db 0x71, 0x5b, 0x3a, 0xb7, 0xe4, 0xa8, 0x6f, 0x46, 0xa1, 0xaa, 0x66, 0xd2, 0x9e, 0x84, 0xfd, 0x42
db 0x98, 0x17, 0x3e, 0xde, 0xaa, 0x18, 0xc9, 0x9c, 0x53, 0x88, 0x2b, 0x92, 0xce, 0x00, 0x8b, 0xb4
db 0x15, 0x7a, 0x39, 0xb7, 0x57, 0xf9, 0xf2, 0x17, 0x0a, 0x8c, 0x05, 0x7b, 0x3f, 0x2a, 0xb0, 0xb7
db 0x8a, 0xbb, 0x9a, 0x0d, 0xe4, 0x0d, 0x6a, 0xbd, 0x8a, 0xe9, 0xbd, 0xca, 0xb2, 0x6a, 0xbe, 0x76
db 0x2c, 0xbe, 0x45, 0x3f, 0x22, 0x03, 0xb1, 0xab, 0x2d, 0xe0, 0x70, 0x52, 0xe5, 0x27, 0x8e, 0xbc
db 0xa9, 0x8d, 0x13, 0xf4, 0xe5, 0xd7, 0xeb, 0x4e, 0x30, 0x3f, 0x76, 0x3b, 0x64, 0xad, 0x57, 0x53
db 0x91, 0x89, 0xf4, 0x9a, 0xd1, 0x38, 0x3d, 0x58, 0xdc, 0x83, 0x65, 0x4a, 0x36, 0x30, 0x73, 0x92
db 0x8c, 0x2f, 0x7d, 0x1e, 0x15, 0x3c, 0xca, 0x54, 0x6f, 0x17, 0xbd, 0xba, 0x97, 0x7e, 0x28, 0x11
db 0x8e, 0x96, 0x9f, 0x46, 0x84, 0x69, 0xe3, 0xc2, 0x8e, 0x1e, 0xea, 0x6b, 0x17, 0xa7, 0xf8, 0x17
db 0xc3, 0xd9, 0x9c, 0x53, 0x79, 0x95, 0x32, 0xf6, 0x78, 0xcd, 0x5d, 0x2f, 0x30, 0x06, 0xe8, 0x9f
db 0x5e, 0xb2, 0x4e, 0x56, 0xf5, 0x31, 0xc3, 0x41, 0xae, 0x4b, 0x0a, 0xbd, 0xdc, 0xce, 0xea, 0xfa
db 0x27, 0x09, 0x4e, 0xd1, 0x24, 0x14, 0x33, 0x8b, 0x21, 0x48, 0x99, 0x92, 0x07, 0xa4, 0x1a, 0x87
db 0x34, 0x15, 0xa6, 0x12, 0x92, 0x3f, 0xf0, 0x3e, 0x18, 0x3c, 0x65, 0x3a, 0x8b, 0x17, 0x9b, 0xf2
db 0xd9, 0x93, 0xa0, 0x19, 0x2b, 0x73, 0x59, 0x29, 0x6f, 0xb7, 0x75, 0x4b, 0x42, 0x24, 0x43, 0xa4
db 0x20, 0xd8, 0x59, 0x8d, 0x9f, 0xd6, 0x64, 0xa1, 0xeb, 0xe3, 0x65, 0x82, 0x69, 0x74, 0x1a, 0x2b
db 0x8d, 0x9a, 0x59, 0x5d, 0x47, 0x75, 0x63, 0xcd, 0xe4, 0x14, 0x48, 0x5f, 0x67, 0x00, 0x12, 0x3c
db 0x58, 0x27, 0x5e, 0x83, 0xde, 0xd8, 0x97, 0xd9, 0x09, 0xd9, 0x06, 0x64, 0x96, 0x67, 0xb4, 0x4f
db 0xb9, 0x58, 0x87, 0xc9, 0xb1, 0xdd, 0x64, 0x8f, 0x4e, 0x8f, 0xa9, 0xfa, 0x40, 0xe6, 0x8f, 0xaa
db 0x22, 0x26, 0x16, 0x15, 0x6a, 0xa3, 0x88, 0xae, 0xa2, 0xbc, 0xa3, 0xa3, 0x56, 0xa1, 0x74, 0x6c
db 0xa2, 0xd0, 0x47, 0x4b, 0x98, 0x0a, 0xea, 0xdd, 0xe8, 0x9c, 0xe1, 0x37, 0x44, 0x1a, 0xc0, 0xc7
db 0x83, 0x07, 0x42, 0xca, 0x98, 0x36, 0xd7, 0x43, 0x18, 0x51, 0x32, 0xf6, 0x99, 0x61, 0x73, 0x79
db 0x51, 0xc4, 0xe9, 0x5b, 0x9e, 0xa8, 0xb4, 0x28, 0x49, 0xbb, 0x44, 0x90, 0xe2, 0xf7, 0x7e, 0x61
db 0x27, 0xbb, 0x85, 0x58, 0xd0, 0xdc, 0x94, 0x53, 0x02, 0x50, 0xfe, 0xc7, 0x37, 0xa2, 0x20, 0x1b
db 0x57, 0x00, 0x9b, 0x7c, 0xa4, 0x6c, 0xa6, 0xb1, 0xae, 0xd0, 0x03, 0x67, 0x2b, 0x82, 0xd9, 0x99
db 0x76, 0xd0, 0xc7, 0x7d, 0x2d, 0xbd, 0x39, 0x28, 0xcf, 0xe1, 0x13, 0xce, 0x1c, 0xe6, 0x4c, 0xa7
db 0x7a, 0x8c, 0x4f, 0xa6, 0x30, 0x77, 0x6b, 0x78, 0x39, 0x6e, 0x10, 0xd1, 0x9c, 0x9a, 0xda, 0x2d
db 0xc9, 0xef, 0xd7, 0xb1, 0xb8, 0xdf, 0x21, 0xce, 0x96, 0x53, 0xaa, 0xa6, 0x76, 0x52, 0x56, 0x0e
db 0xe6, 0x7f, 0xed, 0x88, 0x15, 0x2a, 0xc1, 0xfe, 0xb3, 0x35, 0x54, 0x09, 0x9b, 0x5d, 0x21, 0x62
db 0xc8, 0x6f, 0x2c, 0x6e, 0x56, 0xc8, 0xd9, 0x40, 0x67, 0xeb, 0x26, 0xf5, 0xcb, 0x18, 0xb1, 0x89
db 0xfe, 0x58, 0x1a, 0xff, 0x41, 0xb5, 0xd6, 0xe5, 0xb3, 0x82, 0x29, 0x82, 0xee, 0xbb, 0xb2, 0x5a
db 0x71, 0xf2, 0xca, 0xf1, 0x2f, 0xa7, 0x4d, 0xb1, 0x5c, 0xbc, 0xc3, 0x1a, 0xb4, 0x20, 0x6a, 0x7e
db 0xb9, 0x5e, 0xcb, 0x9b, 0xf3, 0x1c, 0x2b, 0x16, 0xab, 0x15, 0x8d, 0xb5, 0x81, 0xf3, 0xbb, 0xc1
db 0x8e, 0x2c, 0xd6, 0xd1, 0xa8, 0x23, 0x3c, 0x98, 0x3f, 0x4e, 0xff, 0x97, 0x77, 0xd1, 0xbd, 0xda
db 0xff, 0x9c, 0x55, 0x01, 0x1c, 0x4b, 0x4b, 0x1a, 0xa9, 0x3d, 0xe9, 0xbd, 0x3c, 0x5b, 0xfd, 0x65
db 0x34, 0x9c, 0x78, 0x8c, 0x83, 0x46, 0x72, 0xed, 0x66, 0xee, 0x00, 0xac, 0xca, 0x09, 0xaa, 0x3a
db 0x2c, 0xc1, 0x7e, 0xde, 0x44, 0xbd, 0xe3, 0x5a, 0x11, 0x41, 0xc7, 0xc8, 0x65, 0x7a, 0xc7, 0xbb
db 0x44, 0xad, 0x97, 0x17, 0xe8, 0x9f, 0x29, 0x2b, 0x78, 0x6d, 0x96, 0xb6, 0x9c, 0x3a, 0x6a, 0xc2
db 0xab, 0x9a, 0x16, 0x6f, 0x05, 0x78, 0x0d, 0x83, 0xa5, 0x46, 0x8c, 0xd7, 0x57, 0x1e, 0x80, 0x2f
db 0x7e, 0x81, 0x68, 0xa4, 0xc4, 0x3d, 0x6c, 0xae, 0x6b, 0x98, 0xb9, 0xe4, 0xb4, 0xfb, 0xf4, 0x19
db 0xf9, 0xcd, 0xbb, 0xd0, 0xbc, 0x22, 0xdd, 0x2c, 0xbe, 0x11, 0x01, 0xc2, 0x53, 0xdd, 0xa3, 0x3a
db 0xbf, 0x5f, 0x2a, 0x94, 0x8b, 0x58, 0x6e, 0xe3, 0x4e, 0x1b, 0x0d, 0x30, 0x1b, 0x1c, 0x6c, 0x24
db 0x0e, 0xd9, 0x1c, 0xe1, 0x4d, 0x42, 0x48, 0xa0, 0x07, 0xb1, 0xe8, 0x10, 0xa1, 0x51, 0x6a, 0x82
db 0x2e, 0x99, 0xb3, 0xbf, 0xe3, 0xff, 0x3c, 0x77, 0xf4, 0x0c, 0x1f, 0x22, 0x53, 0xd0, 0x99, 0x60
db 0x5d, 0x65, 0x80, 0xb9, 0xa3, 0xb7, 0x25, 0x6d, 0xa6, 0x4f, 0xb5, 0x72, 0xaa, 0x4d, 0x0d, 0x49
db 0x4c, 0x34, 0xc5, 0xf4, 0x1b, 0x5c, 0x3f, 0x6c, 0xbb, 0x86, 0xba, 0xc5, 0x32, 0xee, 0x23, 0x95
db 0xe5, 0x42, 0x66, 0x92, 0x89, 0x5e, 0xf4, 0xd4, 0x2d, 0x04, 0xf2, 0xbc, 0xd7, 0xc8, 0xc9, 0xd7
db 0xe3, 0xdb, 0x4e, 0x4b, 0xda, 0x37, 0x1f, 0xfa, 0x9c, 0xaf, 0x4b, 0x1e, 0xab, 0x64, 0x2a, 0x59
db 0x24, 0x0f, 0xb4, 0xaf, 0xd6, 0x32, 0x30, 0xcd, 0x7c, 0xf3, 0x0f, 0xa9, 0xac, 0x3f, 0x55, 0xa2
db 0x92, 0x21, 0x58, 0x4e, 0x99, 0xbc, 0x9f, 0xfd, 0x16, 0x7c, 0x4e, 0x5b, 0xb4, 0xc7, 0x5f, 0x8d
db 0x0e, 0x26, 0x72, 0x17, 0x02, 0x7d, 0x12, 0xa0, 0xc5, 0xc1, 0x66, 0xd3, 0x19, 0x49, 0x42, 0xfb
db 0x18, 0xd7, 0x18, 0x79, 0xd3, 0x32, 0xfc, 0x4a, 0xab, 0x82, 0x72, 0x0a, 0x90, 0xb7, 0xbc, 0x00
db 0x16, 0x99, 0xd3, 0x9a, 0x76, 0xc6, 0x44, 0x92, 0x9b, 0x2b, 0x6a, 0x35, 0xca, 0x4e, 0x2e, 0x9c
db 0x7f, 0xcb, 0xd3, 0x65, 0x1c, 0xa6, 0x95, 0x2c, 0x3d, 0xe4, 0xd3, 0xe6, 0xe7, 0xe0, 0xde, 0x1e
db 0x54, 0xb3, 0x09, 0x3e, 0x34, 0x35, 0x68, 0x53, 0x01, 0x02, 0xf1, 0x4c, 0x89, 0x19, 0xe3, 0xc6
db 0x4a, 0x51, 0x49, 0xf5, 0x5f, 0x3e, 0xcd, 0xae, 0x6e, 0xeb, 0x90, 0x1a, 0x53, 0x93, 0x0b, 0xe8
db 0xc2, 0x6e, 0xee, 0xf3, 0x38, 0x5d, 0xb8, 0xaf, 0x58, 0x4b, 0xe0, 0xfd, 0x07, 0xcf, 0x15, 0x89
db 0x2b, 0x01, 0x35, 0xbb, 0xa0, 0x2f, 0x7e, 0xd3, 0x34, 0x7b, 0x1f, 0x81, 0x12, 0x7f, 0xb0, 0xff
db 0xe7, 0xa0, 0xf2, 0xc4, 0x86, 0x98, 0x45, 0xe2, 0xa1, 0x1e, 0x4c, 0xc0, 0x23, 0x05, 0x49, 0x0b
db 0x0d, 0xc3, 0x1e, 0x30, 0x20, 0xc6, 0x34, 0xb7, 0xe1, 0x09, 0x84, 0xd5, 0x2a, 0x40, 0x75, 0x9b
db 0x46, 0xbb, 0xa5, 0xfe, 0xbd, 0x7d, 0x39, 0xe4, 0x7b, 0x38, 0xdc, 0x9c, 0xaf, 0xc8, 0x12, 0xf4
db 0x78, 0xb8, 0x51, 0x4a, 0x21, 0xfe, 0xf9, 0x77, 0xf6, 0xb5, 0xad, 0x69, 0xc9, 0x4d, 0xbf, 0x67
db 0xfc, 0x5d, 0x80, 0x7c, 0x76, 0x2c, 0xe5, 0xf2, 0xd7, 0x7f, 0xce, 0xb5, 0x1c, 0x09, 0xa5, 0xc3
db 0x98, 0x18, 0x2d, 0x18, 0xfb, 0x61, 0x13, 0xea, 0xbc, 0x87, 0x3a, 0x3f, 0xb4, 0xaf, 0x3c, 0x3b
db 0x3b, 0xb6, 0xd2, 0xc7, 0x5c, 0x2c, 0xe1, 0x11, 0xb3, 0x9d, 0xf1, 0x52, 0xba, 0xb5, 0xf0, 0x69
db 0xcd, 0xd2, 0x93, 0x9e, 0x80, 0x45, 0x78, 0x17, 0x6d, 0x52, 0x51, 0xad, 0xed, 0x6d, 0x9e, 0x15
db 0xca, 0xb1, 0xfe, 0x22, 0x7b, 0x87, 0xb8, 0x40, 0x06, 0x2d, 0xb0, 0xbb, 0x05, 0x7c, 0x52, 0xd2
db 0xcd, 0xc8, 0x9c, 0xea, 0xd3, 0x4c, 0xb5, 0x06, 0xb4, 0x70, 0xad, 0x09, 0xa5, 0xb8, 0x66, 0xba
db 0x31, 0x0d, 0xe0, 0xe2, 0xcf, 0x62, 0x9f, 0x6d, 0x6d, 0x1a, 0x47, 0x21, 0xd5, 0x33, 0x6b, 0xd7
db 0x75, 0xff, 0x98, 0x6c, 0xb2, 0x78, 0x6d, 0x45, 0x50, 0xeb, 0xfb, 0xea, 0xb7, 0x2a, 0x27, 0x02
db 0xc4, 0x03, 0xde, 0x56, 0x23, 0x26, 0x10, 0x21, 0x57, 0x9c, 0x3b, 0x4c, 0x79, 0x2c, 0x3e, 0xfe
db 0xc8, 0x16, 0xe4, 0xd6, 0x60, 0xb8, 0x46, 0xe3, 0x4b, 0x7e, 0x3d, 0xb3, 0x83, 0x19, 0x54, 0x65
db 0x51, 0x7a, 0x81, 0xdd, 0x07, 0x33, 0x92, 0x08, 0x64, 0x0b, 0xc2, 0x06, 0x5c, 0x07, 0x81, 0x40
db 0x1b, 0xb4, 0x5a, 0x47, 0x2b, 0xdc, 0x96, 0x98, 0x4c, 0x65, 0xad, 0x8e, 0x8e, 0x77, 0xbe, 0x99
db 0x60, 0x4c, 0xb5, 0x6b, 0xed, 0xb7, 0x52, 0x5d, 0x99, 0x2e, 0x93, 0x40, 0xfe, 0x45, 0x83, 0x28
db 0x9b, 0x8b, 0x7f, 0x77, 0x2b, 0xdc, 0x61, 0xbe, 0x62, 0x28, 0xe8, 0x23, 0x3f, 0xdb, 0x1d, 0x6d
db 0x3b, 0xe8, 0x90, 0x05, 0x12, 0xf2, 0xb4, 0xf0, 0x1b, 0xbb, 0x2f, 0x4b, 0x9e, 0x9f, 0x0e, 0x4e
db 0x9e, 0x6a, 0x38, 0x7e, 0x97, 0x13, 0x90, 0x57, 0xb9, 0x49, 0x52, 0xb7, 0x4f, 0xd3, 0xc1, 0x39
db 0x95, 0x20, 0xd4, 0x83, 0x48, 0x0e, 0x7a, 0x9d, 0x89, 0x9d, 0xf4, 0xec, 0xe7, 0xcc, 0xde, 0x0a
db 0xac, 0xc5, 0xb0, 0x4d, 0xc5, 0x25, 0x74, 0x62, 0x66, 0x51, 0x4f, 0xeb, 0x4e, 0x9d, 0x3d, 0x04
db 0x27, 0xec, 0xfe, 0x8d, 0x03, 0x20, 0x38, 0x30, 0x5d, 0xf3, 0xf0, 0x97, 0xbb, 0xa9, 0xd1, 0xea
db 0x73, 0x73, 0x40, 0x2c, 0x0b, 0xa7, 0xc9, 0x8d, 0xac, 0x75, 0xc4, 0x46, 0x7c, 0xc2, 0x9a, 0x26
db 0x07, 0xae, 0x02, 0x27, 0x42, 0xa8, 0x90, 0xb6, 0x9b, 0x98, 0xec, 0x2e, 0xf6, 0xf6, 0x17, 0xda
db 0x9f, 0xfb, 0x54, 0xea, 0xae, 0x96, 0xfe, 0xd6, 0x35, 0x4f, 0x07, 0x9f, 0xf4, 0x57, 0x36, 0xfe
db 0xb1, 0x43, 0xee, 0xe3, 0x21, 0x00, 0x43, 0x12, 0xf2, 0xff, 0xa5, 0x37, 0x65, 0x01, 0xf0, 0xb4
db 0xe8, 0x68, 0xa3, 0xff, 0x31, 0x5f, 0x3f, 0x56, 0xa5, 0xd2, 0xcc, 0xab, 0xa4, 0x90, 0xf9, 0x98
db 0x0b, 0xdc, 0x0d, 0x20, 0x3c, 0x33, 0xda, 0xf1, 0x54, 0xd5, 0x6d, 0xc4, 0xa9, 0xc4, 0x54, 0x29
db 0x56, 0x69, 0x96, 0x98, 0x74, 0x13, 0x72, 0x1f, 0x95, 0xe9, 0xe2, 0xab, 0x60, 0x74, 0x91, 0x96
db 0xdf, 0xa4, 0xd6, 0x62, 0x3c, 0x35, 0x7e, 0xc4, 0x21, 0x16, 0xa3, 0x32, 0xac, 0x20, 0x52, 0xd4
db 0xbb, 0xc2, 0xa5, 0x97, 0x86, 0x4a, 0x55, 0xf4, 0x09, 0xf2, 0x0e, 0xd6, 0x1a, 0xfa, 0x00, 0x67
db 0x45, 0x57, 0xb3, 0xaa, 0xe5, 0x7c, 0x17, 0x8d, 0xde, 0x75, 0xd7, 0x49, 0x6e, 0xb0, 0xb2, 0xa0
db 0x58, 0xd8, 0x01, 0xf0, 0x22, 0x9c, 0xe4, 0xeb, 0x71, 0x5f, 0x4d, 0x38, 0xf2, 0x7e, 0xee, 0xba
db 0xf9, 0x39, 0xff, 0x42, 0x91, 0x00, 0x63, 0x5c, 0x86, 0x02, 0x81, 0x51, 0x10, 0xfb, 0xcf, 0x2a
db 0xcf, 0x16, 0xd9, 0x8f, 0x3a, 0xbb, 0x29, 0xcb, 0xe2, 0xc9, 0xd9, 0xe2, 0xd9, 0x05, 0x1b, 0x46
db 0x08, 0x2c, 0x6d, 0x5b, 0x1a, 0x7d, 0x5b, 0xca, 0x5b, 0xae, 0x18, 0x48, 0x15, 0x3b, 0x85, 0xd1
db 0x29, 0xcf, 0xaf, 0xa5, 0x68, 0xe9, 0x8d, 0x9e, 0x0b, 0xe1, 0x55, 0x54, 0x68, 0x28, 0x9b, 0x4c
db 0x94, 0x30, 0x3a, 0xc0, 0xaa, 0xf8, 0xeb, 0x7b, 0x58, 0x53, 0x5f, 0x25, 0x2e, 0xbf, 0x72, 0x26
db 0xd8, 0x9c, 0xa9, 0xfe, 0x30, 0xe0, 0x68, 0x25, 0xba, 0x71, 0x1a, 0x82, 0xbb, 0xee, 0x03, 0xc9
db 0x4b, 0x0a, 0x22, 0xda, 0x93, 0xa0, 0x72, 0x49, 0x72, 0x3a, 0x8f, 0xbe, 0x39, 0x04, 0x7c, 0x06
db 0xa1, 0x50, 0xa1, 0x94, 0xb4, 0x66, 0x91, 0xee, 0x76, 0xa4, 0xbe, 0x21, 0x33, 0xbe, 0xa9, 0x68
db 0xe6, 0x03, 0xdd, 0x25, 0x3b, 0x78, 0xe3, 0x5a, 0x0c, 0xcf, 0x2b, 0xa2, 0x03, 0x63, 0x8d, 0xd7
db 0xc4, 0xf0, 0x6e, 0xea, 0xe1, 0x76, 0x93, 0x38, 0x7b, 0x85, 0xef, 0xff, 0xce, 0xb0, 0xe1, 0xe3
db 0x86, 0x3d, 0xb6, 0xae, 0xee, 0xf7, 0x92, 0x8a, 0x1b, 0x29, 0x00, 0x9b, 0x85, 0xaf, 0xa2, 0x5e
db 0x90, 0xd9, 0xdc, 0xca, 0xde, 0xde, 0xab, 0xfe, 0x05, 0x61, 0x3c, 0xb6, 0x2f, 0x40, 0x59, 0x1f
db 0x73, 0x80, 0x52, 0xf6, 0x6f, 0x28, 0x30, 0x4b, 0xf2, 0x88, 0x9e, 0x63, 0x84, 0x1b, 0xd2, 0xf4
db 0x67, 0x3b, 0xaf, 0x48, 0x27, 0xfd, 0x7e, 0x30, 0x6e, 0xb8, 0x81, 0xbf, 0xe5, 0x4c, 0x19, 0x16
db 0x24, 0xd0, 0x8e, 0x3a, 0xc9, 0xcd, 0xc8, 0x6f, 0x2e, 0x99, 0xda, 0xb8, 0x7c, 0xd9, 0xbb, 0x2c
db 0xe3, 0xdf, 0xd0, 0x96, 0xe2, 0xcc, 0x99, 0x5b, 0x1d, 0xff, 0x81, 0x74, 0x84, 0x0b, 0x9d, 0x09
db 0x3e, 0x1b, 0x0c, 0x42, 0x3d, 0x96, 0x15, 0x44, 0xed, 0x97, 0x9a, 0x99, 0x68, 0x02, 0x2c, 0x79
db 0x8f, 0xcc, 0xff, 0x83, 0x5e, 0x6e, 0x97, 0x00, 0x50, 0x83, 0xc2, 0x29, 0x2b, 0x27, 0xe6, 0x4f
db 0x18, 0xb0, 0x45, 0xa9, 0xf8, 0x30, 0x35, 0x7f, 0x20, 0xdd, 0xd7, 0x07, 0x32, 0x55, 0x95, 0x4a
db 0xf3, 0xf5, 0x35, 0x5b, 0xac, 0xef, 0xfa, 0xbb, 0x54, 0xba, 0x4d, 0x79, 0x66, 0xce, 0x38, 0x5e
db 0x23, 0xd7, 0x1b, 0x03, 0x37, 0x74, 0xa7, 0xe0, 0xb1, 0x2c, 0xe5, 0xa4, 0x00, 0x36, 0x9a, 0xe9
db 0x36, 0xd4, 0x3e, 0x35, 0x37, 0xb2, 0xc1, 0x71, 0x90, 0x80, 0x3b, 0xd8, 0x6b, 0x7e, 0x79, 0x0a
db 0x7d, 0xe3, 0x3d, 0xc8, 0xd3, 0xb3, 0x56, 0xb6, 0xef, 0x73, 0x3d, 0x24, 0x07, 0x0e, 0xeb, 0x8e
db 0x9b, 0x25, 0xaf, 0x3b, 0xa3, 0x92, 0xf5, 0x19, 0x16, 0xba, 0x1f, 0x6f, 0x92, 0x4b, 0x3f, 0x3c
db 0xc8, 0xac, 0xdd, 0x70, 0xc6, 0x3b, 0x45, 0x0b, 0xa5, 0xe0, 0x8f, 0xa4, 0xd6, 0x56, 0xd8, 0xb9
db 0xc1, 0x1a, 0x53, 0x76, 0x37, 0x60, 0xc9, 0xf4, 0xc8, 0x0a, 0x17, 0x6d, 0x1d, 0xb8, 0x8e, 0xec
db 0xa8, 0x9c, 0x71, 0x08, 0x1f, 0x45, 0x96, 0xc8, 0xed, 0x1e, 0x47, 0x09, 0xbb, 0xe6, 0xee, 0x36
db 0x8e, 0x87, 0xc6, 0xeb, 0xe5, 0x88, 0xd8, 0xab, 0x98, 0x41, 0x4f, 0x2a, 0x49, 0x15, 0x68, 0xf6
db 0x51, 0xaf, 0xc7, 0x74, 0x7c, 0xaa, 0x26, 0x1a, 0x2f, 0xe6, 0x96, 0x86, 0x7c, 0x00, 0xa4, 0x57
db 0x90, 0x1f, 0x83, 0x02, 0x0c, 0xb2, 0xec, 0x27, 0x7f, 0xbc, 0x78, 0x11, 0x64, 0xbe, 0x34, 0x25
db 0xbd, 0xf8, 0x56, 0x00, 0x5f, 0xdd, 0x85, 0x95, 0x23, 0xad, 0xe9, 0x26, 0x1e, 0xd3, 0xfc, 0x22
db 0xe6, 0x35, 0x07, 0xbc, 0xf6, 0x88, 0x19, 0x61, 0x2e, 0xd5, 0x0d, 0xc0, 0x98, 0x79, 0x59, 0x0a
db 0x33, 0x44, 0xa8, 0x70, 0xd8, 0xda, 0x45, 0x72, 0xdb, 0x83, 0xf7, 0xbe, 0xbb, 0x93, 0xc9, 0xaa
db 0xf5, 0xfb, 0xdc, 0x0a, 0x55, 0x54, 0xd1, 0xae, 0x9e, 0x14, 0x38, 0x24, 0x06, 0x6e, 0x4d, 0x17
db 0xaa, 0xb1, 0xe4, 0x55, 0x9b, 0x7c, 0xc2, 0xe7, 0xb6, 0x82, 0x1b, 0x5d, 0x21, 0x20, 0xfc, 0x34
db 0x51, 0xf7, 0xfd, 0x20, 0x17, 0x4b, 0xd1, 0x9f, 0xc7, 0x2a, 0x57, 0x62, 0x4a, 0x60, 0x3f, 0xfa
db 0x70, 0x75, 0x1a, 0x3e, 0x9d, 0xbd, 0x6c, 0xe3, 0x60, 0xc3, 0xd3, 0xa6, 0x3b, 0x73, 0xa5, 0x4f
db 0x06, 0x79, 0xf4, 0x6e, 0x3a, 0xae, 0xa4, 0x98, 0x86, 0xb9, 0x1b, 0x8b, 0x66, 0xd9, 0x96, 0xdb
db 0xa5, 0x47, 0xd3, 0xa8, 0x05, 0x3c, 0x50, 0x57, 0x8a, 0x8f, 0xe0, 0x7f, 0xaf, 0x75, 0x30, 0x44
db 0x01, 0xce, 0x17, 0xb8, 0x89, 0xd4, 0x12, 0xaa, 0xe5, 0x2e, 0xe2, 0x75, 0x70, 0x06, 0x02, 0x5c
db 0xbd, 0x85, 0xaa, 0x75, 0x02, 0x98, 0xe0, 0x0f, 0xe9, 0x94, 0x43, 0x84, 0x8c, 0xca, 0xc1, 0x53
db 0x2f, 0x5c, 0x9a, 0x04, 0x9c, 0x2c, 0x50, 0xc7, 0x6d, 0x13, 0x70, 0x8f, 0x7d, 0xa5, 0x09, 0xc0
db 0x2b, 0x75, 0x55, 0x57, 0xc0, 0x51, 0xad, 0x86, 0x18, 0xc5, 0x9a, 0x9f, 0x1d, 0x99, 0x3e, 0xbd
db 0x38, 0x24, 0x33, 0xd6, 0x04, 0x98, 0xde, 0x19, 0xcc, 0xb3, 0x72, 0x53, 0x6b, 0xbb, 0x38, 0x03
db 0xdc, 0x86, 0xe3, 0x1b, 0x12, 0x04, 0x86, 0x92, 0x3d, 0x3f, 0xf4, 0x4d, 0x73, 0x8a, 0xe7, 0x67
db 0x68, 0xae, 0x63, 0x13, 0x7b, 0x48, 0x90, 0xce, 0x35, 0xfb, 0xf3, 0x46, 0x17, 0xb3, 0xcd, 0x2f
db 0xeb, 0xb5, 0x7a, 0x11, 0xa9, 0xe1, 0xa6, 0xab, 0x0c, 0x9e, 0x9f, 0xd1, 0x08, 0xae, 0xc1, 0x68
db 0xd2, 0xfc, 0x41, 0x36, 0xa8, 0xf4, 0x97, 0xbf, 0x86, 0x61, 0x90, 0x51, 0x02, 0x2e, 0x9a, 0x64
db 0x4e, 0xfb, 0xd1, 0xe5, 0x73, 0x24, 0x07, 0xb5, 0x70, 0xa1, 0xa2, 0xb7, 0xcb, 0x0c, 0xbc, 0x1a
db 0x4a, 0x55, 0x9e, 0x3f, 0x3b, 0xdb, 0x33, 0x4c, 0x01, 0x63, 0x1f, 0xbe, 0xae, 0x05, 0x3e, 0x45
db 0x9e, 0xcf, 0x2e, 0x5f, 0x3b, 0x83, 0x8a, 0xc7, 0xd7, 0x39, 0x3b, 0xfc, 0x54, 0xf0, 0x10, 0x42
db 0x9d, 0x5e, 0x12, 0xc2, 0xb8, 0x8c, 0x4e, 0x26, 0xd7, 0xa0, 0xa1, 0x7a, 0xc0, 0x27, 0x72, 0x52
db 0xdb, 0xc5, 0xed, 0xe1, 0x86, 0x19, 0x0a, 0xff, 0x43, 0x3d, 0x1c, 0x12, 0xb2, 0xbe, 0x5c, 0x12
db 0x4b, 0xbf, 0xff, 0x20, 0xe3, 0xde, 0x4a, 0x74, 0x89, 0x67, 0x42, 0xc3, 0xaf, 0xe3, 0x8a, 0x8a
db 0x57, 0x88, 0xdf, 0xbe, 0x1a, 0x0c, 0x58, 0xa1, 0xfe, 0x21, 0x57, 0x97, 0xf6, 0xef, 0xba, 0x34
db 0x54, 0x60, 0x00, 0x71, 0x09, 0x4a, 0x5b, 0x89, 0x61, 0x4a, 0x67, 0x19, 0x34, 0x44, 0x83, 0x21
db 0x3d, 0xeb, 0x67, 0xff, 0xf7, 0x68, 0xbb, 0x29, 0xa0, 0x74, 0x5e, 0xad, 0x78, 0xb4, 0x11, 0xc5
db 0x5e, 0x0e, 0xc0, 0xd4, 0xe7, 0x50, 0x40, 0xa1, 0xb5, 0x98, 0xdb, 0x75, 0x1f, 0xa5, 0xbc, 0x1b
db 0xeb, 0x13, 0x18, 0x0e, 0x92, 0x54, 0x17, 0x2d, 0x5b, 0xf8, 0x09, 0x50, 0x27, 0x49, 0xf5, 0x01
db 0xb9, 0x51, 0xd1, 0x85, 0x34, 0x67, 0xd8, 0xb9, 0x5f, 0x01, 0x7b, 0xfc, 0xe7, 0x1e, 0xc8, 0xfc
db 0x2f, 0xda, 0x81, 0xfd, 0x76, 0x69, 0x5b, 0x47, 0x98, 0x1b, 0x9b, 0xee, 0x9b, 0x18, 0x8e, 0x30
db 0x85, 0x9d, 0x45, 0xde, 0xa8, 0x9b, 0x4e, 0x57, 0x26, 0x90, 0x0b, 0x9a, 0xe0, 0xf7, 0xfa, 0x08
db 0x1d, 0xe3, 0xca, 0xb8, 0xaa, 0xda, 0x4e, 0xe3, 0xb6, 0x33, 0x05, 0x9a, 0x75, 0x70, 0x18, 0x86
db 0x60, 0x31, 0xc1, 0x05, 0x56, 0x02, 0x30, 0xbd, 0xff, 0x3b, 0xa9, 0xca, 0xe4, 0x84, 0xe6, 0x96
db 0x47, 0xcf, 0x8b, 0xa8, 0xd4, 0x63, 0x8f, 0x8f, 0x55, 0x4a, 0xbc, 0x4c, 0x3c, 0x61, 0x96, 0x38
db 0xcc, 0x10, 0x7e, 0x4e, 0x5c, 0x97, 0xd3, 0x54, 0x22, 0xde, 0xfb, 0x03, 0x81, 0x4e, 0x6d, 0x76
db 0xb5, 0xab, 0x8f, 0xba, 0xf5, 0xf0, 0x1a, 0xf9, 0x69, 0x64, 0x30, 0xb3, 0x19, 0x30, 0x54, 0x97
db 0x14, 0x66, 0x5c, 0xcf, 0x48, 0x0f, 0x74, 0xf3, 0xbe, 0x16, 0x10, 0x6c, 0xb4, 0x93, 0x86, 0xd1
db 0x21, 0xd0, 0x6a, 0x12, 0x35, 0x03, 0x45, 0x99, 0xaa, 0xe1, 0x0a, 0xd9, 0x58, 0x83, 0x2f, 0x97
db 0xcb, 0x0d, 0x81, 0x4b, 0x82, 0x01, 0x6f, 0xd6, 0x20, 0xee, 0xf3, 0xbf, 0xdc, 0x3d, 0x67, 0x6c
db 0xa5, 0x7c, 0x6d, 0x21, 0x09, 0x99, 0x2e, 0x0a, 0x98, 0x7c, 0x50, 0x56, 0x19, 0x54, 0xcc, 0x79
db 0xe1, 0x84, 0x18, 0x86, 0xf8, 0x5a, 0x1b, 0xf7, 0x1f, 0x38, 0xe0, 0x3a, 0xb9, 0x50, 0xc1, 0xf1
db 0xbe, 0x66, 0x89, 0xe2, 0x68, 0x4a, 0x11, 0x0b, 0xfb, 0x84, 0x02, 0x38, 0x31, 0xf4, 0xda, 0x50
db 0xb6, 0x5f, 0x27, 0x62, 0xc7, 0x5a, 0x0f, 0x99, 0xb7, 0x7e, 0x4a, 0x49, 0xe9, 0x67, 0xe0, 0xa5
db 0x0d, 0x08, 0x95, 0xf0, 0xe4, 0x3b, 0x62, 0x30, 0x2b, 0x89, 0x21, 0xdd, 0x52, 0x99, 0x12, 0x16
db 0x83, 0x94, 0x6a, 0x38, 0x1f, 0x8d, 0x81, 0xbf, 0x1f, 0xf9, 0xe0, 0x9c, 0x80, 0xcc, 0x7c, 0xfe
db 0x33, 0x35, 0x27, 0x26, 0xca, 0xcc, 0x1f, 0x43, 0xcd, 0xb0, 0x74, 0x0e, 0xff, 0x1c, 0x86, 0x43
db 0xab, 0x44, 0xbc, 0x31, 0xff, 0xa4, 0x54, 0x95, 0xd4, 0x79, 0x9e, 0xc0, 0xed, 0x87, 0x1c, 0x2e
db 0x50, 0x47, 0xad, 0xc0, 0x2f, 0x5e, 0x8c, 0x15, 0xfb, 0x86, 0x2c, 0xa5, 0x61, 0x2a, 0x60, 0x12
db 0xbc, 0x1f, 0x84, 0xe9, 0x75, 0x55, 0x7e, 0x2c, 0x11, 0xd0, 0xfc, 0x66, 0x89, 0x86, 0x2f, 0x26
db 0x43, 0x1e, 0xa6, 0x6c, 0xa6, 0x40, 0xa9, 0x37, 0x65, 0x99, 0x72, 0xe1, 0x1a, 0xdc, 0x23, 0x53
db 0x09, 0x8e, 0xa1, 0xd6, 0xda, 0xd9, 0x95, 0xaf, 0x58, 0xe0, 0x2a, 0x4a, 0xd3, 0xbd, 0xbd, 0x86
align 4096
result:
dq 0
+2 -1
View File
@@ -9,7 +9,8 @@
"XMM5": ["0x0000000001ecb156", "0", "0x1c86432298df55c8", "0xb29bfeda891be9cc"],
"XMM6": ["0x00000000432298df", "0", "0x88b0bd28710f2147", "0xc4e95e887fb5ac38"],
"XMM7": ["0x0000b0bd28710f21", "0", "0xa7df8c2ad03e5be4", "0x6c70d1eec2d395ea"]
}
},
"HostFeatures": ["SSE4A"]
}
%endif
+2 -1
View File
@@ -9,7 +9,8 @@
"XMM5": ["0x0000000001ecb156", "0", "0x1c86432298df55c8", "0xb29bfeda891be9cc"],
"XMM6": ["0x00000000432298df", "0", "0x88b0bd28710f2147", "0xc4e95e887fb5ac38"],
"XMM7": ["0x0000b0bd28710f21", "0", "0xa7df8c2ad03e5be4", "0x6c70d1eec2d395ea"]
}
},
"HostFeatures": ["SSE4A"]
}
%endif
+2 -1
View File
@@ -9,7 +9,8 @@
"XMM5": ["0x017003bfe89712b0", "0", "0x1c86432298df55c8", "0xb29bfeda891be9cc"],
"XMM6": ["0x1c8678f6900455c8", "0", "0x88b0bd28710f2147", "0xc4e95e887fb5ac38"],
"XMM7": ["0x881fa17837c17f47", "0", "0xa7df8c2ad03e5be4", "0x6c70d1eec2d395ea"]
}
},
"HostFeatures": ["SSE4A"]
}
%endif
+2 -1
View File
@@ -9,7 +9,8 @@
"XMM5": ["0x0acb4bcc689712b0", "0", "0x1c86432298df55c8", "0xb29bfeda891be9cc"],
"XMM6": ["0x1c8625a6a7a855c8", "0", "0x88b0bd28710f2147", "0xc4e95e887fb5ac38"],
"XMM7": ["0x88b3b4b5b6b7b847", "0", "0xa7df8c2ad03e5be4", "0x6c70d1eec2d395ea"]
}
},
"HostFeatures": ["SSE4A"]
}
%endif
+53
View File
@@ -0,0 +1,53 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0x3FDA827999FCEF32",
"RBX": "0xBFE0000000000000",
"RCX": "0x3FF0000000000000"
},
"Env": { "FEX_X87REDUCEDPRECISION" : "1" }
}
%endif
; Test F2XM1 with non-trivial inputs
; Test 1: 2^0.5 - 1 = sqrt(2) - 1 ~= 0.41421356237309515
; Test 2: 2^(-1) - 1 = -0.5
; Test 3: 2^1 - 1 = 1.0
mov rdx, 0xe0000000
; Test 1: f2xm1(0.5)
lea rsi, [rel data_half]
fld tword [rsi]
f2xm1
fstp qword [rdx]
mov rax, [rdx]
; Test 2: f2xm1(-1.0)
lea rsi, [rel data_neg1]
fld tword [rsi]
f2xm1
fstp qword [rdx]
mov rbx, [rdx]
; Test 3: f2xm1(1.0)
lea rsi, [rel data_pos1]
fld tword [rsi]
f2xm1
fstp qword [rdx]
mov rcx, [rdx]
hlt
align 8
data_half:
dt 0.5
dq 0
data_neg1:
dt -1.0
dq 0
data_pos1:
dt 1.0
dq 0
+60
View File
@@ -0,0 +1,60 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0x4008000000000000",
"RBX": "0x4008000000000000",
"RCX": "0x4024000000000000"
},
"Env": { "FEX_X87REDUCEDPRECISION" : "1" }
}
%endif
; Test fyl2x (y * log2(x)) with exact integer results in double precision.
mov rsi, 0xe0000000
; 1.0 * log2(8.0) = 3.0
lea rdx, [rel val_1_0]
fld tword [rdx]
lea rdx, [rel val_8_0]
fld tword [rdx]
fyl2x
fstp qword [rsi]
mov rax, [rsi]
; 3.0 * log2(2.0) = 3.0
lea rdx, [rel val_3_0]
fld tword [rdx]
lea rdx, [rel val_2_0]
fld tword [rdx]
fyl2x
fstp qword [rsi]
mov rbx, [rsi]
; 2.0 * log2(32.0) = 10.0
lea rdx, [rel val_2_0]
fld tword [rdx]
lea rdx, [rel val_32_0]
fld tword [rdx]
fyl2x
fstp qword [rsi]
mov rcx, [rsi]
hlt
align 8
val_1_0:
dt 1.0
dq 0
val_2_0:
dt 2.0
dq 0
val_3_0:
dt 3.0
dq 0
val_8_0:
dt 8.0
dq 0
val_32_0:
dt 32.0
dq 0
+63
View File
@@ -0,0 +1,63 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "1"
},
"Env": { "FEX_X87REDUCEDPRECISION" : "1" }
}
%endif
%include "checkprecision.mac"
; Test fpatan (atan2) with multiple quadrant cases in double precision.
mov rsi, 0xe0000000
; atan2(1.0, 1.0) = pi/4
lea rdx, [rel one_pos]
fld tword [rdx]
fld tword [rdx]
fpatan
fstp qword [rsi]
check_relerr_d rel expected_pi4, rsi, rel tolerance
mov r8, rax
; atan2(1.0, -1.0) = 3*pi/4
lea rdx, [rel one_pos]
fld tword [rdx]
lea rdx, [rel one_neg]
fld tword [rdx]
fpatan
fstp qword [rsi]
check_relerr_d rel expected_3pi4, rsi, rel tolerance
and r8, rax
; atan2(-1.0, 1.0) = -pi/4
lea rdx, [rel one_neg]
fld tword [rdx]
lea rdx, [rel one_pos]
fld tword [rdx]
fpatan
fstp qword [rsi]
check_relerr_d rel expected_neg_pi4, rsi, rel tolerance
and rax, r8
hlt
align 8
one_pos:
dt 1.0
dq 0
one_neg:
dt -1.0
dq 0
expected_pi4:
dq 0x3fe921fb54442d18 ; pi/4
expected_3pi4:
dq 0x4002d97c7f3321d2 ; 3*pi/4
expected_neg_pi4:
dq 0xbfe921fb54442d18 ; -pi/4
tolerance:
dq 0x3cb0000000000000 ; 2^-52, ~1 ULP relative error
define_check_data_constants
+54
View File
@@ -0,0 +1,54 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0x4098000000000000",
"RBX": "0x3FF8000000000000"
},
"Env": { "FEX_X87REDUCEDPRECISION" : "1" }
}
%endif
; Test FSCALE with double-precision verification
; Test 1: 1.5 * 2^10 = 1536.0 (0x4098000000000000)
; Test 2: 3.0 * 2^(-1) = 1.5 (0x3FF8000000000000)
mov rcx, 0xe0000000
; Test 1: 1.5 * 2^10
lea rdx, [rel data_exp1]
fld tword [rdx]
lea rdx, [rel data_base1]
fld tword [rdx]
fscale
fstp qword [rcx]
mov rax, [rcx]
fstp st0
; Test 2: 3.0 * 2^(-1)
lea rdx, [rel data_exp2]
fld tword [rdx]
lea rdx, [rel data_base2]
fld tword [rdx]
fscale
fstp qword [rcx]
mov rbx, [rcx]
fstp st0
hlt
align 8
data_base1:
dt 1.5
dq 0
data_exp1:
dt 10.0
dq 0
data_base2:
dt 3.0
dq 0
data_exp2:
dt -1.0
dq 0
+2 -1
View File
@@ -6,7 +6,8 @@
"MemoryRegions": {
"0x100000000": "4096",
"0x100002000": "4096"
}
},
"HostFeatures": ["CLZERO"]
}
%endif
+2 -1
View File
@@ -6,7 +6,8 @@
"MemoryRegions": {
"0x100000000": "4096",
"0x100002000": "4096"
}
},
"HostFeatures": ["SSE4A"]
}
%endif
+2 -1
View File
@@ -6,7 +6,8 @@
"MemoryRegions": {
"0x100000000": "4096",
"0x100002000": "4096"
}
},
"HostFeatures": ["SSE4A"]
}
%endif
@@ -485,7 +485,7 @@
],
"ExpectedArm64ASM": [
"ushr v2.4s, v16.4s, #31",
"ldr q3, [x28, #3168]",
"ldr q3, [x28, #3200]",
"ushl v2.4s, v2.4s, v3.4s",
"addv s2, v2.4s",
"mov w4, v2.s[0]"
@@ -499,7 +499,7 @@
"ExpectedArm64ASM": [
"ldr q2, [x28, #192]",
"ushr v3.4s, v16.4s, #31",
"ldr q4, [x28, #3168]",
"ldr q4, [x28, #3200]",
"ushl v3.4s, v3.4s, v4.4s",
"addv s3, v3.4s",
"mov w20, v3.s[0]",
@@ -3437,9 +3437,9 @@
"Map 1 0b00 0x5f 128-bit"
],
"ExpectedArm64ASM": [
"fcmgt v0.4s, v18.4s, v17.4s",
"fcmgt v0.4s, v17.4s, v18.4s",
"mov v16.16b, v17.16b",
"bit v16.16b, v18.16b, v0.16b",
"bif v16.16b, v18.16b, v0.16b",
"stp xzr, xzr, [x28, #192]"
]
},
@@ -3451,11 +3451,11 @@
"ExpectedArm64ASM": [
"ldr q2, [x28, #208]",
"ldr q3, [x28, #224]",
"fcmgt v0.4s, v18.4s, v17.4s",
"fcmgt v0.4s, v17.4s, v18.4s",
"mov v16.16b, v17.16b",
"bit v16.16b, v18.16b, v0.16b",
"fcmgt v0.4s, v3.4s, v2.4s",
"bit v2.16b, v3.16b, v0.16b",
"bif v16.16b, v18.16b, v0.16b",
"fcmgt v0.4s, v2.4s, v3.4s",
"bif v2.16b, v3.16b, v0.16b",
"str q2, [x28, #192]"
]
},
@@ -3465,9 +3465,9 @@
"Map 1 0b01 0x5f 128-bit"
],
"ExpectedArm64ASM": [
"fcmgt v0.2d, v18.2d, v17.2d",
"fcmgt v0.2d, v17.2d, v18.2d",
"mov v16.16b, v17.16b",
"bit v16.16b, v18.16b, v0.16b",
"bif v16.16b, v18.16b, v0.16b",
"stp xzr, xzr, [x28, #192]"
]
},
@@ -3479,11 +3479,11 @@
"ExpectedArm64ASM": [
"ldr q2, [x28, #208]",
"ldr q3, [x28, #224]",
"fcmgt v0.2d, v18.2d, v17.2d",
"fcmgt v0.2d, v17.2d, v18.2d",
"mov v16.16b, v17.16b",
"bit v16.16b, v18.16b, v0.16b",
"fcmgt v0.2d, v3.2d, v2.2d",
"bit v2.16b, v3.16b, v0.16b",
"bif v16.16b, v18.16b, v0.16b",
"fcmgt v0.2d, v2.2d, v3.2d",
"bif v2.16b, v3.16b, v0.16b",
"str q2, [x28, #192]"
]
},
@@ -3884,7 +3884,7 @@
"Map 1 0b01 0xd0 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3072]",
"ldr q2, [x28, #3104]",
"eor v2.16b, v18.16b, v2.16b",
"fadd v16.2d, v17.2d, v2.2d",
"stp xzr, xzr, [x28, #192]"
@@ -3898,7 +3898,7 @@
"ExpectedArm64ASM": [
"ldr q2, [x28, #208]",
"ldr q3, [x28, #224]",
"ldr q4, [x28, #3072]",
"ldr q4, [x28, #3104]",
"eor v5.16b, v18.16b, v4.16b",
"fadd v16.2d, v17.2d, v5.2d",
"eor v3.16b, v3.16b, v4.16b",
@@ -3912,7 +3912,7 @@
"Map 1 0b11 0xd0 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3040]",
"ldr q2, [x28, #3072]",
"eor v2.16b, v18.16b, v2.16b",
"fadd v16.4s, v17.4s, v2.4s",
"stp xzr, xzr, [x28, #192]"
@@ -3926,7 +3926,7 @@
"ExpectedArm64ASM": [
"ldr q2, [x28, #208]",
"ldr q3, [x28, #224]",
"ldr q4, [x28, #3040]",
"ldr q4, [x28, #3072]",
"eor v5.16b, v18.16b, v4.16b",
"fadd v16.4s, v17.4s, v5.4s",
"eor v3.16b, v3.16b, v4.16b",
@@ -4097,7 +4097,7 @@
"Map 1 0b01 0xd7 256-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3296]",
"ldr q2, [x28, #3328]",
"cmlt v3.16b, v16.16b, #0",
"and v2.16b, v3.16b, v2.16b",
"addp v2.16b, v2.16b, v2.16b",
@@ -4113,7 +4113,7 @@
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #192]",
"ldr q3, [x28, #3296]",
"ldr q3, [x28, #3328]",
"cmlt v4.16b, v16.16b, #0",
"and v4.16b, v4.16b, v3.16b",
"addp v4.16b, v4.16b, v4.16b",
@@ -1917,7 +1917,7 @@
"Map 2 0b01 0x41 256-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3008]",
"ldr q2, [x28, #3040]",
"zip1 v3.8h, v2.8h, v17.8h",
"zip2 v2.8h, v2.8h, v17.8h",
"umin v2.4s, v3.4s, v2.4s",
@@ -4485,7 +4485,7 @@
"Map 2 0b01 0x96 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3040]",
"ldr q2, [x28, #3072]",
"eor v2.16b, v17.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.4s, v16.4s, v18.4s",
@@ -4502,7 +4502,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3040]",
"ldr q5, [x28, #3072]",
"eor v6.16b, v17.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.4s, v16.4s, v18.4s",
@@ -4518,7 +4518,7 @@
"Map 2 0b01 0x96 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3072]",
"ldr q2, [x28, #3104]",
"eor v2.16b, v17.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.2d, v16.2d, v18.2d",
@@ -4535,7 +4535,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3072]",
"ldr q5, [x28, #3104]",
"eor v6.16b, v17.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.2d, v16.2d, v18.2d",
@@ -4551,7 +4551,7 @@
"Map 2 0b01 0x97 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3104]",
"ldr q2, [x28, #3136]",
"eor v2.16b, v17.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.4s, v16.4s, v18.4s",
@@ -4568,7 +4568,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3104]",
"ldr q5, [x28, #3136]",
"eor v6.16b, v17.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.4s, v16.4s, v18.4s",
@@ -4584,7 +4584,7 @@
"Map 2 0b01 0x97 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3136]",
"ldr q2, [x28, #3168]",
"eor v2.16b, v17.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.2d, v16.2d, v18.2d",
@@ -4601,7 +4601,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3136]",
"ldr q5, [x28, #3168]",
"eor v6.16b, v17.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.2d, v16.2d, v18.2d",
@@ -5541,7 +5541,7 @@
"Map 2 0b01 0xa6 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3040]",
"ldr q2, [x28, #3072]",
"eor v2.16b, v18.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.4s, v17.4s, v16.4s",
@@ -5558,7 +5558,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3040]",
"ldr q5, [x28, #3072]",
"eor v6.16b, v18.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.4s, v17.4s, v16.4s",
@@ -5574,7 +5574,7 @@
"Map 2 0b01 0xa6 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3072]",
"ldr q2, [x28, #3104]",
"eor v2.16b, v18.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.2d, v17.2d, v16.2d",
@@ -5591,7 +5591,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3072]",
"ldr q5, [x28, #3104]",
"eor v6.16b, v18.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.2d, v17.2d, v16.2d",
@@ -5607,7 +5607,7 @@
"Map 2 0b01 0xa7 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3104]",
"ldr q2, [x28, #3136]",
"eor v2.16b, v18.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.4s, v17.4s, v16.4s",
@@ -5624,7 +5624,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3104]",
"ldr q5, [x28, #3136]",
"eor v6.16b, v18.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.4s, v17.4s, v16.4s",
@@ -5640,7 +5640,7 @@
"Map 2 0b01 0xa7 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3136]",
"ldr q2, [x28, #3168]",
"eor v2.16b, v18.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.2d, v17.2d, v16.2d",
@@ -5657,7 +5657,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3136]",
"ldr q5, [x28, #3168]",
"eor v6.16b, v18.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.2d, v17.2d, v16.2d",
@@ -5673,7 +5673,7 @@
"Map 2 0b01 0xb6 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3040]",
"ldr q2, [x28, #3072]",
"eor v2.16b, v16.16b, v2.16b",
"mov v16.16b, v2.16b",
"fmla v16.4s, v17.4s, v18.4s",
@@ -5689,7 +5689,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3040]",
"ldr q5, [x28, #3072]",
"eor v6.16b, v16.16b, v5.16b",
"mov v16.16b, v6.16b",
"fmla v16.4s, v17.4s, v18.4s",
@@ -5704,7 +5704,7 @@
"Map 2 0b01 0xb6 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3072]",
"ldr q2, [x28, #3104]",
"eor v2.16b, v16.16b, v2.16b",
"mov v16.16b, v2.16b",
"fmla v16.2d, v17.2d, v18.2d",
@@ -5720,7 +5720,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3072]",
"ldr q5, [x28, #3104]",
"eor v6.16b, v16.16b, v5.16b",
"mov v16.16b, v6.16b",
"fmla v16.2d, v17.2d, v18.2d",
@@ -5735,7 +5735,7 @@
"Map 2 0b01 0xb7 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3104]",
"ldr q2, [x28, #3136]",
"eor v2.16b, v16.16b, v2.16b",
"mov v16.16b, v2.16b",
"fmla v16.4s, v17.4s, v18.4s",
@@ -5751,7 +5751,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3104]",
"ldr q5, [x28, #3136]",
"eor v6.16b, v16.16b, v5.16b",
"mov v16.16b, v6.16b",
"fmla v16.4s, v17.4s, v18.4s",
@@ -5766,7 +5766,7 @@
"Map 2 0b01 0xb7 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3136]",
"ldr q2, [x28, #3168]",
"eor v2.16b, v16.16b, v2.16b",
"mov v16.16b, v2.16b",
"fmla v16.2d, v17.2d, v18.2d",
@@ -5782,7 +5782,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3136]",
"ldr q5, [x28, #3168]",
"eor v6.16b, v16.16b, v5.16b",
"mov v16.16b, v6.16b",
"fmla v16.2d, v17.2d, v18.2d",
@@ -2843,7 +2843,7 @@
"Map 2 0b01 0x96 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3040]",
"ldr q2, [x28, #3072]",
"eor v2.16b, v17.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.4s, v16.4s, v18.4s",
@@ -2860,7 +2860,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3040]",
"ldr q5, [x28, #3072]",
"eor v6.16b, v17.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.4s, v16.4s, v18.4s",
@@ -2876,7 +2876,7 @@
"Map 2 0b01 0x96 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3072]",
"ldr q2, [x28, #3104]",
"eor v2.16b, v17.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.2d, v16.2d, v18.2d",
@@ -2893,7 +2893,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3072]",
"ldr q5, [x28, #3104]",
"eor v6.16b, v17.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.2d, v16.2d, v18.2d",
@@ -2909,7 +2909,7 @@
"Map 2 0b01 0x97 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3104]",
"ldr q2, [x28, #3136]",
"eor v2.16b, v17.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.4s, v16.4s, v18.4s",
@@ -2926,7 +2926,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3104]",
"ldr q5, [x28, #3136]",
"eor v6.16b, v17.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.4s, v16.4s, v18.4s",
@@ -2942,7 +2942,7 @@
"Map 2 0b01 0x97 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3136]",
"ldr q2, [x28, #3168]",
"eor v2.16b, v17.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.2d, v16.2d, v18.2d",
@@ -2959,7 +2959,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3136]",
"ldr q5, [x28, #3168]",
"eor v6.16b, v17.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.2d, v16.2d, v18.2d",
@@ -3879,7 +3879,7 @@
"Map 2 0b01 0xa6 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3040]",
"ldr q2, [x28, #3072]",
"eor v2.16b, v18.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.4s, v17.4s, v16.4s",
@@ -3896,7 +3896,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3040]",
"ldr q5, [x28, #3072]",
"eor v6.16b, v18.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.4s, v17.4s, v16.4s",
@@ -3912,7 +3912,7 @@
"Map 2 0b01 0xa6 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3072]",
"ldr q2, [x28, #3104]",
"eor v2.16b, v18.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.2d, v17.2d, v16.2d",
@@ -3929,7 +3929,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3072]",
"ldr q5, [x28, #3104]",
"eor v6.16b, v18.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.2d, v17.2d, v16.2d",
@@ -3945,7 +3945,7 @@
"Map 2 0b01 0xa7 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3104]",
"ldr q2, [x28, #3136]",
"eor v2.16b, v18.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.4s, v17.4s, v16.4s",
@@ -3962,7 +3962,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3104]",
"ldr q5, [x28, #3136]",
"eor v6.16b, v18.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.4s, v17.4s, v16.4s",
@@ -3978,7 +3978,7 @@
"Map 2 0b01 0xa7 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3136]",
"ldr q2, [x28, #3168]",
"eor v2.16b, v18.16b, v2.16b",
"mov v0.16b, v2.16b",
"fmla v0.2d, v17.2d, v16.2d",
@@ -3995,7 +3995,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3136]",
"ldr q5, [x28, #3168]",
"eor v6.16b, v18.16b, v5.16b",
"mov v0.16b, v6.16b",
"fmla v0.2d, v17.2d, v16.2d",
@@ -4011,7 +4011,7 @@
"Map 2 0b01 0xb6 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3040]",
"ldr q2, [x28, #3072]",
"eor v2.16b, v16.16b, v2.16b",
"mov v16.16b, v2.16b",
"fmla v16.4s, v17.4s, v18.4s",
@@ -4027,7 +4027,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3040]",
"ldr q5, [x28, #3072]",
"eor v6.16b, v16.16b, v5.16b",
"mov v16.16b, v6.16b",
"fmla v16.4s, v17.4s, v18.4s",
@@ -4042,7 +4042,7 @@
"Map 2 0b01 0xb6 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3072]",
"ldr q2, [x28, #3104]",
"eor v2.16b, v16.16b, v2.16b",
"mov v16.16b, v2.16b",
"fmla v16.2d, v17.2d, v18.2d",
@@ -4058,7 +4058,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3072]",
"ldr q5, [x28, #3104]",
"eor v6.16b, v16.16b, v5.16b",
"mov v16.16b, v6.16b",
"fmla v16.2d, v17.2d, v18.2d",
@@ -4073,7 +4073,7 @@
"Map 2 0b01 0xb7 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3104]",
"ldr q2, [x28, #3136]",
"eor v2.16b, v16.16b, v2.16b",
"mov v16.16b, v2.16b",
"fmla v16.4s, v17.4s, v18.4s",
@@ -4089,7 +4089,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3104]",
"ldr q5, [x28, #3136]",
"eor v6.16b, v16.16b, v5.16b",
"mov v16.16b, v6.16b",
"fmla v16.4s, v17.4s, v18.4s",
@@ -4104,7 +4104,7 @@
"Map 2 0b01 0xb7 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3136]",
"ldr q2, [x28, #3168]",
"eor v2.16b, v16.16b, v2.16b",
"mov v16.16b, v2.16b",
"fmla v16.2d, v17.2d, v18.2d",
@@ -4120,7 +4120,7 @@
"ldr q2, [x28, #192]",
"ldr q3, [x28, #208]",
"ldr q4, [x28, #224]",
"ldr q5, [x28, #3136]",
"ldr q5, [x28, #3168]",
"eor v6.16b, v16.16b, v5.16b",
"mov v16.16b, v6.16b",
"fmla v16.2d, v17.2d, v18.2d",
@@ -337,7 +337,7 @@
"Map 3 0b01 0x02 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3200]",
"ldr q2, [x28, #3232]",
"tbx v16.16b, {v17.16b}, v2.16b",
"stp xzr, xzr, [x28, #192]"
]
@@ -348,7 +348,7 @@
"Map 3 0b01 0x02 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3216]",
"ldr q2, [x28, #3248]",
"tbx v16.16b, {v17.16b}, v2.16b",
"stp xzr, xzr, [x28, #192]"
]
@@ -369,7 +369,7 @@
"Map 3 0b01 0x02 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3232]",
"ldr q2, [x28, #3264]",
"tbx v16.16b, {v17.16b}, v2.16b",
"stp xzr, xzr, [x28, #192]"
]
@@ -391,7 +391,7 @@
"Map 3 0b01 0x02 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3248]",
"ldr q2, [x28, #3280]",
"tbx v16.16b, {v17.16b}, v2.16b",
"stp xzr, xzr, [x28, #192]"
]
@@ -412,7 +412,7 @@
"Map 3 0b01 0x02 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3264]",
"ldr q2, [x28, #3296]",
"tbx v16.16b, {v17.16b}, v2.16b",
"stp xzr, xzr, [x28, #192]"
]
@@ -423,7 +423,7 @@
"Map 3 0b01 0x02 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3280]",
"ldr q2, [x28, #3312]",
"tbx v16.16b, {v17.16b}, v2.16b",
"stp xzr, xzr, [x28, #192]"
]
@@ -3488,7 +3488,7 @@
],
"ExpectedArm64ASM": [
"movi v2.2d, #0x0",
"ldr q3, [x28, #3184]",
"ldr q3, [x28, #3216]",
"mov v16.16b, v17.16b",
"aese v16.16b, v2.16b",
"tbl v16.16b, {v16.16b}, v3.16b",
@@ -3502,7 +3502,7 @@
],
"ExpectedArm64ASM": [
"movi v2.2d, #0x0",
"ldr q3, [x28, #3184]",
"ldr q3, [x28, #3216]",
"mov v16.16b, v17.16b",
"aese v16.16b, v2.16b",
"tbl v16.16b, {v16.16b}, v3.16b",
@@ -55,7 +55,7 @@
"0x66 0x0f 0x3a 0xdf"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3184]",
"ldr q2, [x28, #3216]",
"movi v3.2d, #0x0",
"mov v16.16b, v17.16b",
"aese v16.16b, v3.16b",
@@ -68,7 +68,7 @@
"0x66 0x0f 0x3a 0xdf"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3184]",
"ldr q2, [x28, #3216]",
"movi v3.2d, #0x0",
"mov v16.16b, v17.16b",
"aese v16.16b, v3.16b",
@@ -84,7 +84,7 @@
"0x66 0x0f 0x3a 0xcc"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3568]",
"ldr q2, [x28, #3600]",
"movi v3.2d, #0x0",
"ldr x0, [x28, #2688]",
"ldr q4, [x0, #432]",
@@ -101,7 +101,7 @@
"0x66 0x0f 0x3a 0xcc"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3584]",
"ldr q2, [x28, #3616]",
"movi v3.2d, #0x0",
"ldr x0, [x28, #2688]",
"ldr q4, [x0, #432]",
@@ -118,7 +118,7 @@
"0x66 0x0f 0x3a 0xcc"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3600]",
"ldr q2, [x28, #3632]",
"movi v3.2d, #0x0",
"ldr x0, [x28, #2688]",
"ldr q4, [x0, #432]",
@@ -135,7 +135,7 @@
"0x66 0x0f 0x3a 0xcc"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3616]",
"ldr q2, [x28, #3648]",
"movi v3.2d, #0x0",
"ldr x0, [x28, #2688]",
"ldr q4, [x0, #432]",
+2 -2
View File
@@ -269,8 +269,8 @@
"strb w20, [x28, #1202]",
"ldr d2, [x28, #1072]",
"ldr d3, [x28, #1056]",
"fcmgt v0.4s, v2.4s, v3.4s",
"bit v3.16b, v2.16b, v0.16b",
"fcmgt v0.4s, v3.4s, v2.4s",
"bif v3.16b, v2.16b, v0.16b",
"str d3, [x28, #1056]",
"strh w20, [x28, #1064]"
]
@@ -377,7 +377,7 @@
"mrs x0, nzcv",
"cmp w20, w4",
"ccmp w21, w5, #nzcv, eq",
"rmif x0, #0, #NzCV",
"rmif x0, #28, #NzCV",
"csel x4, x20, x4, ne",
"csel x5, x21, x5, ne",
"subs x26, x4, #0x0 (0)"
@@ -126,7 +126,7 @@
"mrs x0, nzcv",
"cmp w22, w4",
"ccmp w23, w5, #nzcv, eq",
"rmif x0, #0, #NzCV",
"rmif x0, #28, #NzCV",
"csel x4, x22, x4, ne",
"csel x5, x23, x5, ne",
"cfinv"
@@ -1608,7 +1608,7 @@
"mov w20, #0xffff",
"strb w20, [x28, #1202]",
"ldr d2, [x28, #1056]",
"ldr d3, [x28, #3296]",
"ldr d3, [x28, #3328]",
"cmlt v2.16b, v2.16b, #0",
"and v2.8b, v2.8b, v3.8b",
"addp v2.16b, v2.16b, v2.16b",
@@ -713,7 +713,7 @@
"mrs x0, nzcv",
"cmp w20, w4",
"ccmp w21, w5, #nzcv, eq",
"rmif x0, #0, #NzCV",
"rmif x0, #28, #NzCV",
"csel x4, x20, x4, ne",
"csel x5, x21, x5, ne"
]
@@ -728,7 +728,7 @@
"mrs x0, nzcv",
"cmp x20, x4",
"ccmp x21, x5, #nzcv, eq",
"rmif x0, #0, #NzCV",
"rmif x0, #28, #NzCV",
"csel x4, x20, x4, ne",
"csel x5, x21, x5, ne"
]
@@ -37,7 +37,7 @@
"ExpectedInstructionCount": 7,
"Comment": "0x66 0x0f 0xd7",
"ExpectedArm64ASM": [
"ldr q2, [x28, #3296]",
"ldr q2, [x28, #3328]",
"cmlt v3.16b, v16.16b, #0",
"and v2.16b, v3.16b, v2.16b",
"addp v2.16b, v2.16b, v2.16b",
@@ -68,7 +68,7 @@
"Map 1 0b01 0xd7 256-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3296]",
"ldr q2, [x28, #3328]",
"cmlt v3.16b, v16.16b, #0",
"and v2.16b, v3.16b, v2.16b",
"addp v2.16b, v2.16b, v2.16b",
@@ -557,7 +557,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q3, [x28, #3552]",
"ldr q3, [x28, #3584]",
"bic v2.16b, v2.16b, v3.16b",
"ldr s3, [x4]",
"str x30, [sp, #-16]!",
@@ -567,7 +567,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v3.16b, v0.16b",
"ldr q4, [x28, #3552]",
"ldr q4, [x28, #3584]",
"bic v3.16b, v3.16b, v4.16b",
"strb wzr, [x28, #1049]",
"str x30, [sp, #-16]!",
@@ -598,7 +598,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q3, [x28, #3552]",
"ldr q3, [x28, #3584]",
"bic v2.16b, v2.16b, v3.16b",
"ldr s3, [x4, #4]",
"str x30, [sp, #-16]!",
@@ -608,7 +608,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v3.16b, v0.16b",
"ldr q5, [x28, #3552]",
"ldr q5, [x28, #3584]",
"bic v3.16b, v3.16b, v5.16b",
"strb wzr, [x28, #1049]",
"str x30, [sp, #-16]!",
@@ -639,7 +639,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q3, [x28, #3552]",
"ldr q3, [x28, #3584]",
"bic v2.16b, v2.16b, v3.16b",
"ldr s3, [x4, #8]",
"str x30, [sp, #-16]!",
@@ -649,7 +649,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v3.16b, v0.16b",
"ldr q6, [x28, #3552]",
"ldr q6, [x28, #3584]",
"bic v3.16b, v3.16b, v6.16b",
"strb wzr, [x28, #1049]",
"str x30, [sp, #-16]!",
@@ -3789,7 +3789,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q9, [x28, #3552]",
"ldr q9, [x28, #3584]",
"eor v2.16b, v2.16b, v9.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -3839,7 +3839,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q9, [x28, #3552]",
"ldr q9, [x28, #3584]",
"eor v2.16b, v2.16b, v9.16b",
"ldr s9, [x8, #28]",
"str x30, [sp, #-16]!",
@@ -4002,7 +4002,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q9, [x28, #3552]",
"ldr q9, [x28, #3584]",
"eor v2.16b, v2.16b, v9.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -4052,7 +4052,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q9, [x28, #3552]",
"ldr q9, [x28, #3584]",
"eor v2.16b, v2.16b, v9.16b",
"ldr s9, [x8, #60]",
"str x30, [sp, #-16]!",
@@ -4238,7 +4238,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q9, [x28, #3552]",
"ldr q9, [x28, #3584]",
"eor v2.16b, v2.16b, v9.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -4259,7 +4259,7 @@
"ldr x30, [sp], #16",
"mov v9.16b, v0.16b",
"str s2, [x8, #176]",
"ldr q2, [x28, #3552]",
"ldr q2, [x28, #3584]",
"eor v2.16b, v9.16b, v2.16b",
"ldr s9, [x8, #8]",
"str x30, [sp, #-16]!",
@@ -7530,7 +7530,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v8.16b, v0.16b",
"ldr q10, [x28, #3552]",
"ldr q10, [x28, #3584]",
"eor v8.16b, v8.16b, v10.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v8.16b",
@@ -7621,7 +7621,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v8.16b, v0.16b",
"ldr q11, [x28, #3552]",
"ldr q11, [x28, #3584]",
"eor v8.16b, v8.16b, v11.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v8.16b",
@@ -7679,7 +7679,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v8.16b, v0.16b",
"ldr q11, [x28, #3552]",
"ldr q11, [x28, #3584]",
"eor v8.16b, v8.16b, v11.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v8.16b",
@@ -7952,7 +7952,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v7.16b, v0.16b",
"ldr q9, [x28, #3552]",
"ldr q9, [x28, #3584]",
"eor v7.16b, v7.16b, v9.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v7.16b",
@@ -8112,7 +8112,7 @@
"ldr x30, [sp], #16",
"fmov s2, s0",
"str s2, [x4, #1024]",
"ldr q2, [x28, #3552]",
"ldr q2, [x28, #3584]",
"eor v2.16b, v3.16b, v2.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -8130,7 +8130,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q3, [x28, #3552]",
"ldr q3, [x28, #3584]",
"eor v2.16b, v2.16b, v3.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -8141,7 +8141,7 @@
"fmov s2, s0",
"str s2, [x4, #1152]",
"strb wzr, [x28, #1049]",
"ldr q2, [x28, #3552]",
"ldr q2, [x28, #3584]",
"eor v2.16b, v6.16b, v2.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -8159,7 +8159,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q3, [x28, #3552]",
"ldr q3, [x28, #3584]",
"eor v2.16b, v2.16b, v3.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -8177,7 +8177,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q3, [x28, #3552]",
"ldr q3, [x28, #3584]",
"eor v2.16b, v2.16b, v3.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -8188,7 +8188,7 @@
"fmov s2, s0",
"str s2, [x4, #1344]",
"strb wzr, [x28, #1049]",
"ldr q2, [x28, #3552]",
"ldr q2, [x28, #3584]",
"eor v2.16b, v11.16b, v2.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -8206,7 +8206,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q3, [x28, #3552]",
"ldr q3, [x28, #3584]",
"eor v2.16b, v2.16b, v3.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -8217,7 +8217,7 @@
"fmov s2, s0",
"str s2, [x4, #1472]",
"strb wzr, [x28, #1049]",
"ldr q2, [x28, #3552]",
"ldr q2, [x28, #3584]",
"eor v2.16b, v10.16b, v2.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -8228,7 +8228,7 @@
"fmov s2, s0",
"str s2, [x4, #1536]",
"strb wzr, [x28, #1049]",
"ldr q2, [x28, #3552]",
"ldr q2, [x28, #3584]",
"eor v2.16b, v9.16b, v2.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -8239,7 +8239,7 @@
"fmov s2, s0",
"str s2, [x4, #1600]",
"strb wzr, [x28, #1049]",
"ldr q2, [x28, #3552]",
"ldr q2, [x28, #3584]",
"eor v2.16b, v8.16b, v2.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -8249,7 +8249,7 @@
"ldr x30, [sp], #16",
"fmov s2, s0",
"str s2, [x4, #1664]",
"ldr q2, [x28, #3552]",
"ldr q2, [x28, #3584]",
"eor v2.16b, v7.16b, v2.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -12538,7 +12538,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q3, [x28, #3552]",
"ldr q3, [x28, #3584]",
"eor v3.16b, v2.16b, v3.16b",
"ldr s4, [x4]",
"str x30, [sp, #-16]!",
@@ -12580,7 +12580,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v4.16b, v0.16b",
"ldr q5, [x28, #3552]",
"ldr q5, [x28, #3584]",
"eor v5.16b, v4.16b, v5.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v3.16b",
@@ -12615,7 +12615,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v5.16b, v0.16b",
"ldr q6, [x28, #3552]",
"ldr q6, [x28, #3584]",
"eor v6.16b, v5.16b, v6.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v3.16b",
@@ -12650,7 +12650,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v6.16b, v0.16b",
"ldr q7, [x28, #3552]",
"ldr q7, [x28, #3584]",
"eor v7.16b, v6.16b, v7.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v3.16b",
@@ -12685,7 +12685,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v7.16b, v0.16b",
"ldr q8, [x28, #3552]",
"ldr q8, [x28, #3584]",
"eor v8.16b, v7.16b, v8.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v3.16b",
@@ -12720,7 +12720,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v8.16b, v0.16b",
"ldr q9, [x28, #3552]",
"ldr q9, [x28, #3584]",
"eor v9.16b, v8.16b, v9.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v3.16b",
@@ -12755,7 +12755,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v9.16b, v0.16b",
"ldr q10, [x28, #3552]",
"ldr q10, [x28, #3584]",
"eor v9.16b, v9.16b, v10.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v3.16b",
@@ -12789,7 +12789,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v9.16b, v0.16b",
"ldr q10, [x28, #3552]",
"ldr q10, [x28, #3584]",
"eor v9.16b, v9.16b, v10.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v3.16b",
@@ -12823,7 +12823,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v9.16b, v0.16b",
"ldr q10, [x28, #3552]",
"ldr q10, [x28, #3584]",
"eor v9.16b, v9.16b, v10.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v3.16b",
@@ -20012,7 +20012,7 @@
"mov x8, x26",
"str s2, [x8, #16]",
"uxtb w7, w4",
"ldr q2, [x28, #3328]",
"ldr q2, [x28, #3360]",
"str w7, [x8, #56]",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -21708,7 +21708,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q3, [x28, #3552]",
"ldr q3, [x28, #3584]",
"eor v2.16b, v2.16b, v3.16b",
"add x14, x28, x20, lsl #4",
"ldr q3, [x14, #1056]",
@@ -21763,7 +21763,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q5, [x28, #3552]",
"ldr q5, [x28, #3584]",
"eor v2.16b, v2.16b, v5.16b",
"mov w14, #0x7b90",
"movk w14, #0xa7, lsl #16",
@@ -21827,7 +21827,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q6, [x28, #3552]",
"ldr q6, [x28, #3584]",
"eor v2.16b, v2.16b, v6.16b",
"mov w15, #0x7b80",
"movk w15, #0xa7, lsl #16",
@@ -21955,7 +21955,7 @@
"fmov s7, s0",
"str s7, [x8, #64]",
"strb wzr, [x28, #1049]",
"ldr q7, [x28, #3552]",
"ldr q7, [x28, #3584]",
"eor v7.16b, v6.16b, v7.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v7.16b",
@@ -21979,7 +21979,7 @@
"fmov s7, s0",
"str s7, [x8, #68]",
"strb wzr, [x28, #1049]",
"ldr q7, [x28, #3552]",
"ldr q7, [x28, #3584]",
"eor v2.16b, v2.16b, v7.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v5.16b",
@@ -22005,7 +22005,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q5, [x28, #3552]",
"ldr q5, [x28, #3584]",
"eor v5.16b, v2.16b, v5.16b",
"ldr d7, [x15]",
"str x30, [sp, #-16]!",
@@ -10858,7 +10858,7 @@
"add w22, w20, #0x7 (7)",
"and w22, w22, #0x7",
"add x23, x28, x22, lsl #4",
"ldr q4, [x28, #3552]",
"ldr q4, [x28, #3584]",
"eor v3.16b, v3.16b, v4.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v3.16b",
@@ -10903,7 +10903,7 @@
"add w22, w22, #0x7 (7)",
"and w22, w22, #0x7",
"add x12, x28, x22, lsl #4",
"ldr q5, [x28, #3552]",
"ldr q5, [x28, #3584]",
"eor v4.16b, v4.16b, v5.16b",
"ldur s5, [x5, #-4]",
"str x30, [sp, #-16]!",
@@ -11028,7 +11028,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v5.16b, v0.16b",
"ldr q6, [x28, #3552]",
"ldr q6, [x28, #3584]",
"eor v5.16b, v5.16b, v6.16b",
"ldr s6, [x5, #4]",
"str x30, [sp, #-16]!",
@@ -12174,7 +12174,7 @@
"ldr x30, [sp], #16",
"mov v4.16b, v0.16b",
"ldr w9, [x8, #48]",
"ldr q5, [x28, #3552]",
"ldr q5, [x28, #3584]",
"eor v4.16b, v4.16b, v5.16b",
"ldr s5, [x9, #12]",
"str x30, [sp, #-16]!",
@@ -12302,7 +12302,7 @@
"ldr x30, [sp], #16",
"mov v5.16b, v0.16b",
"ldr w9, [x8, #48]",
"ldr q6, [x28, #3552]",
"ldr q6, [x28, #3584]",
"eor v5.16b, v5.16b, v6.16b",
"ldr s6, [x9, #4]",
"str x30, [sp, #-16]!",
@@ -14021,7 +14021,7 @@
"add w22, w20, #0x7 (7)",
"and w22, w22, #0x7",
"add x23, x28, x22, lsl #4",
"ldr q4, [x28, #3552]",
"ldr q4, [x28, #3584]",
"eor v3.16b, v3.16b, v4.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v3.16b",
@@ -22326,7 +22326,7 @@
"add w22, w22, #0x7 (7)",
"and w22, w22, #0x7",
"add x13, x28, x22, lsl #4",
"ldr q6, [x28, #3552]",
"ldr q6, [x28, #3584]",
"eor v5.16b, v5.16b, v6.16b",
"add w14, w4, w10, lsl #2",
"ldur s6, [x14, #-4]",
@@ -22927,7 +22927,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v5.16b, v0.16b",
"ldr q6, [x28, #3552]",
"ldr q6, [x28, #3584]",
"eor v5.16b, v5.16b, v6.16b",
"add w15, w4, w10, lsl #2",
"ldr s6, [x15, #4]",
@@ -23397,7 +23397,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v6.16b, v0.16b",
"ldr q7, [x28, #3552]",
"ldr q7, [x28, #3584]",
"eor v6.16b, v6.16b, v7.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v5.16b",
@@ -23485,7 +23485,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v5.16b, v0.16b",
"ldr q6, [x28, #3552]",
"ldr q6, [x28, #3584]",
"eor v5.16b, v5.16b, v6.16b",
"add w15, w4, w10, lsl #2",
"ldr s6, [x15, #12]",
@@ -25586,7 +25586,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v6.16b, v0.16b",
"ldr q7, [x28, #3552]",
"ldr q7, [x28, #3584]",
"eor v6.16b, v6.16b, v7.16b",
"str x30, [sp, #-16]!",
"mov v0.16b, v5.16b",
+31 -28
View File
@@ -2468,7 +2468,7 @@
"ldrb w20, [x28, #1051]",
"add x20, x28, x20, lsl #4",
"ldr q2, [x20, #1056]",
"ldr q3, [x28, #3552]",
"ldr q3, [x28, #3584]",
"eor v2.16b, v2.16b, v3.16b",
"str q2, [x20, #1056]"
]
@@ -2482,7 +2482,7 @@
"ldrb w20, [x28, #1051]",
"add x20, x28, x20, lsl #4",
"ldr q2, [x20, #1056]",
"ldr q3, [x28, #3552]",
"ldr q3, [x28, #3584]",
"bic v2.16b, v2.16b, v3.16b",
"str q2, [x20, #1056]"
]
@@ -2548,7 +2548,7 @@
"0xd9 11b 0xe8 /5"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3328]",
"ldr q2, [x28, #3360]",
"ldrb w20, [x28, #1051]",
"add w20, w20, #0x7 (7)",
"and w20, w20, #0x7",
@@ -2568,7 +2568,7 @@
"0xd9 11b 0xe9 /5"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3344]",
"ldr q2, [x28, #3376]",
"ldrb w20, [x28, #1051]",
"add w20, w20, #0x7 (7)",
"and w20, w20, #0x7",
@@ -2588,7 +2588,7 @@
"0xd9 11b 0xea /5"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3360]",
"ldr q2, [x28, #3392]",
"ldrb w20, [x28, #1051]",
"add w20, w20, #0x7 (7)",
"and w20, w20, #0x7",
@@ -2608,7 +2608,7 @@
"0xd9 11b 0xeb /5"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3376]",
"ldr q2, [x28, #3408]",
"ldrb w20, [x28, #1051]",
"add w20, w20, #0x7 (7)",
"and w20, w20, #0x7",
@@ -2628,7 +2628,7 @@
"0xd9 11b 0xec /5"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3392]",
"ldr q2, [x28, #3424]",
"ldrb w20, [x28, #1051]",
"add w20, w20, #0x7 (7)",
"and w20, w20, #0x7",
@@ -2648,7 +2648,7 @@
"0xd9 11b 0xed /5"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3408]",
"ldr q2, [x28, #3440]",
"ldrb w20, [x28, #1051]",
"add w20, w20, #0x7 (7)",
"and w20, w20, #0x7",
@@ -2742,7 +2742,7 @@
"blr x0",
"ldr x30, [sp], #16",
"mov v2.16b, v0.16b",
"ldr q3, [x28, #3328]",
"ldr q3, [x28, #3360]",
"add w20, w20, #0x7 (7)",
"and w20, w20, #0x7",
"strb wzr, [x28, #1050]",
@@ -2900,7 +2900,7 @@
"0xd9 11b 0xf9 /7"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3328]",
"ldr q2, [x28, #3360]",
"ldrb w20, [x28, #1051]",
"add x21, x28, x20, lsl #4",
"ldr q3, [x21, #1056]",
@@ -9959,7 +9959,7 @@
]
},
"fisttp word [rax]": {
"ExpectedInstructionCount": 30,
"ExpectedInstructionCount": 31,
"Comment": [
"0xdf !11b /1"
],
@@ -9968,14 +9968,15 @@
"add x21, x28, x20, lsl #4",
"ldr q2, [x21, #1056]",
"mov x21, v2.d[1]",
"mov w22, #0x7fff",
"and x21, x21, #0x7fff",
"mrs x22, nzcv",
"tst x21, #0x7fff",
"cset x23, eq",
"mrs x23, nzcv",
"cmp x21, x22",
"cset x22, eq",
"mov w24, #0x400e",
"cmp x21, x24",
"cset x21, hs",
"orr x21, x23, x21",
"orr x21, x22, x21",
"strb w21, [x28, #1040]",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -9987,7 +9988,7 @@
"strh w21, [x4]",
"add w21, w20, #0x1 (1)",
"and w21, w21, #0x7",
"msr nzcv, x22",
"msr nzcv, x23",
"strb w21, [x28, #1051]",
"ldrb w21, [x28, #1202]",
"mov w22, #0x1",
@@ -9997,7 +9998,7 @@
]
},
"fist word [rax]": {
"ExpectedInstructionCount": 22,
"ExpectedInstructionCount": 23,
"Comment": [
"0xdf !11b /2"
],
@@ -10006,14 +10007,15 @@
"add x20, x28, x20, lsl #4",
"ldr q2, [x20, #1056]",
"mov x20, v2.d[1]",
"mov w21, #0x7fff",
"and x20, x20, #0x7fff",
"mrs x21, nzcv",
"tst x20, #0x7fff",
"cset x22, eq",
"mrs x22, nzcv",
"cmp x20, x21",
"cset x21, eq",
"mov w23, #0x400e",
"cmp x20, x23",
"cset x20, hs",
"orr x20, x22, x20",
"orr x20, x21, x20",
"strb w20, [x28, #1040]",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -10023,11 +10025,11 @@
"ldr x30, [sp], #16",
"mov w20, w0",
"strh w20, [x4]",
"msr nzcv, x21"
"msr nzcv, x22"
]
},
"fistp word [rax]": {
"ExpectedInstructionCount": 30,
"ExpectedInstructionCount": 31,
"Comment": [
"0xdf !11b /3"
],
@@ -10036,14 +10038,15 @@
"add x21, x28, x20, lsl #4",
"ldr q2, [x21, #1056]",
"mov x21, v2.d[1]",
"mov w22, #0x7fff",
"and x21, x21, #0x7fff",
"mrs x22, nzcv",
"tst x21, #0x7fff",
"cset x23, eq",
"mrs x23, nzcv",
"cmp x21, x22",
"cset x22, eq",
"mov w24, #0x400e",
"cmp x21, x24",
"cset x21, hs",
"orr x21, x23, x21",
"orr x21, x22, x21",
"strb w21, [x28, #1040]",
"str x30, [sp, #-16]!",
"mov v0.16b, v2.16b",
@@ -10055,7 +10058,7 @@
"strh w21, [x4]",
"add w21, w20, #0x1 (1)",
"and w21, w21, #0x7",
"msr nzcv, x22",
"msr nzcv, x23",
"strb w21, [x28, #1051]",
"ldrb w21, [x28, #1202]",
"mov w22, #0x1",
+30 -25
View File
@@ -2142,7 +2142,7 @@
]
},
"f2xm1": {
"ExpectedInstructionCount": 11,
"ExpectedInstructionCount": 10,
"Comment": [
"0xd9 11b 0xf0 /6"
],
@@ -2150,10 +2150,9 @@
"ldrb w20, [x28, #1051]",
"add x20, x28, x20, lsl #4",
"ldr d2, [x20, #1056]",
"str x30, [sp, #-16]!",
"fmov d0, d2",
"ldr x0, [x28, #2248]",
"ldr x3, [x28, #2256]",
"ldr x0, [x28, #3008]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
"fmov d2, d0",
@@ -2161,7 +2160,7 @@
]
},
"fyl2x": {
"ExpectedInstructionCount": 17,
"ExpectedInstructionCount": 16,
"Comment": [
"0xd9 11b 0xf1 /6"
],
@@ -2173,11 +2172,10 @@
"ldr d2, [x22, #1056]",
"add x20, x28, x20, lsl #4",
"ldr d3, [x20, #1056]",
"str x30, [sp, #-16]!",
"fmov d0, d3",
"fmov d1, d2",
"ldr x0, [x28, #2264]",
"ldr x3, [x28, #2272]",
"ldr x0, [x28, #3032]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
"fmov d2, d0",
@@ -2217,7 +2215,7 @@
]
},
"fpatan": {
"ExpectedInstructionCount": 17,
"ExpectedInstructionCount": 16,
"Comment": [
"0xd9 11b 0xf3 /6"
],
@@ -2229,11 +2227,10 @@
"and w20, w20, #0x7",
"add x21, x28, x20, lsl #4",
"ldr d3, [x21, #1056]",
"str x30, [sp, #-16]!",
"fmov d0, d3",
"fmov d1, d2",
"ldr x0, [x28, #2232]",
"ldr x3, [x28, #2240]",
"ldr x0, [x28, #3024]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
"fmov d2, d0",
@@ -2242,7 +2239,7 @@
]
},
"fxtract": {
"ExpectedInstructionCount": 30,
"ExpectedInstructionCount": 40,
"Comment": [
"0xd9 11b 0xf4 /6"
],
@@ -2253,13 +2250,23 @@
"mov x22, v2.d[0]",
"mov x23, #0xfff0000000000000",
"fmov d3, x23",
"mov x23, #0x7ff0000000000000",
"fmov d4, x23",
"ubfx x23, x22, #52, #11",
"sub x23, x23, #0x3ff (1023)",
"scvtf d4, x23",
"scvtf d5, x23",
"and x23, x22, #0x800fffffffffffff",
"orr x23, x23, #0x3ff0000000000000",
"fmov d5, x23",
"fmov d6, x23",
"mrs x23, nzcv",
"and x24, x22, #0xfffffffffffff",
"mov x30, #0xffffffffffffffff",
"tst x24, x30",
"fcsel d4, d4, d2, eq",
"ubfx x24, x22, #52, #11",
"cmp x24, #0x7ff (2047)",
"fcsel d4, d4, d5, eq",
"fcsel d5, d2, d6, eq",
"tst x22, #0x7fffffffffffffff",
"fcsel d2, d2, d5, eq",
"fcsel d3, d3, d4, eq",
@@ -2354,7 +2361,7 @@
]
},
"fyl2xp1": {
"ExpectedInstructionCount": 21,
"ExpectedInstructionCount": 20,
"Comment": [
"0xd9 11b 0xf9 /7"
],
@@ -2369,11 +2376,10 @@
"and w20, w20, #0x7",
"add x22, x28, x20, lsl #4",
"ldr d3, [x22, #1056]",
"str x30, [sp, #-16]!",
"fmov d0, d2",
"fmov d1, d3",
"ldr x0, [x28, #2264]",
"ldr x3, [x28, #2272]",
"ldr x0, [x28, #3032]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
"fmov d3, d0",
@@ -2444,7 +2450,7 @@
]
},
"fscale": {
"ExpectedInstructionCount": 16,
"ExpectedInstructionCount": 15,
"Comment": [
"0xd9 11b 0xfd /7"
],
@@ -2456,11 +2462,10 @@
"ldr d2, [x21, #1056]",
"add x20, x28, x20, lsl #4",
"ldr d3, [x20, #1056]",
"str x30, [sp, #-16]!",
"fmov d0, d3",
"fmov d1, d2",
"ldr x0, [x28, #2312]",
"ldr x3, [x28, #2320]",
"ldr x0, [x28, #3016]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
"fmov d2, d0",
@@ -5340,8 +5345,8 @@
"ldrb w20, [x28, #1051]",
"add x21, x28, x20, lsl #4",
"ldr d2, [x21, #1056]",
"fcvtzs x21, d2",
"str x21, [x4]",
"fcvtzs v2.2d, v2.2d",
"str d2, [x4]",
"add w21, w20, #0x1 (1)",
"and w21, w21, #0x7",
"strb w21, [x28, #1051]",
+1 -1
View File
@@ -685,7 +685,7 @@
"0x66 0x0f 0x38 0x41"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3008]",
"ldr q2, [x28, #3040]",
"zip1 v3.8h, v2.8h, v17.8h",
"zip2 v2.8h, v2.8h, v17.8h",
"umin v2.4s, v3.4s, v2.4s",
+6 -6
View File
@@ -327,7 +327,7 @@
"0x66 0x0f 0x3a 0x0c"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3200]",
"ldr q2, [x28, #3232]",
"tbx v16.16b, {v17.16b}, v2.16b"
]
},
@@ -337,7 +337,7 @@
"0x66 0x0f 0x3a 0x0c"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3216]",
"ldr q2, [x28, #3248]",
"tbx v16.16b, {v17.16b}, v2.16b"
]
},
@@ -356,7 +356,7 @@
"0x66 0x0f 0x3a 0x0c"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3232]",
"ldr q2, [x28, #3264]",
"tbx v16.16b, {v17.16b}, v2.16b"
]
},
@@ -376,7 +376,7 @@
"0x66 0x0f 0x3a 0x0c"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3248]",
"ldr q2, [x28, #3280]",
"tbx v16.16b, {v17.16b}, v2.16b"
]
},
@@ -395,7 +395,7 @@
"0x66 0x0f 0x3a 0x0c"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3264]",
"ldr q2, [x28, #3296]",
"tbx v16.16b, {v17.16b}, v2.16b"
]
},
@@ -405,7 +405,7 @@
"0x66 0x0f 0x3a 0x0c"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3280]",
"ldr q2, [x28, #3312]",
"tbx v16.16b, {v17.16b}, v2.16b"
]
},
@@ -1826,14 +1826,6 @@
"strh w20, [x8, #-2]!"
]
},
"push dword -1": {
"ExpectedInstructionCount": 2,
"Comment": "0x6a",
"ExpectedArm64ASM": [
"mov x20, #0xffffffffffffffff",
"str x20, [x8, #-8]!"
]
},
"push qword -1": {
"ExpectedInstructionCount": 2,
"Comment": "0x6a",
+13 -15
View File
@@ -651,7 +651,7 @@
"Comment": "0x0f 0x50",
"ExpectedArm64ASM": [
"ushr v2.4s, v16.4s, #31",
"ldr q3, [x28, #3168]",
"ldr q3, [x28, #3200]",
"ushl v2.4s, v2.4s, v3.4s",
"addv s2, v2.4s",
"mov w4, v2.s[0]"
@@ -662,7 +662,7 @@
"Comment": "0x0f 0x50",
"ExpectedArm64ASM": [
"ushr v2.4s, v16.4s, #31",
"ldr q3, [x28, #3168]",
"ldr q3, [x28, #3200]",
"ushl v2.4s, v2.4s, v3.4s",
"addv s2, v2.4s",
"mov w4, v2.s[0]"
@@ -793,8 +793,8 @@
"ExpectedInstructionCount": 2,
"Comment": "0x0f 0x5f",
"ExpectedArm64ASM": [
"fcmgt v0.4s, v17.4s, v16.4s",
"bit v16.16b, v17.16b, v0.16b"
"fcmgt v0.4s, v16.4s, v17.4s",
"bif v16.16b, v17.16b, v0.16b"
]
},
"punpcklbw mm0, mm1": {
@@ -1153,32 +1153,30 @@
]
},
"pshufw mm0, mm1, 1": {
"ExpectedInstructionCount": 9,
"ExpectedInstructionCount": 8,
"Comment": "0x0f 0x70",
"ExpectedArm64ASM": [
"strb wzr, [x28, #1051]",
"mov w20, #0xffff",
"strb w20, [x28, #1202]",
"ldr d2, [x28, #1072]",
"ldr x0, [x28, #2672]",
"ldr d3, [x0, #16]",
"tbl v2.8b, {v2.16b}, v3.8b",
"str d2, [x28, #1056]",
"dup v3.4h, v2.h[0]",
"mov v3.h[0], v2.h[1]",
"str d3, [x28, #1056]",
"strh w20, [x28, #1064]"
]
},
"pshufw mm0, [rax], 1": {
"ExpectedInstructionCount": 9,
"ExpectedInstructionCount": 8,
"Comment": "0x0f 0x70",
"ExpectedArm64ASM": [
"ldr d2, [x4]",
"ldr x0, [x28, #2672]",
"ldr d3, [x0, #16]",
"tbl v2.8b, {v2.16b}, v3.8b",
"dup v3.4h, v2.h[0]",
"mov v3.h[0], v2.h[1]",
"strb wzr, [x28, #1051]",
"mov w20, #0xffff",
"strb w20, [x28, #1202]",
"str d2, [x28, #1056]",
"str d3, [x28, #1056]",
"strh w20, [x28, #1064]"
]
},
@@ -3697,7 +3695,7 @@
"mov w20, #0xffff",
"strb w20, [x28, #1202]",
"ldr d2, [x28, #1056]",
"ldr d3, [x28, #3296]",
"ldr d3, [x28, #3328]",
"cmlt v2.16b, v2.16b, #0",
"and v2.8b, v2.8b, v3.8b",
"addp v2.16b, v2.16b, v2.16b",
@@ -266,8 +266,8 @@
"ExpectedInstructionCount": 2,
"Comment": "0x66 0x0f 0x5f",
"ExpectedArm64ASM": [
"fcmgt v0.2d, v17.2d, v16.2d",
"bit v16.16b, v17.16b, v0.16b"
"fcmgt v0.2d, v16.2d, v17.2d",
"bif v16.16b, v17.16b, v0.16b"
]
},
"punpcklbw xmm0, xmm1": {
@@ -1259,7 +1259,7 @@
"ExpectedInstructionCount": 3,
"Comment": "0x66 0x0f 0xd0",
"ExpectedArm64ASM": [
"ldr q2, [x28, #3072]",
"ldr q2, [x28, #3104]",
"eor v2.16b, v17.16b, v2.16b",
"fadd v16.2d, v16.2d, v2.2d"
]
@@ -1315,7 +1315,7 @@
"ExpectedInstructionCount": 7,
"Comment": "0x66 0x0f 0xd7",
"ExpectedArm64ASM": [
"ldr q2, [x28, #3296]",
"ldr q2, [x28, #3328]",
"cmlt v3.16b, v16.16b, #0",
"and v2.16b, v3.16b, v2.16b",
"addp v2.16b, v2.16b, v2.16b",
+10 -10
View File
@@ -118,7 +118,7 @@
"ExpectedArm64ASM": [
"fcvtzs w20, s16",
"mov w21, #0x80000000",
"ldr s2, [x28, #3424]",
"ldr s2, [x28, #3456]",
"mrs x22, nzcv",
"fcmp s2, s16",
"csel w4, w20, w21, gt",
@@ -132,7 +132,7 @@
"ldr s2, [x6]",
"fcvtzs w20, s2",
"mov w21, #0x80000000",
"ldr s3, [x28, #3424]",
"ldr s3, [x28, #3456]",
"mrs x22, nzcv",
"fcmp s3, s2",
"csel w4, w20, w21, gt",
@@ -145,7 +145,7 @@
"ExpectedArm64ASM": [
"fcvtzs x20, s16",
"mov x21, #0x8000000000000000",
"ldr s2, [x28, #3456]",
"ldr s2, [x28, #3488]",
"mrs x22, nzcv",
"fcmp s2, s16",
"csel x4, x20, x21, gt",
@@ -159,7 +159,7 @@
"ldr s2, [x6]",
"fcvtzs x20, s2",
"mov x21, #0x8000000000000000",
"ldr s3, [x28, #3456]",
"ldr s3, [x28, #3488]",
"mrs x22, nzcv",
"fcmp s3, s2",
"csel x4, x20, x21, gt",
@@ -173,7 +173,7 @@
"frinti s2, s16",
"fcvtzs w20, s2",
"mov w21, #0x80000000",
"ldr s3, [x28, #3424]",
"ldr s3, [x28, #3456]",
"mrs x22, nzcv",
"fcmp s3, s2",
"csel w4, w20, w21, gt",
@@ -188,7 +188,7 @@
"frinti s2, s2",
"fcvtzs w20, s2",
"mov w21, #0x80000000",
"ldr s3, [x28, #3424]",
"ldr s3, [x28, #3456]",
"mrs x22, nzcv",
"fcmp s3, s2",
"csel w4, w20, w21, gt",
@@ -202,7 +202,7 @@
"frinti s2, s16",
"fcvtzs x20, s2",
"mov x21, #0x8000000000000000",
"ldr s3, [x28, #3456]",
"ldr s3, [x28, #3488]",
"mrs x22, nzcv",
"fcmp s3, s2",
"csel x4, x20, x21, gt",
@@ -217,7 +217,7 @@
"frinti s2, s2",
"fcvtzs x20, s2",
"mov x21, #0x8000000000000000",
"ldr s3, [x28, #3456]",
"ldr s3, [x28, #3488]",
"mrs x22, nzcv",
"fcmp s3, s2",
"csel x4, x20, x21, gt",
@@ -296,8 +296,8 @@
"ExpectedInstructionCount": 6,
"Comment": "0xf3 0x0f 0x5b",
"ExpectedArm64ASM": [
"ldr q2, [x28, #3520]",
"ldr q3, [x28, #3424]",
"ldr q2, [x28, #3552]",
"ldr q3, [x28, #3456]",
"fcvtzs v4.4s, v17.4s",
"fcmgt v3.4s, v3.4s, v17.4s",
"mov v16.16b, v3.16b",
@@ -503,7 +503,7 @@
"ExpectedInstructionCount": 3,
"Comment": "0xf2 0x0f 0xd0",
"ExpectedArm64ASM": [
"ldr q2, [x28, #3040]",
"ldr q2, [x28, #3072]",
"eor v2.16b, v17.16b, v2.16b",
"fadd v16.4s, v16.4s, v2.4s"
]
+31 -29
View File
@@ -3271,7 +3271,7 @@
"ExpectedArm64ASM": [
"fcvtzs w20, s16",
"mov w21, #0x80000000",
"ldr s2, [x28, #3424]",
"ldr s2, [x28, #3456]",
"mrs x22, nzcv",
"fcmp s2, s16",
"csel w4, w20, w21, gt",
@@ -3286,7 +3286,7 @@
"ExpectedArm64ASM": [
"fcvtzs x20, s16",
"mov x21, #0x8000000000000000",
"ldr s2, [x28, #3456]",
"ldr s2, [x28, #3488]",
"mrs x22, nzcv",
"fcmp s2, s16",
"csel x4, x20, x21, gt",
@@ -3301,7 +3301,7 @@
"ExpectedArm64ASM": [
"fcvtzs w20, d16",
"mov w21, #0x80000000",
"ldr d2, [x28, #3472]",
"ldr d2, [x28, #3504]",
"mrs x22, nzcv",
"fcmp d2, d16",
"csel w4, w20, w21, gt",
@@ -3316,7 +3316,7 @@
"ExpectedArm64ASM": [
"fcvtzs x20, d16",
"mov x21, #0x8000000000000000",
"ldr d2, [x28, #3504]",
"ldr d2, [x28, #3536]",
"mrs x22, nzcv",
"fcmp d2, d16",
"csel x4, x20, x21, gt",
@@ -3332,7 +3332,7 @@
"frinti s2, s16",
"fcvtzs w20, s2",
"mov w21, #0x80000000",
"ldr s3, [x28, #3424]",
"ldr s3, [x28, #3456]",
"mrs x22, nzcv",
"fcmp s3, s2",
"csel w4, w20, w21, gt",
@@ -3348,7 +3348,7 @@
"frinti s2, s16",
"fcvtzs x20, s2",
"mov x21, #0x8000000000000000",
"ldr s3, [x28, #3456]",
"ldr s3, [x28, #3488]",
"mrs x22, nzcv",
"fcmp s3, s2",
"csel x4, x20, x21, gt",
@@ -3364,7 +3364,7 @@
"frinti d2, d16",
"fcvtzs w20, d2",
"mov w21, #0x80000000",
"ldr d3, [x28, #3472]",
"ldr d3, [x28, #3504]",
"mrs x22, nzcv",
"fcmp d3, d2",
"csel w4, w20, w21, gt",
@@ -3380,7 +3380,7 @@
"frinti d2, d16",
"fcvtzs x20, d2",
"mov x21, #0x8000000000000000",
"ldr d3, [x28, #3504]",
"ldr d3, [x28, #3536]",
"mrs x22, nzcv",
"fcmp d3, d2",
"csel x4, x20, x21, gt",
@@ -3643,8 +3643,8 @@
],
"ExpectedArm64ASM": [
"frinti v2.4s, v17.4s",
"ldr q3, [x28, #3520]",
"ldr q4, [x28, #3424]",
"ldr q3, [x28, #3552]",
"ldr q4, [x28, #3456]",
"fcvtzs v5.4s, v2.4s",
"fcmgt v2.4s, v4.4s, v2.4s",
"mov v16.16b, v2.16b",
@@ -3678,8 +3678,8 @@
"Map 1 0b10 0x5b 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3520]",
"ldr q3, [x28, #3424]",
"ldr q2, [x28, #3552]",
"ldr q3, [x28, #3456]",
"fcvtzs v4.4s, v17.4s",
"fcmgt v3.4s, v3.4s, v17.4s",
"mov v16.16b, v3.16b",
@@ -3950,18 +3950,19 @@
"Map 1 0b00 0x5f 128-bit"
],
"ExpectedArm64ASM": [
"fcmgt v0.4s, v18.4s, v17.4s",
"fcmgt v0.4s, v17.4s, v18.4s",
"mov v16.16b, v17.16b",
"bit v16.16b, v18.16b, v0.16b"
"bif v16.16b, v18.16b, v0.16b"
]
},
"vmaxps ymm0, ymm1, ymm2": {
"ExpectedInstructionCount": 4,
"ExpectedInstructionCount": 5,
"Comment": [
"Map 1 0b00 0x5f 256-bit"
],
"ExpectedArm64ASM": [
"fcmgt p0.s, p7/z, z18.s, z17.s",
"fcmgt p0.s, p7/z, z17.s, z18.s",
"not p0.b, p7/z, p0.b",
"mov z0.d, z17.d",
"mov z0.s, p0/m, z18.s",
"mov z16.d, z0.d"
@@ -3973,18 +3974,19 @@
"Map 1 0b01 0x5f 128-bit"
],
"ExpectedArm64ASM": [
"fcmgt v0.2d, v18.2d, v17.2d",
"fcmgt v0.2d, v17.2d, v18.2d",
"mov v16.16b, v17.16b",
"bit v16.16b, v18.16b, v0.16b"
"bif v16.16b, v18.16b, v0.16b"
]
},
"vmaxpd ymm0, ymm1, ymm2": {
"ExpectedInstructionCount": 4,
"ExpectedInstructionCount": 5,
"Comment": [
"Map 1 0b01 0x5f 256-bit"
],
"ExpectedArm64ASM": [
"fcmgt p0.d, p7/z, z18.d, z17.d",
"fcmgt p0.d, p7/z, z17.d, z18.d",
"not p0.b, p7/z, p0.b",
"mov z0.d, z17.d",
"mov z0.d, p0/m, z18.d",
"mov z16.d, z0.d"
@@ -4427,7 +4429,7 @@
"Map 1 0b01 0xd0 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3072]",
"ldr q2, [x28, #3104]",
"eor v2.16b, v18.16b, v2.16b",
"fadd v16.2d, v17.2d, v2.2d"
]
@@ -4450,7 +4452,7 @@
"Map 1 0b11 0xd0 128-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3040]",
"ldr q2, [x28, #3072]",
"eor v2.16b, v18.16b, v2.16b",
"fadd v16.4s, v17.4s, v2.4s"
]
@@ -4587,7 +4589,7 @@
"Map 1 0b01 0xd7 256-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3296]",
"ldr q2, [x28, #3328]",
"cmlt v3.16b, v16.16b, #0",
"and v2.16b, v3.16b, v2.16b",
"addp v2.16b, v2.16b, v2.16b",
@@ -4979,8 +4981,8 @@
"Map 1 0b01 0xe6 128-bit"
],
"ExpectedArm64ASM": [
"ldr d2, [x28, #3520]",
"ldr q3, [x28, #3472]",
"ldr d2, [x28, #3552]",
"ldr q3, [x28, #3504]",
"fcvtzs z4.s, p6/m, z17.d",
"uzp1 z4.s, z4.s, z4.s",
"mov v4.8b, v4.8b",
@@ -4996,7 +4998,7 @@
"Map 1 0b01 0xe6 256-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3520]",
"ldr q2, [x28, #3552]",
"ldr x0, [x28, #2592]",
"ld1b {z3.b}, p7/z, [x0]",
"fcvtzs z4.s, p7/m, z17.d",
@@ -5040,8 +5042,8 @@
],
"ExpectedArm64ASM": [
"frinti v2.2d, v17.2d",
"ldr d3, [x28, #3520]",
"ldr q4, [x28, #3472]",
"ldr d3, [x28, #3552]",
"ldr q4, [x28, #3504]",
"fcvtzs z5.s, p6/m, z2.d",
"uzp1 z5.s, z5.s, z5.s",
"mov v5.8b, v5.8b",
@@ -5058,7 +5060,7 @@
],
"ExpectedArm64ASM": [
"frinti z2.d, p7/m, z17.d",
"ldr q3, [x28, #3520]",
"ldr q3, [x28, #3552]",
"ldr x0, [x28, #2592]",
"ld1b {z4.b}, p7/z, [x0]",
"fcvtzs z5.s, p7/m, z2.d",
@@ -173,7 +173,7 @@
"Map 1 0b01 0xe6 256-bit"
],
"ExpectedArm64ASM": [
"ldr q2, [x28, #3520]",
"ldr q2, [x28, #3552]",
"ldr x0, [x28, #2592]",
"ld1b {z3.b}, p7/z, [x0]",
"fcvtzs z4.s, p7/m, z17.d",
@@ -208,7 +208,7 @@
],
"ExpectedArm64ASM": [
"frinti z2.d, p7/m, z17.d",
"ldr q3, [x28, #3520]",
"ldr q3, [x28, #3552]",
"ldr x0, [x28, #2592]",
"ld1b {z4.b}, p7/z, [x0]",
"fcvtzs z5.s, p7/m, z2.d",
Loaded 100 of 104 files, more files were not shown because too many files have changed in this diff. Show more