mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-08 01:00:15 +02:00
Compare commits
375
Commits
FEX-2309.1
...
FEX-2310
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee0c1457d8 | ||
|
|
3413eb3d98 | ||
|
|
2e0753a244 | ||
|
|
8a51bb7a61 | ||
|
|
ee6debe8fd | ||
|
|
3ba1c7912c | ||
|
|
a408afaeb0 | ||
|
|
fba7c4bedc | ||
|
|
c52753e9c8 | ||
|
|
e39634d314 | ||
|
|
507cf82dad | ||
|
|
48fa4f1121 | ||
|
|
e06d609bf0 | ||
|
|
0a09e04e33 | ||
|
|
a1a709f948 | ||
|
|
5925eef213 | ||
|
|
df369bd6a0 | ||
|
|
978489fce1 | ||
|
|
d5a4d9b17f | ||
|
|
9933ef07ea | ||
|
|
6964e65660 | ||
|
|
11db8e7506 | ||
|
|
b6b5e93dbb | ||
|
|
935b3a313a | ||
|
|
fe681ab335 | ||
|
|
2d9e816ff5 | ||
|
|
b04b0549a9 | ||
|
|
2b472cb962 | ||
|
|
7f931b5623 | ||
|
|
070fa9f924 | ||
|
|
371bf50c76 | ||
|
|
d65d29903b | ||
|
|
7791e0090d | ||
|
|
02da6d6ce7 | ||
|
|
a478cbb694 | ||
|
|
3a25dd6d2b | ||
|
|
9c25db83d9 | ||
|
|
7346476546 | ||
|
|
c42b581378 | ||
|
|
ccfd770d9d | ||
|
|
d4a623a3fb | ||
|
|
c09c25005e | ||
|
|
90570fd5f4 | ||
|
|
ab4642af38 | ||
|
|
d94e5ce7f4 | ||
|
|
dad7086fd0 | ||
|
|
a21def7d74 | ||
|
|
0d8d5444a4 | ||
|
|
eedfad5036 | ||
|
|
85da0f0640 | ||
|
|
9a01b440e3 | ||
|
|
228ee7fa47 | ||
|
|
98789a8039 | ||
|
|
14398742c3 | ||
|
|
5a7e3192da | ||
|
|
6b4ff4ae81 | ||
|
|
d1d3de80d1 | ||
|
|
2e32e1367d | ||
|
|
711583aa76 | ||
|
|
3efac9646c | ||
|
|
095a362046 | ||
|
|
3bb64c64e3 | ||
|
|
a4de164944 | ||
|
|
45a645fbbc | ||
|
|
92211bf8c6 | ||
|
|
728d3f8ac7 | ||
|
|
ca87d8688d | ||
|
|
e32601f49d | ||
|
|
f4dd456c80 | ||
|
|
7b22dbfe24 | ||
|
|
7a06cc9727 | ||
|
|
8b3881b5db | ||
|
|
76d4637d9c | ||
|
|
0d12cce74f | ||
|
|
04592af609 | ||
|
|
d8366c04dc | ||
|
|
533f35934c | ||
|
|
35bb7cc801 | ||
|
|
5facb21d30 | ||
|
|
adead832a5 | ||
|
|
5eed24a242 | ||
|
|
7907f70ed2 | ||
|
|
7141332f6f | ||
|
|
234e029391 | ||
|
|
19a7b514e6 | ||
|
|
220761a0e8 | ||
|
|
cbd4daddff | ||
|
|
c8519b0b87 | ||
|
|
68d32ad70d | ||
|
|
62890f148f | ||
|
|
1f02a6da34 | ||
|
|
86063411dc | ||
|
|
9968e6431f | ||
|
|
ff24f64b2a | ||
|
|
e9a7ef2534 | ||
|
|
842c57e221 | ||
|
|
93aeb157b4 | ||
|
|
02ff9f200c | ||
|
|
f65b40f298 | ||
|
|
c38beff826 | ||
|
|
94c22b2269 | ||
|
|
bee97309f6 | ||
|
|
331941dec6 | ||
|
|
8798e0cba0 | ||
|
|
c5fc03dac4 | ||
|
|
e63871ed2e | ||
|
|
ea8b7633eb | ||
|
|
e795ec683d | ||
|
|
6dc5c0d3be | ||
|
|
eb5e0be569 | ||
|
|
be3ff804a6 | ||
|
|
9ab2967d71 | ||
|
|
d01b457727 | ||
|
|
4e9a114858 | ||
|
|
72d092e951 | ||
|
|
da3e172857 | ||
|
|
28fa0bda31 | ||
|
|
1f2a3cfa8b | ||
|
|
571b0fe47e | ||
|
|
86ad35c418 | ||
|
|
0b27029c3f | ||
|
|
223a6562ff | ||
|
|
b1231c24ef | ||
|
|
699aa85c4b | ||
|
|
2d65a3677b | ||
|
|
2a2619c0f5 | ||
|
|
797c890ff6 | ||
|
|
879b41c184 | ||
|
|
0fbf403787 | ||
|
|
04cf418452 | ||
|
|
057a7c6ee8 | ||
|
|
3d6955592b | ||
|
|
f57aee0a62 | ||
|
|
c978fdd12f | ||
|
|
19713bd20a | ||
|
|
22b1fea96d | ||
|
|
be4fcaf65c | ||
|
|
2add8a7751 | ||
|
|
9612133088 | ||
|
|
f46fd42977 | ||
|
|
51f8c83c76 | ||
|
|
d641d3f61e | ||
|
|
02ae59a348 | ||
|
|
64df9e31c6 | ||
|
|
d32bb993a8 | ||
|
|
b5cc9a12f2 | ||
|
|
65b6df9dbb | ||
|
|
31564354b1 | ||
|
|
fea72ce19c | ||
|
|
2b7e1d10ec | ||
|
|
5444810d64 | ||
|
|
4a2ceabfdd | ||
|
|
1a4d1d820b | ||
|
|
0ae4bbb9c5 | ||
|
|
7d99eb05c6 | ||
|
|
8247ded2cf | ||
|
|
c52741c813 | ||
|
|
75ffbc16f2 | ||
|
|
1596e33f58 | ||
|
|
07d03f1610 | ||
|
|
a8b48dcacd | ||
|
|
bb87b2a19d | ||
|
|
19eff62c77 | ||
|
|
5fc8699db9 | ||
|
|
43fd159689 | ||
|
|
758820ca86 | ||
|
|
5664195e49 | ||
|
|
683daefc15 | ||
|
|
8e9e87f631 | ||
|
|
0a0865eb1c | ||
|
|
d588d41ab9 | ||
|
|
8aa8d597f6 | ||
|
|
67680d71a4 | ||
|
|
d86f41e29a | ||
|
|
ba56e514bd | ||
|
|
9f5f09b772 | ||
|
|
ddf4b5cbd4 | ||
|
|
e4613477b1 | ||
|
|
d18ce59187 | ||
|
|
1032224d62 | ||
|
|
44767901fe | ||
|
|
1220c86573 | ||
|
|
6ace406a2f | ||
|
|
38f1536255 | ||
|
|
324473651e | ||
|
|
573148b27a | ||
|
|
12e1c2eaa0 | ||
|
|
c678ea3060 | ||
|
|
e570b07ba0 | ||
|
|
afda4d6b7a | ||
|
|
22daa506f6 | ||
|
|
e85b90c614 | ||
|
|
9d3d33fa27 | ||
|
|
0d9dce987d | ||
|
|
65d558b2c4 | ||
|
|
b00d413961 | ||
|
|
6b54540756 | ||
|
|
356a42d330 | ||
|
|
8fcf419183 | ||
|
|
83c8b64c50 | ||
|
|
25943d1d17 | ||
|
|
bf03dab295 | ||
|
|
8adfaa9aa6 | ||
|
|
ca6570d5de | ||
|
|
3026f7249c | ||
|
|
bea29fd2ba | ||
|
|
fc55091fc5 | ||
|
|
782cf3f7c7 | ||
|
|
8f25e9d3e6 | ||
|
|
01175e2e7c | ||
|
|
5d9d539495 | ||
|
|
efb5624db6 | ||
|
|
fe0a16f478 | ||
|
|
d9d376d40d | ||
|
|
74e7f88449 | ||
|
|
b2811ffc59 | ||
|
|
f08e1da577 | ||
|
|
e863eba364 | ||
|
|
10081595af | ||
|
|
75d53725e5 | ||
|
|
d21335be85 | ||
|
|
e0385cd807 | ||
|
|
e962462e79 | ||
|
|
5896c30954 | ||
|
|
745729cdc2 | ||
|
|
95e5d37e4c | ||
|
|
838293c2f0 | ||
|
|
da21fc937b | ||
|
|
3b188b7f49 | ||
|
|
94bbd415a2 | ||
|
|
2ea2300408 | ||
|
|
000fb2efae | ||
|
|
8b523082af | ||
|
|
5d2a3cd322 | ||
|
|
df3833edbe | ||
|
|
527b65648f | ||
|
|
bef64c53f8 | ||
|
|
8edcd31404 | ||
|
|
fd1b639ad9 | ||
|
|
950a8dbfe7 | ||
|
|
26e4d8ad59 | ||
|
|
d54f590b14 | ||
|
|
b3269f20ef | ||
|
|
047646be6d | ||
|
|
8168a49d10 | ||
|
|
7f2fd4e9a0 | ||
|
|
4ea9f08425 | ||
|
|
ffb58761c1 | ||
|
|
8ecdb341e2 | ||
|
|
0c5c146fcf | ||
|
|
ad8b0c673f | ||
|
|
e574cfe681 | ||
|
|
e9be291cec | ||
|
|
d4f87c7db1 | ||
|
|
4604c01986 | ||
|
|
b0c8ff0ea6 | ||
|
|
647629ac23 | ||
|
|
be90e76422 | ||
|
|
4a37ea4819 | ||
|
|
6e08ac65b9 | ||
|
|
8705de1893 | ||
|
|
c8e7c347c3 | ||
|
|
3d0b66407e | ||
|
|
c86b6dc690 | ||
|
|
773e9465bc | ||
|
|
e1ed7f43fd | ||
|
|
3eb501aa27 | ||
|
|
d5b58eebaf | ||
|
|
6dbbd9ecfc | ||
|
|
759cc0025a | ||
|
|
d05f890147 | ||
|
|
9152fb030e | ||
|
|
2385c275ac | ||
|
|
d29b8bab36 | ||
|
|
b6922dff57 | ||
|
|
c560a88de4 | ||
|
|
fc02f38435 | ||
|
|
d5782567e8 | ||
|
|
060433621a | ||
|
|
9866e238d5 | ||
|
|
f5c4e28696 | ||
|
|
96bbd01ad6 | ||
|
|
f84a264b0e | ||
|
|
a8c17201b5 | ||
|
|
d81d89c4fb | ||
|
|
92212c48f1 | ||
|
|
42a24bbbd1 | ||
|
|
021c99e233 | ||
|
|
f730339365 | ||
|
|
40a4eb90af | ||
|
|
31ad26202e | ||
|
|
a3115d4699 | ||
|
|
c3ead80927 | ||
|
|
80cda1bb18 | ||
|
|
90ddee5f8d | ||
|
|
6fdf2f963b | ||
|
|
e1eb151051 | ||
|
|
3f8bf01f75 | ||
|
|
92824f5e4d | ||
|
|
213d3c4e2b | ||
|
|
d4c6749d2a | ||
|
|
1804b007ec | ||
|
|
655cee070d | ||
|
|
28309a1cc5 | ||
|
|
29f824cf7a | ||
|
|
2bafa2c26f | ||
|
|
5e7d793a6a | ||
|
|
3e40713ccc | ||
|
|
33a2fbb896 | ||
|
|
853ded7df7 | ||
|
|
67914157cb | ||
|
|
750d90939d | ||
|
|
31d828390f | ||
|
|
6c2f8ab085 | ||
|
|
2aea401189 | ||
|
|
c008671509 | ||
|
|
5903be156c | ||
|
|
db5056f275 | ||
|
|
e9d96ce538 | ||
|
|
444d4c082d | ||
|
|
cfe620ab15 | ||
|
|
ea8d63350a | ||
|
|
e37cef8283 | ||
|
|
3f1979286f | ||
|
|
d5c3036bc2 | ||
|
|
ebdca02218 | ||
|
|
dda5861bdd | ||
|
|
f7e652b616 | ||
|
|
65bc159ff1 | ||
|
|
c362d3a9d8 | ||
|
|
8a44be0c30 | ||
|
|
304dba5f20 | ||
|
|
b2e61d2deb | ||
|
|
e6c0bebee9 | ||
|
|
aa017116b3 | ||
|
|
97a6184e53 | ||
|
|
76bd81af15 | ||
|
|
90f7937146 | ||
|
|
98f148766d | ||
|
|
9c44e295fa | ||
|
|
b5a1d323c2 | ||
|
|
b453439968 | ||
|
|
863331b117 | ||
|
|
48521a4416 | ||
|
|
6fe643d270 | ||
|
|
fbc4bda7a6 | ||
|
|
6d9b52452e | ||
|
|
950007c815 | ||
|
|
d029394c27 | ||
|
|
879fcdc6fe | ||
|
|
2f77982b54 | ||
|
|
e3a00fb2fb | ||
|
|
4feb059f51 | ||
|
|
3d1bbe505d | ||
|
|
b2a42b6c61 | ||
|
|
315d1855de | ||
|
|
93246878e2 | ||
|
|
6c62691af0 | ||
|
|
ee5aed51d8 | ||
|
|
47f50a7008 | ||
|
|
be07254935 | ||
|
|
636f8aa4a7 | ||
|
|
22ca46a227 | ||
|
|
7b80427de0 | ||
|
|
b753b9ffa2 | ||
|
|
c62b5a3103 | ||
|
|
3c729bcacb | ||
|
|
677b77f1bb | ||
|
|
024fb268c0 | ||
|
|
ab8bc052a0 | ||
|
|
971821460c | ||
|
|
615ab8d80c | ||
|
|
83c74e86c8 | ||
|
|
9ff5544d55 | ||
|
|
2b9265d9fe |
No files matched your search
+50
-50
@@ -17,11 +17,11 @@ env:
|
||||
FEX_ENABLEAVX: 1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
build_plus_test:
|
||||
runs-on: ${{ matrix.arch }}
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [[self-hosted, x64], [self-hosted, ARMv8.0], [self-hosted, ARMv8.2], [self-hosted, ARMv8.4]]
|
||||
arch: [[self-hosted, ARMv8.0], [self-hosted, ARMv8.2], [self-hosted, ARMv8.4]]
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
@@ -65,7 +65,7 @@ jobs:
|
||||
# Note the current convention is to use the -S and -B options here to specify source
|
||||
# and build directories, but this is only available with CMake 3.13 and higher.
|
||||
# The CMake binaries on the Github Actions machines are (as of this writing) 3.12
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True -DENABLE_INTERPRETER=True -DBUILD_FEX_LINUX_TESTS=True -DBUILD_THUNKS=True -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/build/install
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True -DBUILD_FEX_LINUX_TESTS=True -DBUILD_THUNKS=True -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/build/install
|
||||
|
||||
- name: Build
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
@@ -78,18 +78,6 @@ jobs:
|
||||
shell: bash
|
||||
run: cmake --build . --config $BUILD_TYPE --target install
|
||||
|
||||
- name: ASM Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the unit tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target asm_tests
|
||||
|
||||
- name: ASM Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ASM.log || true
|
||||
|
||||
- name: IR Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
@@ -102,30 +90,6 @@ jobs:
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_IR.log || true
|
||||
|
||||
- name: Posix Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the posixtest
|
||||
run: cmake --build . --config $BUILD_TYPE --target posix_tests
|
||||
|
||||
- name: Posix Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_Posix.log || true
|
||||
|
||||
- name: gvisor tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the gvisor tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target gvisor_tests
|
||||
|
||||
- name: GVisor Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_GVisor.log || true
|
||||
|
||||
- name: gcc target tests 64
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
@@ -150,17 +114,6 @@ jobs:
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_GCC32.log || true
|
||||
|
||||
- name: Struct verifier tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: cmake --build . --config $BUILD_TYPE --target struct_verifier
|
||||
|
||||
- name: Struct verifier Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_StructVerifier.log || true
|
||||
|
||||
- name: APITest tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
@@ -244,6 +197,53 @@ jobs:
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ThunkResults.log || true
|
||||
|
||||
- name: ASM Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the unit tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target asm_tests
|
||||
|
||||
- name: ASM Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ASM.log || true
|
||||
|
||||
- name: Posix Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the posixtest
|
||||
run: cmake --build . --config $BUILD_TYPE --target posix_tests
|
||||
|
||||
- name: Posix Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_Posix.log || true
|
||||
|
||||
- name: gvisor tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the gvisor tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target gvisor_tests
|
||||
|
||||
- name: GVisor Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_GVisor.log || true
|
||||
|
||||
- name: Struct verifier tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: cmake --build . --config $BUILD_TYPE --target struct_verifier
|
||||
|
||||
- name: Struct verifier Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_StructVerifier.log || true
|
||||
|
||||
- name: Truncate test results
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
|
||||
@@ -24,12 +24,11 @@ env:
|
||||
FEX_ENABLEAVX: 1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
glibc_fault_test:
|
||||
runs-on: ${{ matrix.arch }}
|
||||
strategy:
|
||||
matrix:
|
||||
# Run on an x86 device and any ARM runner.
|
||||
arch: [[self-hosted, x64], [self-hosted, ARM64]]
|
||||
arch: [[self-hosted, ARM64]]
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
@@ -73,7 +72,7 @@ jobs:
|
||||
# Note the current convention is to use the -S and -B options here to specify source
|
||||
# and build directories, but this is only available with CMake 3.13 and higher.
|
||||
# The CMake binaries on the Github Actions machines are (as of this writing) 3.12
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True -DENABLE_INTERPRETER=True -DBUILD_FEX_LINUX_TESTS=True -DENABLE_GLIBC_ALLOCATOR_HOOK_FAULT=True -DENABLE_JEMALLOC_GLIBC_ALLOC=False -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/build/install
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True -DBUILD_FEX_LINUX_TESTS=True -DENABLE_GLIBC_ALLOCATOR_HOOK_FAULT=True -DENABLE_JEMALLOC_GLIBC_ALLOC=False -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/build/install
|
||||
|
||||
- name: Build
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
@@ -86,18 +85,6 @@ jobs:
|
||||
shell: bash
|
||||
run: cmake --build . --config $BUILD_TYPE --target install
|
||||
|
||||
- name: ASM Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the unit tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target asm_tests
|
||||
|
||||
- name: ASM Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ASM.log || true
|
||||
|
||||
- name: IR Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
@@ -110,18 +97,6 @@ jobs:
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_IR.log || true
|
||||
|
||||
- name: Posix Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the posixtest
|
||||
run: cmake --build . --config $BUILD_TYPE --target posix_tests
|
||||
|
||||
- name: Posix Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_Posix.log || true
|
||||
|
||||
- name: gcc target tests 64
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
@@ -179,6 +154,30 @@ jobs:
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_FEXLinuxTests.log || true
|
||||
|
||||
- name: ASM Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the unit tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target asm_tests
|
||||
|
||||
- name: ASM Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ASM.log || true
|
||||
|
||||
- name: Posix Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the posixtest
|
||||
run: cmake --build . --config $BUILD_TYPE --target posix_tests
|
||||
|
||||
- name: Posix Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_Posix.log || true
|
||||
|
||||
- name: Truncate test results
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
name: Hostrunner tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||
BUILD_TYPE: Release
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
FEX_ENABLEAVX: 1
|
||||
|
||||
jobs:
|
||||
hostrunner_tests:
|
||||
runs-on: ${{ matrix.arch }}
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [[self-hosted, x64]]
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set runner label
|
||||
run: echo "runner_label=${{ matrix.arch[1] }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set rootfs paths
|
||||
run: |
|
||||
echo "FEX_ROOTFS_MOUNT=/mnt/AutoNFS/rootfs/" >> $GITHUB_ENV
|
||||
echo "FEX_ROOTFS_PATH=$HOME/Rootfs/" >> $GITHUB_ENV
|
||||
echo "FEX_ROOTFS=$HOME/Rootfs/" >> $GITHUB_ENV
|
||||
echo "ROOTFS=$HOME/Rootfs/" >> $GITHUB_ENV
|
||||
|
||||
- name: Update RootFS cache
|
||||
# Use a bash shell so we can use the same syntax for environment variable
|
||||
# access regardless of the host operating system
|
||||
shell: bash
|
||||
run: $GITHUB_WORKSPACE/Scripts/CI_FetchRootFS.py
|
||||
|
||||
- name : submodule checkout
|
||||
# Need to update submodules
|
||||
run: |
|
||||
git submodule sync --recursive
|
||||
git submodule update --init --depth 1
|
||||
|
||||
- name: Clean Build Environment
|
||||
run: rm -Rf ${{runner.workspace}}/build
|
||||
|
||||
- name: Create Build Environment
|
||||
# Some projects don't allow in-source building, so create a separate build directory
|
||||
# We'll use this as our working directory for all subsequent commands
|
||||
run: cmake -E make_directory ${{runner.workspace}}/build
|
||||
|
||||
- name: Configure CMake
|
||||
# Use a bash shell so we can use the same syntax for environment variable
|
||||
# access regardless of the host operating system
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
# Note the current convention is to use the -S and -B options here to specify source
|
||||
# and build directories, but this is only available with CMake 3.13 and higher.
|
||||
# The CMake binaries on the Github Actions machines are (as of this writing) 3.12
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True
|
||||
|
||||
- name: Build
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the build. You can specify a specific target with "--target <NAME>"
|
||||
run: cmake --build . --config $BUILD_TYPE
|
||||
|
||||
- name: ASM Tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
# Execute the unit tests
|
||||
run: cmake --build . --config $BUILD_TYPE --target asm_tests
|
||||
|
||||
- name: ASM Test Results move
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_ASM.log || true
|
||||
|
||||
- name: Truncate test results
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
# Cap out the log files at 20M in case something crash spins and dumps fault text
|
||||
# ASM tests get quite close to 10MB
|
||||
run: truncate --size=<20M ${{runner.workspace}}/build/Testing/Temporary/LastTest_*.log || true
|
||||
|
||||
- name: Set runner name
|
||||
if: ${{ always() }}
|
||||
run: echo "runner_name=$(hostname)" >> $GITHUB_ENV
|
||||
|
||||
- name: Upload results
|
||||
if: ${{ always() }}
|
||||
uses: 'actions/upload-artifact@v3'
|
||||
timeout-minutes: 1
|
||||
with:
|
||||
name: Results-${{ env.runner_name }}
|
||||
path: ${{runner.workspace}}/build/Testing/Temporary/LastTest_*.log
|
||||
retention-days: 3
|
||||
|
||||
@@ -16,11 +16,11 @@ env:
|
||||
FEX_ENABLEAVX: 1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
instcountci_tests:
|
||||
runs-on: ${{ matrix.arch }}
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [[self-hosted, ARM64]]
|
||||
arch: [[self-hosted, x64], [self-hosted, ARM64]]
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
# Note the current convention is to use the -S and -B options here to specify source
|
||||
# and build directories, but this is only available with CMake 3.13 and higher.
|
||||
# The CMake binaries on the Github Actions machines are (as of this writing) 3.12
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_VIXL_SIMULATOR=False -DENABLE_VIXL_DISASSEMBLER=True -DENABLE_LTO=False -DENABLE_ASSERTIONS=True
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_VIXL_SIMULATOR=False -DENABLE_VIXL_DISASSEMBLER=True -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True
|
||||
|
||||
- name: Build
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
@@ -86,6 +86,25 @@ jobs:
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mv ${{runner.workspace}}/build/Testing/Temporary/LastTest.log ${{runner.workspace}}/build/Testing/Temporary/LastTest_InstCountCI.log || true
|
||||
|
||||
- name: Update local repo instcount
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: cmake --build . --config $BUILD_TYPE --target instcountci_update_tests
|
||||
|
||||
- name: Get instcountCI diff
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{github.workspace}}/
|
||||
run: git diff --output=${{runner.workspace}}/build/InstCountCI.diff
|
||||
|
||||
- name: Check if InstCountCI Diff exists
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
working-directory: ${{github.workspace}}/
|
||||
# Check if the file is empty
|
||||
run: sh -c "! test -s ${{runner.workspace}}/build/InstCountCI.diff"
|
||||
|
||||
- name: Truncate test results
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
@@ -107,3 +126,12 @@ jobs:
|
||||
path: ${{runner.workspace}}/build/Testing/Temporary/LastTest_*.log
|
||||
retention-days: 3
|
||||
|
||||
- name: Upload results InstCountCI
|
||||
if: ${{ always() }}
|
||||
uses: 'actions/upload-artifact@v3'
|
||||
timeout-minutes: 1
|
||||
with:
|
||||
name: Results-${{ env.runner_name }}-instcountci
|
||||
path: ${{runner.workspace}}/build/InstCountCI.diff
|
||||
retention-days: 3
|
||||
|
||||
@@ -13,11 +13,11 @@ env:
|
||||
FEX_ENABLEAVX: 1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
mingw_build:
|
||||
runs-on: ${{ matrix.arch }}
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [[self-hosted, x64, mingw], [self-hosted, ARM64, mingw]]
|
||||
arch: [[self-hosted, ARM64, mingw]]
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
@@ -74,7 +74,7 @@ jobs:
|
||||
# Note the current convention is to use the -S and -B options here to specify source
|
||||
# and build directories, but this is only available with CMake 3.13 and higher.
|
||||
# The CMake binaries on the Github Actions machines are (as of this writing) 3.12
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/toolchain_mingw.cmake -DMINGW_TRIPLE=$MINGW_TRIPLE -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True -DENABLE_INTERPRETER=False -DBUILD_TESTS=False -DENABLE_JEMALLOC=False -DENABLE_JEMALLOC_GLIBC_ALLOC=False -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/build/install
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/toolchain_mingw.cmake -DMINGW_TRIPLE=$MINGW_TRIPLE -G Ninja -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True -DBUILD_TESTS=False -DENABLE_JEMALLOC=False -DENABLE_JEMALLOC_GLIBC_ALLOC=False -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/build/install
|
||||
|
||||
- name: Build
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
|
||||
@@ -16,7 +16,7 @@ env:
|
||||
FEX_ENABLEAVX: 1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
vixl_simulator:
|
||||
runs-on: ${{ matrix.arch }}
|
||||
strategy:
|
||||
matrix:
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"ThunksDB": {
|
||||
"fex_thunk_test": 1
|
||||
}
|
||||
}
|
||||
+2
-16
@@ -25,7 +25,6 @@ option(ENABLE_JEMALLOC_GLIBC_ALLOC "Enables jemalloc glibc allocator" TRUE)
|
||||
option(ENABLE_OFFLINE_TELEMETRY "Enables FEX offline telemetry" TRUE)
|
||||
option(ENABLE_COMPILE_TIME_TRACE "Enables time trace compile option" FALSE)
|
||||
option(ENABLE_LIBCXX "Enables LLVM libc++" FALSE)
|
||||
option(ENABLE_INTERPRETER "Enables FEX's Interpreter" FALSE)
|
||||
option(ENABLE_CCACHE "Enables ccache for compile caching" TRUE)
|
||||
option(ENABLE_TERMUX_BUILD "Forces building for Termux on a non-Termux build machine" FALSE)
|
||||
option(ENABLE_VIXL_SIMULATOR "Forces the FEX JIT to use the VIXL simulator" FALSE)
|
||||
@@ -97,11 +96,6 @@ if (ENABLE_GDB_SYMBOLS)
|
||||
endif()
|
||||
|
||||
|
||||
if (ENABLE_INTERPRETER)
|
||||
message(STATUS "Interpreter enabled")
|
||||
add_definitions(-DINTERPRETER_ENABLED=1)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Bin)
|
||||
@@ -118,14 +112,6 @@ else()
|
||||
endif()
|
||||
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
|
||||
option(ENABLE_X86_HOST_DEBUG "Enables compiling on x86_64 host" FALSE)
|
||||
if (NOT ENABLE_X86_HOST_DEBUG)
|
||||
message(FATAL_ERROR
|
||||
" Be warned: FEX isn't optimized for x86_64 hosts!\n"
|
||||
" Support for x86_64 hosts is only for debugging and convenience!\n"
|
||||
" Don't expect amazing performance or optimal code generation!\n"
|
||||
" Pass -DENABLE_X86_HOST_DEBUG=True to bypass this message!")
|
||||
endif()
|
||||
set(_M_X86_64 1)
|
||||
add_definitions(-D_M_X86_64=1)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcx16")
|
||||
@@ -467,10 +453,10 @@ if (BUILD_THUNKS)
|
||||
CMAKE_ARGS
|
||||
"-DBITNESS=64"
|
||||
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
|
||||
"-DBUILD_FEX_LINUX_TESTS=${BUILD_FEX_LINUX_TESTS}"
|
||||
"-DENABLE_CLANG_THUNKS=${ENABLE_CLANG_THUNKS}"
|
||||
"-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${X86_64_TOOLCHAIN_FILE}"
|
||||
"-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}"
|
||||
"-DSTRUCT_VERIFIER=${CMAKE_SOURCE_DIR}/Scripts/StructPackVerifier.py"
|
||||
"-DFEX_PROJECT_SOURCE_DIR=${FEX_PROJECT_SOURCE_DIR}"
|
||||
"-DGENERATOR_EXE=$<TARGET_FILE:thunkgen>"
|
||||
INSTALL_COMMAND ""
|
||||
@@ -485,10 +471,10 @@ if (BUILD_THUNKS)
|
||||
CMAKE_ARGS
|
||||
"-DBITNESS=32"
|
||||
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
|
||||
"-DBUILD_FEX_LINUX_TESTS=${BUILD_FEX_LINUX_TESTS}"
|
||||
"-DENABLE_CLANG_THUNKS=${ENABLE_CLANG_THUNKS}"
|
||||
"-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${X86_32_TOOLCHAIN_FILE}"
|
||||
"-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}"
|
||||
"-DSTRUCT_VERIFIER=${CMAKE_SOURCE_DIR}/Scripts/StructPackVerifier.py"
|
||||
"-DFEX_PROJECT_SOURCE_DIR=${FEX_PROJECT_SOURCE_DIR}"
|
||||
"-DGENERATOR_EXE=$<TARGET_FILE:thunkgen>"
|
||||
INSTALL_COMMAND ""
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"Config": {
|
||||
"Env": "STEAM_GAME_LAUNCH_SHELL=@CMAKE_INSTALL_PREFIX@/bin/FEXBash"
|
||||
}
|
||||
}
|
||||
@@ -144,6 +144,12 @@
|
||||
"@PREFIX_LIB@/libasound.so.2.0.0"
|
||||
]
|
||||
},
|
||||
"fex_thunk_test": {
|
||||
"Library": "libfex_thunk_test-guest.so",
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libfex_thunk_test.so"
|
||||
]
|
||||
},
|
||||
"Xrender": {
|
||||
"Library": "libXrender-guest.so",
|
||||
"Overlay": [
|
||||
|
||||
Vendored
+1
-1
Submodule External/Vulkan-Headers updated: 98f440ce68...85c2334e92.
+16
-9
@@ -13,15 +13,6 @@ if (CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64|^arm64|^armv8\.*")
|
||||
set(_M_ARM_64 1)
|
||||
endif()
|
||||
|
||||
if (ENABLE_VIXL_SIMULATOR)
|
||||
# If the vixl simulator is enabled then we are using the ARM64 JIT
|
||||
option(ENABLE_JIT_X86_64 "Enable the x86_64 JIT" FALSE)
|
||||
option(ENABLE_JIT_ARM64 "Enable the ARM64 JIT" TRUE)
|
||||
else()
|
||||
option(ENABLE_JIT_X86_64 "Enable the x86_64 JIT" ${_M_X86_64})
|
||||
option(ENABLE_JIT_ARM64 "Enable the ARM64 JIT" ${_M_ARM_64})
|
||||
endif()
|
||||
|
||||
option(ENABLE_CLANG_FORMAT "Run clang format over the source" FALSE)
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
@@ -33,6 +24,22 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(CheckIncludeFileCXX)
|
||||
include(CheckCXXSourceCompiles)
|
||||
|
||||
set(CMAKE_REQUIRED_FLAGS "-std=c++11 -Wattributes -Werror=attributes")
|
||||
check_cxx_source_compiles(
|
||||
"
|
||||
__attribute__((preserve_all))
|
||||
void Testy() {
|
||||
}
|
||||
int main() {
|
||||
return 0;
|
||||
}"
|
||||
HAS_CLANG_PRESERVE_ALL)
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
if (HAS_CLANG_PRESERVE_ALL)
|
||||
message(STATUS "Has clang::preserve_all")
|
||||
endif ()
|
||||
|
||||
if (EXISTS ${CMAKE_CURRENT_DIR}/External/vixl/)
|
||||
# Useful to have for freestanding libFEXCore
|
||||
|
||||
@@ -144,7 +144,7 @@ def parse_ops(ops):
|
||||
Argument = Argument.strip()
|
||||
OpArg = OpArgument()
|
||||
|
||||
Split = Argument.split(":")
|
||||
Split = Argument.split(":", 1)
|
||||
if len(Split) != 2:
|
||||
ExitError("Error parsing argument. Missing Type and name colon split")
|
||||
|
||||
|
||||
@@ -107,9 +107,19 @@ set (SRCS
|
||||
Interface/Core/X86HelperGen.cpp
|
||||
Interface/Core/ArchHelpers/Arm64Emitter.cpp
|
||||
Interface/Core/Dispatcher/Dispatcher.cpp
|
||||
Interface/Core/Dispatcher/X86Dispatcher.cpp
|
||||
Interface/Core/Dispatcher/Arm64Dispatcher.cpp
|
||||
Interface/Core/Interpreter/Fallbacks/InterpreterFallbacks.cpp
|
||||
Interface/Core/JIT/Arm64/JIT.cpp
|
||||
Interface/Core/JIT/Arm64/ALUOps.cpp
|
||||
Interface/Core/JIT/Arm64/AtomicOps.cpp
|
||||
Interface/Core/JIT/Arm64/BranchOps.cpp
|
||||
Interface/Core/JIT/Arm64/ConversionOps.cpp
|
||||
Interface/Core/JIT/Arm64/EncryptionOps.cpp
|
||||
Interface/Core/JIT/Arm64/FlagOps.cpp
|
||||
Interface/Core/JIT/Arm64/MemoryOps.cpp
|
||||
Interface/Core/JIT/Arm64/MiscOps.cpp
|
||||
Interface/Core/JIT/Arm64/MoveOps.cpp
|
||||
Interface/Core/JIT/Arm64/VectorOps.cpp
|
||||
Interface/Core/JIT/Arm64/Arm64Relocations.cpp
|
||||
Interface/Core/X86Tables/BaseTables.cpp
|
||||
Interface/Core/X86Tables/DDDTables.cpp
|
||||
Interface/Core/X86Tables/EVEXTables.cpp
|
||||
@@ -141,7 +151,7 @@ set (SRCS
|
||||
Interface/IR/Passes/RedundantFlagCalculationElimination.cpp
|
||||
Interface/IR/Passes/DeadStoreElimination.cpp
|
||||
Interface/IR/Passes/RegisterAllocationPass.cpp
|
||||
Interface/IR/Passes/SyscallOptimization.cpp
|
||||
Interface/IR/Passes/InlineCallOptimization.cpp
|
||||
Utils/NetStream.cpp
|
||||
Utils/Telemetry.cpp
|
||||
Utils/Threads.cpp
|
||||
@@ -159,24 +169,7 @@ if (ENABLE_GLIBC_ALLOCATOR_HOOK_FAULT)
|
||||
Utils/AllocatorOverride.cpp)
|
||||
endif()
|
||||
|
||||
if (ENABLE_INTERPRETER)
|
||||
list(APPEND SRCS
|
||||
Interface/Core/Interpreter/InterpreterCore.cpp
|
||||
Interface/Core/Interpreter/InterpreterOps.cpp
|
||||
Interface/Core/Interpreter/ALUOps.cpp
|
||||
Interface/Core/Interpreter/AtomicOps.cpp
|
||||
Interface/Core/Interpreter/BranchOps.cpp
|
||||
Interface/Core/Interpreter/ConversionOps.cpp
|
||||
Interface/Core/Interpreter/EncryptionOps.cpp
|
||||
Interface/Core/Interpreter/F80Ops.cpp
|
||||
Interface/Core/Interpreter/FlagOps.cpp
|
||||
Interface/Core/Interpreter/MemoryOps.cpp
|
||||
Interface/Core/Interpreter/MiscOps.cpp
|
||||
Interface/Core/Interpreter/MoveOps.cpp
|
||||
Interface/Core/Interpreter/VectorOps.cpp)
|
||||
endif()
|
||||
|
||||
set(DEFINES -DTHREAD_LOCAL=_Thread_local)
|
||||
set(DEFINES -DTHREAD_LOCAL=_Thread_local -DJIT_ARM64)
|
||||
|
||||
if (_M_X86_64)
|
||||
list(APPEND DEFINES -D_M_X86_64=1)
|
||||
@@ -195,41 +188,14 @@ if (ENABLE_VIXL_DISASSEMBLER)
|
||||
list(APPEND DEFINES -DVIXL_DISASSEMBLER=1)
|
||||
endif()
|
||||
|
||||
if (ENABLE_JIT_X86_64)
|
||||
list(APPEND SRCS
|
||||
Interface/Core/JIT/x86_64/JIT.cpp
|
||||
Interface/Core/JIT/x86_64/ALUOps.cpp
|
||||
Interface/Core/JIT/x86_64/AtomicOps.cpp
|
||||
Interface/Core/JIT/x86_64/BranchOps.cpp
|
||||
Interface/Core/JIT/x86_64/ConversionOps.cpp
|
||||
Interface/Core/JIT/x86_64/EncryptionOps.cpp
|
||||
Interface/Core/JIT/x86_64/FlagOps.cpp
|
||||
Interface/Core/JIT/x86_64/MemoryOps.cpp
|
||||
Interface/Core/JIT/x86_64/MiscOps.cpp
|
||||
Interface/Core/JIT/x86_64/MoveOps.cpp
|
||||
Interface/Core/JIT/x86_64/VectorOps.cpp
|
||||
Interface/Core/JIT/x86_64/x64Relocations.cpp
|
||||
)
|
||||
list(APPEND DEFINES -DJIT_X86_64)
|
||||
if (_M_ARM_64 AND HAS_CLANG_PRESERVE_ALL)
|
||||
list(APPEND DEFINES "-DFEXCORE_PRESERVE_ALL_ATTR=__attribute__((preserve_all));-DFEXCORE_HAS_PRESERVE_ALL_ATTR=1")
|
||||
else()
|
||||
list(APPEND DEFINES "-DFEXCORE_PRESERVE_ALL_ATTR=;-DFEXCORE_HAS_PRESERVE_ALL_ATTR=0")
|
||||
endif()
|
||||
|
||||
if (ENABLE_JIT_ARM64)
|
||||
list(APPEND DEFINES -DJIT_ARM64)
|
||||
list(APPEND SRCS
|
||||
Interface/Core/JIT/Arm64/JIT.cpp
|
||||
Interface/Core/JIT/Arm64/ALUOps.cpp
|
||||
Interface/Core/JIT/Arm64/AtomicOps.cpp
|
||||
Interface/Core/JIT/Arm64/BranchOps.cpp
|
||||
Interface/Core/JIT/Arm64/ConversionOps.cpp
|
||||
Interface/Core/JIT/Arm64/EncryptionOps.cpp
|
||||
Interface/Core/JIT/Arm64/FlagOps.cpp
|
||||
Interface/Core/JIT/Arm64/MemoryOps.cpp
|
||||
Interface/Core/JIT/Arm64/MiscOps.cpp
|
||||
Interface/Core/JIT/Arm64/MoveOps.cpp
|
||||
Interface/Core/JIT/Arm64/VectorOps.cpp
|
||||
Interface/Core/JIT/Arm64/Arm64Relocations.cpp
|
||||
)
|
||||
endif()
|
||||
# Some defines for the softfloat library
|
||||
list(APPEND DEFINES "-DSOFTFLOAT_BUILTIN_CLZ")
|
||||
|
||||
set (LIBS fmt::fmt vixl xxhash FEXHeaderUtils)
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/Utils/Allocator.h>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include <FEXCore/fextl/fmt.h>
|
||||
|
||||
#include "Common/JitSymbols.h"
|
||||
@@ -26,42 +27,6 @@ namespace FEXCore {
|
||||
fd = open(PerfMap.c_str(), O_CREAT | O_TRUNC | O_WRONLY | O_APPEND, 0644);
|
||||
}
|
||||
|
||||
void JITSymbols::Register(const void *HostAddr, uint64_t GuestAddr, uint32_t CodeSize) {
|
||||
if (fd == -1) return;
|
||||
|
||||
// Linux perf format is very straightforward
|
||||
// `<HostPtr> <Size> <Name>\n`
|
||||
const auto Buffer = fextl::fmt::format("{} {:x} JIT_0x{:x}_{}\n", HostAddr, CodeSize, GuestAddr, HostAddr);
|
||||
auto Result = write(fd, Buffer.c_str(), Buffer.size());
|
||||
if (Result == -1 && errno == EBADF) {
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void JITSymbols::Register(const void *HostAddr, uint32_t CodeSize, std::string_view Name) {
|
||||
if (fd == -1) return;
|
||||
|
||||
// Linux perf format is very straightforward
|
||||
// `<HostPtr> <Size> <Name>\n`
|
||||
const auto Buffer = fextl::fmt::format("{} {:x} {}_{}\n", HostAddr, CodeSize, Name, HostAddr);
|
||||
auto Result = write(fd, Buffer.c_str(), Buffer.size());
|
||||
if (Result == -1 && errno == EBADF) {
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void JITSymbols::Register(const void *HostAddr, uint32_t CodeSize, std::string_view Name, uintptr_t Offset) {
|
||||
if (fd == -1) return;
|
||||
|
||||
// Linux perf format is very straightforward
|
||||
// `<HostPtr> <Size> <Name>\n`
|
||||
const auto Buffer = fextl::fmt::format("{} {:x} {}+0x{:x} ({})\n", HostAddr, CodeSize, Name, Offset, HostAddr);
|
||||
auto Result = write(fd, Buffer.c_str(), Buffer.size());
|
||||
if (Result == -1 && errno == EBADF) {
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void JITSymbols::RegisterNamedRegion(const void *HostAddr, uint32_t CodeSize, std::string_view Name) {
|
||||
if (fd == -1) return;
|
||||
|
||||
@@ -86,4 +51,89 @@ namespace FEXCore {
|
||||
}
|
||||
}
|
||||
|
||||
// Buffered JIT symbols.
|
||||
void JITSymbols::Register(Core::JITSymbolBuffer *Buffer, const void *HostAddr, uint64_t GuestAddr, uint32_t CodeSize) {
|
||||
if (fd == -1) return;
|
||||
|
||||
// Calculate remaining sizes.
|
||||
const auto RemainingSize = Buffer->BUFFER_SIZE - Buffer->Offset;
|
||||
const auto CurrentBufferOffset = &Buffer->Buffer[Buffer->Offset];
|
||||
|
||||
// Linux perf format is very straightforward
|
||||
// `<HostPtr> <Size> <Name>\n`
|
||||
const auto FMTResult = fmt::format_to_n(CurrentBufferOffset, RemainingSize, "{} {:x} JIT_0x{:x}_{}\n", HostAddr, CodeSize, GuestAddr, HostAddr);
|
||||
if (FMTResult.out >= &Buffer->Buffer[Buffer->BUFFER_SIZE]) {
|
||||
// Couldn't fit, need to force a write.
|
||||
WriteBuffer(Buffer, true);
|
||||
// Rerun
|
||||
Register(Buffer, HostAddr, GuestAddr, CodeSize);
|
||||
return;
|
||||
}
|
||||
|
||||
Buffer->Offset += FMTResult.size;
|
||||
WriteBuffer(Buffer);
|
||||
}
|
||||
|
||||
void JITSymbols::Register(Core::JITSymbolBuffer *Buffer, const void *HostAddr, uint32_t CodeSize, std::string_view Name, uintptr_t Offset) {
|
||||
if (fd == -1) return;
|
||||
|
||||
// Calculate remaining sizes.
|
||||
const auto RemainingSize = Buffer->BUFFER_SIZE - Buffer->Offset;
|
||||
const auto CurrentBufferOffset = &Buffer->Buffer[Buffer->Offset];
|
||||
|
||||
// Linux perf format is very straightforward
|
||||
// `<HostPtr> <Size> <Name>\n`
|
||||
const auto FMTResult = fmt::format_to_n(CurrentBufferOffset, RemainingSize, "{} {:x} {}+0x{:x} ({})\n", HostAddr, CodeSize, Name, Offset, HostAddr);
|
||||
if (FMTResult.out >= &Buffer->Buffer[Buffer->BUFFER_SIZE]) {
|
||||
// Couldn't fit, need to force a write.
|
||||
WriteBuffer(Buffer, true);
|
||||
// Rerun
|
||||
Register(Buffer, HostAddr, CodeSize, Name, Offset);
|
||||
return;
|
||||
}
|
||||
|
||||
Buffer->Offset += FMTResult.size;
|
||||
WriteBuffer(Buffer);
|
||||
}
|
||||
|
||||
void JITSymbols::RegisterNamedRegion(Core::JITSymbolBuffer *Buffer, const void *HostAddr, uint32_t CodeSize, std::string_view Name) {
|
||||
if (fd == -1) return;
|
||||
|
||||
// Calculate remaining sizes.
|
||||
const auto RemainingSize = Buffer->BUFFER_SIZE - Buffer->Offset;
|
||||
const auto CurrentBufferOffset = &Buffer->Buffer[Buffer->Offset];
|
||||
|
||||
// Linux perf format is very straightforward
|
||||
// `<HostPtr> <Size> <Name>\n`
|
||||
const auto FMTResult = fmt::format_to_n(CurrentBufferOffset, RemainingSize, "{} {:x} {}\n", HostAddr, CodeSize, Name);
|
||||
if (FMTResult.out >= &Buffer->Buffer[Buffer->BUFFER_SIZE]) {
|
||||
// Couldn't fit, need to force a write.
|
||||
WriteBuffer(Buffer, true);
|
||||
// Rerun
|
||||
RegisterNamedRegion(Buffer, HostAddr, CodeSize, Name);
|
||||
return;
|
||||
}
|
||||
|
||||
Buffer->Offset += FMTResult.size;
|
||||
WriteBuffer(Buffer);
|
||||
}
|
||||
|
||||
void JITSymbols::WriteBuffer(Core::JITSymbolBuffer *Buffer, bool ForceWrite) {
|
||||
auto Now = std::chrono::steady_clock::now();
|
||||
if (!ForceWrite) {
|
||||
if (((Buffer->LastWrite - Now) < Buffer->MAXIMUM_THRESHOLD) &&
|
||||
Buffer->Offset < Buffer->NEEDS_WRITE_DISTANCE) {
|
||||
// Still buffering, no need to write.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Buffer->LastWrite = Now;
|
||||
auto Result = write(fd, Buffer->Buffer, Buffer->Offset);
|
||||
if (Result == -1 && errno == EBADF) {
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
Buffer->Offset = 0;
|
||||
}
|
||||
} // namespace FEXCore
|
||||
@@ -1,5 +1,10 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/Debug/InternalThreadState.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
@@ -12,13 +17,20 @@ public:
|
||||
~JITSymbols();
|
||||
|
||||
void InitFile();
|
||||
void Register(const void *HostAddr, uint64_t GuestAddr, uint32_t CodeSize);
|
||||
void Register(const void *HostAddr, uint32_t CodeSize, std::string_view Name);
|
||||
void Register(const void *HostAddr, uint32_t CodeSize, std::string_view Name, uintptr_t Offset);
|
||||
void RegisterNamedRegion(const void *HostAddr, uint32_t CodeSize, std::string_view Name);
|
||||
void RegisterJITSpace(const void *HostAddr, uint32_t CodeSize);
|
||||
|
||||
// Allocate JIT buffer.
|
||||
static fextl::unique_ptr<Core::JITSymbolBuffer> AllocateBuffer() {
|
||||
return fextl::make_unique<Core::JITSymbolBuffer>();
|
||||
}
|
||||
|
||||
void Register(Core::JITSymbolBuffer *Buffer, const void *HostAddr, uint64_t GuestAddr, uint32_t CodeSize);
|
||||
void Register(Core::JITSymbolBuffer *Buffer, const void *HostAddr, uint32_t CodeSize, std::string_view Name, uintptr_t Offset);
|
||||
void RegisterNamedRegion(Core::JITSymbolBuffer *Buffer, const void *HostAddr, uint32_t CodeSize, std::string_view Name);
|
||||
|
||||
private:
|
||||
int fd{-1};
|
||||
void WriteBuffer(Core::JITSymbolBuffer *Buffer, bool ForceWrite = false);
|
||||
};
|
||||
}
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "internals.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t extF80_add( extFloat80_t a, extFloat80_t b )
|
||||
{
|
||||
union { struct extFloat80M s; extFloat80_t f; } uA;
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t extF80_div( extFloat80_t a, extFloat80_t b )
|
||||
{
|
||||
union { struct extFloat80M s; extFloat80_t f; } uA;
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
bool extF80_eq( extFloat80_t a, extFloat80_t b )
|
||||
{
|
||||
union { struct extFloat80M s; extFloat80_t f; } uA;
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
bool extF80_lt( extFloat80_t a, extFloat80_t b )
|
||||
{
|
||||
union { struct extFloat80M s; extFloat80_t f; } uA;
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t extF80_mul( extFloat80_t a, extFloat80_t b )
|
||||
{
|
||||
union { struct extFloat80M s; extFloat80_t f; } uA;
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t extF80_rem( extFloat80_t a, extFloat80_t b )
|
||||
{
|
||||
union { struct extFloat80M s; extFloat80_t f; } uA;
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t
|
||||
extF80_roundToInt( extFloat80_t a, uint_fast8_t roundingMode, bool exact )
|
||||
{
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t extF80_sqrt( extFloat80_t a )
|
||||
{
|
||||
union { struct extFloat80M s; extFloat80_t f; } uA;
|
||||
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "internals.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t extF80_sub( extFloat80_t a, extFloat80_t b )
|
||||
{
|
||||
union { struct extFloat80M s; extFloat80_t f; } uA;
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
float128_t extF80_to_f128( extFloat80_t a )
|
||||
{
|
||||
union { struct extFloat80M s; extFloat80_t f; } uA;
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
float32_t extF80_to_f32( extFloat80_t a )
|
||||
{
|
||||
union { struct extFloat80M s; extFloat80_t f; } uA;
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
float64_t extF80_to_f64( extFloat80_t a )
|
||||
{
|
||||
union { struct extFloat80M s; extFloat80_t f; } uA;
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
int_fast32_t
|
||||
extF80_to_i32( extFloat80_t a, uint_fast8_t roundingMode, bool exact )
|
||||
{
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
int_fast64_t
|
||||
extF80_to_i64( extFloat80_t a, uint_fast8_t roundingMode, bool exact )
|
||||
{
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint_fast64_t
|
||||
extF80_to_ui64( extFloat80_t a, uint_fast8_t roundingMode, bool exact )
|
||||
{
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t f128_to_extF80( float128_t a )
|
||||
{
|
||||
union ui128_f128 uA;
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t f32_to_extF80( float32_t a )
|
||||
{
|
||||
union ui32_f32 uA;
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t f64_to_extF80( float64_t a )
|
||||
{
|
||||
union ui64_f64 uA;
|
||||
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "internals.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t i32_to_extF80( int32_t a )
|
||||
{
|
||||
uint_fast16_t uiZ64;
|
||||
|
||||
@@ -68,9 +68,11 @@ uint_fast64_t
|
||||
uint_fast64_t softfloat_roundMToUI64( bool, uint32_t *, uint_fast8_t, bool );
|
||||
#endif
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
int_fast32_t softfloat_roundToI32( bool, uint_fast64_t, uint_fast8_t, bool );
|
||||
|
||||
#ifdef SOFTFLOAT_FAST_INT64
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
int_fast64_t
|
||||
softfloat_roundToI64(
|
||||
bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool );
|
||||
@@ -109,8 +111,10 @@ float16_t
|
||||
#define isNaNF32UI( a ) (((~(a) & 0x7F800000) == 0) && ((a) & 0x007FFFFF))
|
||||
|
||||
struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; };
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t );
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
float32_t softfloat_roundPackToF32( bool, int_fast16_t, uint_fast32_t );
|
||||
float32_t softfloat_normRoundPackToF32( bool, int_fast16_t, uint_fast32_t );
|
||||
|
||||
@@ -130,8 +134,10 @@ float32_t
|
||||
#define isNaNF64UI( a ) (((~(a) & UINT64_C( 0x7FF0000000000000 )) == 0) && ((a) & UINT64_C( 0x000FFFFFFFFFFFFF )))
|
||||
|
||||
struct exp16_sig64 { int_fast16_t exp; uint_fast64_t sig; };
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t );
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
float64_t softfloat_roundPackToF64( bool, int_fast16_t, uint_fast64_t );
|
||||
float64_t softfloat_normRoundPackToF64( bool, int_fast16_t, uint_fast64_t );
|
||||
|
||||
@@ -155,11 +161,14 @@ float64_t
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
struct exp32_sig64 { int_fast32_t exp; uint64_t sig; };
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t );
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t
|
||||
softfloat_roundPackToExtF80(
|
||||
bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t
|
||||
softfloat_normRoundPackToExtF80(
|
||||
bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t );
|
||||
@@ -181,6 +190,7 @@ extFloat80_t
|
||||
#define isNaNF128UI( a64, a0 ) (((~(a64) & UINT64_C( 0x7FFF000000000000 )) == 0) && (a0 || ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF ))))
|
||||
|
||||
struct exp32_sig128 { int_fast32_t exp; struct uint128 sig; };
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct exp32_sig128
|
||||
softfloat_normSubnormalF128Sig( uint_fast64_t, uint_fast64_t );
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ INLINE
|
||||
uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist )
|
||||
{ return a>>dist | ((a & (((uint_fast64_t) 1<<dist) - 1)) != 0); }
|
||||
#else
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist );
|
||||
#endif
|
||||
#endif
|
||||
@@ -74,6 +75,7 @@ INLINE uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist )
|
||||
(dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0);
|
||||
}
|
||||
#else
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist );
|
||||
#endif
|
||||
#endif
|
||||
@@ -95,6 +97,7 @@ INLINE uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist )
|
||||
(dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0);
|
||||
}
|
||||
#else
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist );
|
||||
#endif
|
||||
#endif
|
||||
@@ -148,6 +151,7 @@ INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a )
|
||||
return count;
|
||||
}
|
||||
#else
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint_fast8_t softfloat_countLeadingZeros32( uint32_t a );
|
||||
#endif
|
||||
#endif
|
||||
@@ -157,6 +161,7 @@ uint_fast8_t softfloat_countLeadingZeros32( uint32_t a );
|
||||
| Returns the number of leading 0 bits before the most-significant 1 bit of
|
||||
| 'a'. If 'a' is zero, 64 is returned.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint_fast8_t softfloat_countLeadingZeros64( uint64_t a );
|
||||
#endif
|
||||
|
||||
@@ -178,6 +183,7 @@ extern const uint16_t softfloat_approxRecip_1k1s[16];
|
||||
#ifdef SOFTFLOAT_FAST_DIV64TO32
|
||||
#define softfloat_approxRecip32_1( a ) ((uint32_t) (UINT64_C( 0x7FFFFFFFFFFFFFFF ) / (uint32_t) (a)))
|
||||
#else
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint32_t softfloat_approxRecip32_1( uint32_t a );
|
||||
#endif
|
||||
#endif
|
||||
@@ -204,6 +210,7 @@ extern const uint16_t softfloat_approxRecipSqrt_1k1s[16];
|
||||
| returned is also always within the range 0.5 to 1; thus, the most-
|
||||
| significant bit of the result is always set.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a );
|
||||
#endif
|
||||
|
||||
@@ -240,6 +247,7 @@ INLINE
|
||||
bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
|
||||
{ return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); }
|
||||
#else
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
|
||||
#endif
|
||||
#endif
|
||||
@@ -255,6 +263,7 @@ INLINE
|
||||
bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
|
||||
{ return (a64 < b64) || ((a64 == b64) && (a0 < b0)); }
|
||||
#else
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
|
||||
#endif
|
||||
#endif
|
||||
@@ -275,6 +284,7 @@ struct uint128
|
||||
return z;
|
||||
}
|
||||
#else
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128
|
||||
softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist );
|
||||
#endif
|
||||
@@ -296,6 +306,7 @@ struct uint128
|
||||
return z;
|
||||
}
|
||||
#else
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128
|
||||
softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist );
|
||||
#endif
|
||||
@@ -413,6 +424,7 @@ struct uint64_extra
|
||||
return z;
|
||||
}
|
||||
#else
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint64_extra
|
||||
softfloat_shiftRightJam64Extra(
|
||||
uint64_t a, uint64_t extra, uint_fast32_t dist );
|
||||
@@ -492,6 +504,7 @@ struct uint128
|
||||
return z;
|
||||
}
|
||||
#else
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128
|
||||
softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
|
||||
#endif
|
||||
@@ -528,6 +541,7 @@ struct uint128
|
||||
return z;
|
||||
}
|
||||
#else
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128
|
||||
softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
|
||||
#endif
|
||||
@@ -562,6 +576,7 @@ INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b )
|
||||
return z;
|
||||
}
|
||||
#else
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b );
|
||||
#endif
|
||||
#endif
|
||||
@@ -570,6 +585,7 @@ struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b );
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the 128-bit product of 'a' and 'b'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b );
|
||||
#endif
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef softfloat_add128
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128
|
||||
softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
|
||||
{
|
||||
|
||||
@@ -42,6 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
extern const uint16_t softfloat_approxRecip_1k0s[16];
|
||||
extern const uint16_t softfloat_approxRecip_1k1s[16];
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint32_t softfloat_approxRecip32_1( uint32_t a )
|
||||
{
|
||||
int index;
|
||||
|
||||
@@ -42,6 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
extern const uint16_t softfloat_approxRecipSqrt_1k0s[];
|
||||
extern const uint16_t softfloat_approxRecipSqrt_1k1s[];
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a )
|
||||
{
|
||||
int index;
|
||||
|
||||
@@ -44,6 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
| floating-point NaN, and returns the bit pattern of this value as an unsigned
|
||||
| integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr )
|
||||
{
|
||||
struct uint128 uiZ;
|
||||
|
||||
@@ -43,6 +43,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point
|
||||
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr )
|
||||
{
|
||||
struct uint128 uiZ;
|
||||
|
||||
@@ -42,6 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
| Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point
|
||||
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr )
|
||||
{
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
| Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point
|
||||
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr )
|
||||
{
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32
|
||||
#include "primitives.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint_fast8_t softfloat_countLeadingZeros32( uint32_t a )
|
||||
{
|
||||
uint_fast8_t count;
|
||||
|
||||
@@ -42,6 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64
|
||||
#include "primitives.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint_fast8_t softfloat_countLeadingZeros64( uint64_t a )
|
||||
{
|
||||
uint_fast8_t count;
|
||||
|
||||
@@ -46,6 +46,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
void
|
||||
softfloat_extF80UIToCommonNaN(
|
||||
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr )
|
||||
|
||||
@@ -47,6 +47,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
| pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid exception
|
||||
| is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
void
|
||||
softfloat_f128UIToCommonNaN(
|
||||
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr )
|
||||
|
||||
@@ -45,6 +45,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr )
|
||||
{
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr )
|
||||
{
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef softfloat_le128
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
|
||||
{
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef softfloat_lt128
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
|
||||
{
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef softfloat_mul64ByShifted32To128
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b )
|
||||
{
|
||||
uint_fast64_t mid;
|
||||
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef softfloat_mul64To128
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b )
|
||||
{
|
||||
uint32_t a32, a0, b32, b0;
|
||||
|
||||
@@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t
|
||||
softfloat_normRoundPackToExtF80(
|
||||
bool sign,
|
||||
|
||||
@@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t sig )
|
||||
{
|
||||
int_fast8_t shiftDist;
|
||||
|
||||
@@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct exp32_sig128
|
||||
softfloat_normSubnormalF128Sig( uint_fast64_t sig64, uint_fast64_t sig0 )
|
||||
{
|
||||
|
||||
@@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t sig )
|
||||
{
|
||||
int_fast8_t shiftDist;
|
||||
|
||||
@@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "platform.h"
|
||||
#include "internals.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t sig )
|
||||
{
|
||||
int_fast8_t shiftDist;
|
||||
|
||||
@@ -50,6 +50,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
| result. If either original floating-point value is a signaling NaN, the
|
||||
| invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128
|
||||
softfloat_propagateNaNExtF80UI(
|
||||
uint_fast16_t uiA64,
|
||||
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "internals.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t
|
||||
softfloat_roundPackToExtF80(
|
||||
bool sign,
|
||||
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "internals.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
float32_t
|
||||
softfloat_roundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig )
|
||||
{
|
||||
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "internals.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
float64_t
|
||||
softfloat_roundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig )
|
||||
{
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
int_fast32_t
|
||||
softfloat_roundToI32(
|
||||
bool sign, uint_fast64_t sig, uint_fast8_t roundingMode, bool exact )
|
||||
|
||||
@@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "specialize.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
int_fast64_t
|
||||
softfloat_roundToI64(
|
||||
bool sign,
|
||||
|
||||
@@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef softfloat_shiftRightJam32
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist )
|
||||
{
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef softfloat_shiftRightJam64
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist )
|
||||
{
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef softfloat_shiftRightJam64Extra
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint64_extra
|
||||
softfloat_shiftRightJam64Extra(
|
||||
uint64_t a, uint64_t extra, uint_fast32_t dist )
|
||||
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef softfloat_shortShiftLeft128
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128
|
||||
softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
|
||||
{
|
||||
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef softfloat_shortShiftRight128
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128
|
||||
softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
|
||||
{
|
||||
|
||||
@@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef softfloat_shortShiftRightJam64
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist )
|
||||
{
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef softfloat_sub128
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128
|
||||
softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
|
||||
{
|
||||
|
||||
@@ -92,6 +92,7 @@ enum {
|
||||
/*----------------------------------------------------------------------------
|
||||
| Routine to raise any or all of the software floating-point exception flags.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
void softfloat_raiseFlags( uint_fast8_t );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
@@ -110,6 +111,7 @@ float16_t ui64_to_f16( uint64_t );
|
||||
float32_t ui64_to_f32( uint64_t );
|
||||
float64_t ui64_to_f64( uint64_t );
|
||||
#ifdef SOFTFLOAT_FAST_INT64
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t ui64_to_extF80( uint64_t );
|
||||
float128_t ui64_to_f128( uint64_t );
|
||||
#endif
|
||||
@@ -119,6 +121,7 @@ float16_t i32_to_f16( int32_t );
|
||||
float32_t i32_to_f32( int32_t );
|
||||
float64_t i32_to_f64( int32_t );
|
||||
#ifdef SOFTFLOAT_FAST_INT64
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t i32_to_extF80( int32_t );
|
||||
float128_t i32_to_f128( int32_t );
|
||||
#endif
|
||||
@@ -183,6 +186,7 @@ int_fast64_t f32_to_i64_r_minMag( float32_t, bool );
|
||||
float16_t f32_to_f16( float32_t );
|
||||
float64_t f32_to_f64( float32_t );
|
||||
#ifdef SOFTFLOAT_FAST_INT64
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t f32_to_extF80( float32_t );
|
||||
float128_t f32_to_f128( float32_t );
|
||||
#endif
|
||||
@@ -218,6 +222,7 @@ int_fast64_t f64_to_i64_r_minMag( float64_t, bool );
|
||||
float16_t f64_to_f16( float64_t );
|
||||
float32_t f64_to_f32( float64_t );
|
||||
#ifdef SOFTFLOAT_FAST_INT64
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t f64_to_extF80( float64_t );
|
||||
float128_t f64_to_f128( float64_t );
|
||||
#endif
|
||||
@@ -250,26 +255,41 @@ extern THREAD_LOCAL uint_fast8_t extF80_roundingPrecision;
|
||||
*----------------------------------------------------------------------------*/
|
||||
#ifdef SOFTFLOAT_FAST_INT64
|
||||
uint_fast32_t extF80_to_ui32( extFloat80_t, uint_fast8_t, bool );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint_fast64_t extF80_to_ui64( extFloat80_t, uint_fast8_t, bool );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
int_fast32_t extF80_to_i32( extFloat80_t, uint_fast8_t, bool );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
int_fast64_t extF80_to_i64( extFloat80_t, uint_fast8_t, bool );
|
||||
uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t, bool );
|
||||
uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t, bool );
|
||||
int_fast32_t extF80_to_i32_r_minMag( extFloat80_t, bool );
|
||||
int_fast64_t extF80_to_i64_r_minMag( extFloat80_t, bool );
|
||||
float16_t extF80_to_f16( extFloat80_t );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
float32_t extF80_to_f32( extFloat80_t );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
float64_t extF80_to_f64( extFloat80_t );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
float128_t extF80_to_f128( extFloat80_t );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t extF80_roundToInt( extFloat80_t, uint_fast8_t, bool );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t extF80_add( extFloat80_t, extFloat80_t );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t extF80_sub( extFloat80_t, extFloat80_t );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t extF80_mul( extFloat80_t, extFloat80_t );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t extF80_div( extFloat80_t, extFloat80_t );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t extF80_rem( extFloat80_t, extFloat80_t );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t extF80_sqrt( extFloat80_t );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
bool extF80_eq( extFloat80_t, extFloat80_t );
|
||||
bool extF80_le( extFloat80_t, extFloat80_t );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
bool extF80_lt( extFloat80_t, extFloat80_t );
|
||||
bool extF80_eq_signaling( extFloat80_t, extFloat80_t );
|
||||
bool extF80_le_quiet( extFloat80_t, extFloat80_t );
|
||||
@@ -320,6 +340,7 @@ int_fast64_t f128_to_i64_r_minMag( float128_t, bool );
|
||||
float16_t f128_to_f16( float128_t );
|
||||
float32_t f128_to_f32( float128_t );
|
||||
float64_t f128_to_f64( float128_t );
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t f128_to_extF80( float128_t );
|
||||
float128_t f128_roundToInt( float128_t, uint_fast8_t, bool );
|
||||
float128_t f128_add( float128_t, float128_t );
|
||||
|
||||
@@ -43,6 +43,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
| to substitute a result value. If traps are not implemented, this routine
|
||||
| should be simply `softfloat_exceptionFlags |= flags;'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
void softfloat_raiseFlags( uint_fast8_t flags )
|
||||
{
|
||||
|
||||
|
||||
@@ -135,12 +135,14 @@ uint_fast16_t
|
||||
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point
|
||||
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
@@ -170,12 +172,14 @@ uint_fast32_t
|
||||
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point
|
||||
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
@@ -215,6 +219,7 @@ uint_fast64_t
|
||||
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
void
|
||||
softfloat_extF80UIToCommonNaN(
|
||||
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
|
||||
@@ -224,6 +229,7 @@ void
|
||||
| floating-point NaN, and returns the bit pattern of this value as an unsigned
|
||||
| integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
@@ -235,6 +241,7 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
|
||||
| result. If either original floating-point value is a signaling NaN, the
|
||||
| invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128
|
||||
softfloat_propagateNaNExtF80UI(
|
||||
uint_fast16_t uiA64,
|
||||
@@ -264,6 +271,7 @@ struct uint128
|
||||
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
|
||||
| is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
void
|
||||
softfloat_f128UIToCommonNaN(
|
||||
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
|
||||
@@ -272,6 +280,7 @@ void
|
||||
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
|
||||
| NaN, and returns the bit pattern of this value as an unsigned integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
||||
@@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "internals.h"
|
||||
#include "softfloat.h"
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
extFloat80_t ui64_to_extF80( uint64_t a )
|
||||
{
|
||||
uint_fast16_t uiZ64;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/Utils/BitUtils.h>
|
||||
@@ -62,6 +63,7 @@ struct FEX_PACKED X80SoftFloat {
|
||||
}
|
||||
|
||||
// Ops
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FADD(X80SoftFloat const &lhs, X80SoftFloat const &rhs) {
|
||||
#ifdef DEBUG_X86_FLOAT
|
||||
BIGFLOAT Result;
|
||||
@@ -83,6 +85,7 @@ struct FEX_PACKED X80SoftFloat {
|
||||
#endif
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FSUB(X80SoftFloat const &lhs, X80SoftFloat const &rhs) {
|
||||
#ifdef DEBUG_X86_FLOAT
|
||||
BIGFLOAT Result;
|
||||
@@ -104,6 +107,7 @@ struct FEX_PACKED X80SoftFloat {
|
||||
#endif
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FMUL(X80SoftFloat const &lhs, X80SoftFloat const &rhs) {
|
||||
#ifdef DEBUG_X86_FLOAT
|
||||
BIGFLOAT Result;
|
||||
@@ -125,6 +129,7 @@ struct FEX_PACKED X80SoftFloat {
|
||||
#endif
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FDIV(X80SoftFloat const &lhs, X80SoftFloat const &rhs) {
|
||||
#ifdef DEBUG_X86_FLOAT
|
||||
BIGFLOAT Result;
|
||||
@@ -146,6 +151,7 @@ struct FEX_PACKED X80SoftFloat {
|
||||
#endif
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FREM(X80SoftFloat const &lhs, X80SoftFloat const &rhs) {
|
||||
#if defined(DEBUG_X86_FLOAT)
|
||||
BIGFLOAT Result;
|
||||
@@ -168,6 +174,7 @@ struct FEX_PACKED X80SoftFloat {
|
||||
#endif
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FREM1(X80SoftFloat const &lhs, X80SoftFloat const &rhs) {
|
||||
#if defined(DEBUG_X86_FLOAT)
|
||||
BIGFLOAT Result;
|
||||
@@ -190,14 +197,17 @@ struct FEX_PACKED X80SoftFloat {
|
||||
#endif
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FRNDINT(X80SoftFloat const &lhs) {
|
||||
return extF80_roundToInt(lhs, softfloat_roundingMode, false);
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FRNDINT(X80SoftFloat const &lhs, uint_fast8_t RoundMode) {
|
||||
return extF80_roundToInt(lhs, RoundMode, false);
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FXTRACT_SIG(X80SoftFloat const &lhs) {
|
||||
#if defined(DEBUG_X86_FLOAT)
|
||||
BIGFLOAT Result;
|
||||
@@ -221,6 +231,7 @@ struct FEX_PACKED X80SoftFloat {
|
||||
#endif
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FXTRACT_EXP(X80SoftFloat const &lhs) {
|
||||
#if defined(DEBUG_X86_FLOAT)
|
||||
BIGFLOAT Result;
|
||||
@@ -242,12 +253,14 @@ struct FEX_PACKED X80SoftFloat {
|
||||
#endif
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static void FCMP(X80SoftFloat const &lhs, X80SoftFloat const &rhs, bool *eq, bool *lt, bool *nan) {
|
||||
*eq = extF80_eq(lhs, rhs);
|
||||
*lt = extF80_lt(lhs, rhs);
|
||||
*nan = IsNan(lhs) || IsNan(rhs);
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FSCALE(X80SoftFloat const &lhs, X80SoftFloat const &rhs) {
|
||||
WARN_ONCE_FMT("x87: Application used FSCALE which may have accuracy problems");
|
||||
#ifdef DEBUG_X86_FLOAT
|
||||
@@ -276,6 +289,7 @@ struct FEX_PACKED X80SoftFloat {
|
||||
#endif
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat F2XM1(X80SoftFloat const &lhs) {
|
||||
WARN_ONCE_FMT("x87: Application used F2XM1 which may have accuracy problems");
|
||||
#ifdef DEBUG_X86_FLOAT
|
||||
@@ -299,6 +313,7 @@ struct FEX_PACKED X80SoftFloat {
|
||||
#endif
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FYL2X(X80SoftFloat const &lhs, X80SoftFloat const &rhs) {
|
||||
WARN_ONCE_FMT("x87: Application used FYL2X which may have accuracy problems");
|
||||
#ifdef DEBUG_X86_FLOAT
|
||||
@@ -324,6 +339,7 @@ struct FEX_PACKED X80SoftFloat {
|
||||
#endif
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FATAN(X80SoftFloat const &lhs, X80SoftFloat const &rhs) {
|
||||
WARN_ONCE_FMT("x87: Application used FATAN which may have accuracy problems");
|
||||
#ifdef DEBUG_X86_FLOAT
|
||||
@@ -349,6 +365,7 @@ struct FEX_PACKED X80SoftFloat {
|
||||
#endif
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FTAN(X80SoftFloat const &lhs) {
|
||||
WARN_ONCE_FMT("x87: Application used FTAN which may have accuracy problems");
|
||||
#ifdef DEBUG_X86_FLOAT
|
||||
@@ -372,6 +389,7 @@ struct FEX_PACKED X80SoftFloat {
|
||||
#endif
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FSIN(X80SoftFloat const &lhs) {
|
||||
WARN_ONCE_FMT("x87: Application used FSIN which may have accuracy problems");
|
||||
#ifdef DEBUG_X86_FLOAT
|
||||
@@ -394,6 +412,7 @@ struct FEX_PACKED X80SoftFloat {
|
||||
#endif
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FCOS(X80SoftFloat const &lhs) {
|
||||
WARN_ONCE_FMT("x87: Application used FCOS which may have accuracy problems");
|
||||
#ifdef DEBUG_X86_FLOAT
|
||||
@@ -416,6 +435,7 @@ struct FEX_PACKED X80SoftFloat {
|
||||
#endif
|
||||
}
|
||||
|
||||
FEXCORE_PRESERVE_ALL_ATTR
|
||||
static X80SoftFloat FSQRT(X80SoftFloat const &lhs) {
|
||||
#ifdef DEBUG_X86_FLOAT
|
||||
BIGFLOAT Result;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
#include <FEXCore/fextl/string.h>
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
#include <FEXCore/fextl/string.h>
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include "Common/StringConv.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "FEXCore/Utils/EnumUtils.h"
|
||||
@@ -334,16 +335,11 @@ namespace DefaultValues {
|
||||
// Sanitize Core option
|
||||
FEX_CONFIG_OPT(Core, CORE);
|
||||
#if (_M_X86_64)
|
||||
constexpr uint32_t MaxCoreNumber = 2;
|
||||
#else
|
||||
constexpr uint32_t MaxCoreNumber = 1;
|
||||
#endif
|
||||
#ifdef INTERPRETER_ENABLED
|
||||
constexpr uint32_t MinCoreNumber = 0;
|
||||
#else
|
||||
constexpr uint32_t MinCoreNumber = 1;
|
||||
constexpr uint32_t MaxCoreNumber = 0;
|
||||
#endif
|
||||
if (Core > MaxCoreNumber || Core < MinCoreNumber) {
|
||||
if (Core > MaxCoreNumber) {
|
||||
// Sanitize the core option by setting the core to the JIT if invalid
|
||||
FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_CORE, fextl::fmt::format("{}", static_cast<uint32_t>(FEXCore::Config::CONFIG_IRJIT)));
|
||||
}
|
||||
@@ -352,11 +348,6 @@ namespace DefaultValues {
|
||||
if (FEXCore::Config::Exists(FEXCore::Config::CONFIG_CACHEOBJECTCODECOMPILATION)) {
|
||||
FEX_CONFIG_OPT(CacheObjectCodeCompilation, CACHEOBJECTCODECOMPILATION);
|
||||
FEX_CONFIG_OPT(Core, CORE);
|
||||
|
||||
if (CacheObjectCodeCompilation() && Core() == FEXCore::Config::CONFIG_INTERPRETER) {
|
||||
// If running the interpreter then disable cache code compilation
|
||||
FEXCore::Config::Erase(FEXCore::Config::CONFIG_CACHEOBJECTCODECOMPILATION);
|
||||
}
|
||||
}
|
||||
|
||||
fextl::string ContainerPrefix { FindContainerPrefix() };
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
"Default": "FEXCore::Config::ConfigCore::CONFIG_IRJIT",
|
||||
"TextDefault": "irjit",
|
||||
"ShortArg": "c",
|
||||
"Choices": [ "irint", "irjit", "host" ],
|
||||
"Choices": [ "irjit", "host" ],
|
||||
"ArgumentHandler": "CoreHandler",
|
||||
"Desc": [
|
||||
"Which CPU core to use",
|
||||
"host only exists on x86_64",
|
||||
"[irint, irjit, host]"
|
||||
"[irjit, host]"
|
||||
]
|
||||
},
|
||||
"Multiblock": {
|
||||
@@ -59,6 +59,8 @@
|
||||
"DISABLESVE": "disablesve",
|
||||
"ENABLEAVX": "enableavx",
|
||||
"DISABLEAVX": "disableavx",
|
||||
"ENABLEAVX2": "enableavx2",
|
||||
"DISABLEAVX2": "disableavx2",
|
||||
"ENABLEAFP": "enableafp",
|
||||
"DISABLEAFP": "disableafp",
|
||||
"ENABLELRCPC": "enablelrcpc",
|
||||
@@ -76,13 +78,18 @@
|
||||
"ENABLEATOMICS": "enableatomics",
|
||||
"DISABLEATOMICS": "disableatomics",
|
||||
"ENABLEFCMA": "enablefcma",
|
||||
"DISABLEFCMA": "disablefcma"
|
||||
"DISABLEFCMA": "disablefcma",
|
||||
"ENABLEFLAGM": "enableflagm",
|
||||
"DISABLEFLAGM": "disableflagm",
|
||||
"ENABLEFLAGM2": "enableflagm2",
|
||||
"DISABLEFLAGM2": "disableflagm2"
|
||||
},
|
||||
"Desc": [
|
||||
"Allows controlling of the CPU features in the JIT.",
|
||||
"\toff: Default CPU features queried from CPU features",
|
||||
"\t{enable,disable}sve: Will force enable or disable sve even if the host doesn't support it",
|
||||
"\t{enable,disable}avx: Will force enable or disable avx even if the host doesn't support it",
|
||||
"\t{enable,disable}avx2: Will force enable or disable avx2 even if the host doesn't support it",
|
||||
"\t{enable,disable}afp: Will force enable or disable afp even if the host doesn't support it",
|
||||
"\t{enable,disable}lrcpc: Will force enable or disable lrcpc even if the host doesn't support it",
|
||||
"\t{enable,disable}lrcpc2: Will force enable or disable lrcpc2 even if the host doesn't support it",
|
||||
@@ -91,7 +98,9 @@
|
||||
"\t{enable,disable}rng: Will force enable or disable rng even if the host doesn't support it",
|
||||
"\t{enable,disable}clzero: Will force enable or disable clzero even if the host doesn't support it",
|
||||
"\t{enable,disable}atomics: Will force enable or disable ARMv8.1 LSE atomics even if the host doesn't support it",
|
||||
"\t{enable,disable}fcma: Will force enable or disable fcma even if the host doesn't support it"
|
||||
"\t{enable,disable}fcma: Will force enable or disable fcma even if the host doesn't support it",
|
||||
"\t{enable,disable}flagm: Will force enable or disable flagm even if the host doesn't support it",
|
||||
"\t{enable,disable}flagm2: Will force enable or disable flagm2 even if the host doesn't support it"
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -490,6 +499,15 @@
|
||||
"IS64BIT_MODE": {
|
||||
"Type": "bool",
|
||||
"Default": "false"
|
||||
},
|
||||
"DISABLE_VIXL_INDIRECT_RUNTIME_CALLS": {
|
||||
"Type": "bool",
|
||||
"Default": "true",
|
||||
"Desc": [
|
||||
"This option is used for the InstructionCountCI so it can generate the same codegen between Arm64 hosts and vixl simulator hosts.",
|
||||
"Vixl simulator indirect runtime calls are a special hlt instruction with metadata after it. Effectively making a custom call instruction.",
|
||||
"With visual simulator calls disabled, the code generation would be the same as on a native Arm64 host, but running the code is broken."
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include "Interface/Context/Context.h"
|
||||
#include "Interface/Core/OpcodeDispatcher.h"
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "Common/JitSymbols.h"
|
||||
@@ -45,7 +46,6 @@ namespace CodeSerialize {
|
||||
namespace CPU {
|
||||
class Arm64JITCore;
|
||||
class X86JITCore;
|
||||
class InterpreterCore;
|
||||
class Dispatcher;
|
||||
}
|
||||
namespace HLE {
|
||||
@@ -87,6 +87,8 @@ namespace FEXCore::Context {
|
||||
|
||||
ExitReason RunUntilExit() override;
|
||||
|
||||
void ExecuteThread(FEXCore::Core::InternalThreadState *Thread) override;
|
||||
|
||||
void CompileRIP(FEXCore::Core::InternalThreadState *Thread, uint64_t GuestRIP) override;
|
||||
|
||||
int GetProgramStatus() const override;
|
||||
@@ -204,7 +206,6 @@ namespace FEXCore::Context {
|
||||
friend class FEXCore::CPU::X86JITCore;
|
||||
#endif
|
||||
|
||||
friend class FEXCore::CPU::InterpreterCore;
|
||||
friend class FEXCore::IR::Validation::IRValidation;
|
||||
|
||||
struct {
|
||||
@@ -240,6 +241,7 @@ namespace FEXCore::Context {
|
||||
FEX_CONFIG_OPT(CacheObjectCodeCompilation, CACHEOBJECTCODECOMPILATION);
|
||||
FEX_CONFIG_OPT(x87ReducedPrecision, X87REDUCEDPRECISION);
|
||||
FEX_CONFIG_OPT(DisableTelemetry, DISABLETELEMETRY);
|
||||
FEX_CONFIG_OPT(DisableVixlIndirectCalls, DISABLE_VIXL_INDIRECT_RUNTIME_CALLS);
|
||||
} Config;
|
||||
|
||||
FEXCore::HostFeatures HostFeatures;
|
||||
@@ -378,6 +380,20 @@ namespace FEXCore::Context {
|
||||
UpdateAtomicTSOEmulationConfig();
|
||||
}
|
||||
|
||||
// Returns if Software TSO emulation is required.
|
||||
// NOTE: This doesn't necessary return if Atomic-based TSO is currently enabled.
|
||||
// This will still return true if on a single thread and TSO is currently disabled.
|
||||
//
|
||||
// This is to ensure that if early initialization checks CPU features and TSO /could/ be enabled, that
|
||||
// we return consistent results.
|
||||
//
|
||||
// To check if Atomic TSO is currently enabled in the JIT, use `IsAtomicTSOEnabled` instead.
|
||||
bool SoftwareTSORequired() const {
|
||||
if (SupportsHardwareTSO) return false;
|
||||
|
||||
return Config.TSOEnabled;
|
||||
}
|
||||
|
||||
void EnableExitOnHLT() override { ExitOnHLT = true; }
|
||||
|
||||
bool ExitOnHLTEnabled() const { return ExitOnHLT; }
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include "Interface/Core/ArchHelpers/Arm64Emitter.h"
|
||||
#include "FEXCore/Utils/AllocatorHooks.h"
|
||||
#include "Interface/Core/ArchHelpers/CodeEmitter/Emitter.h"
|
||||
#include "Interface/Core/ArchHelpers/CodeEmitter/Registers.h"
|
||||
#include "Interface/Core/Dispatcher/Dispatcher.h"
|
||||
#include "Interface/Context/Context.h"
|
||||
#include "Interface/HLE/Thunks/Thunks.h"
|
||||
@@ -66,11 +68,102 @@ namespace x64 {
|
||||
};
|
||||
|
||||
// v8..v15 = (lower 64bits) Callee saved
|
||||
constexpr std::array<FEXCore::ARMEmitter::VRegister, 12> RAFPR = {
|
||||
// v0 ~ v3 are used as temps.
|
||||
constexpr std::array<FEXCore::ARMEmitter::VRegister, 14> RAFPR = {
|
||||
// v0 ~ v1 are used as temps.
|
||||
// FEXCore::ARMEmitter::VReg::v0, FEXCore::ARMEmitter::VReg::v1,
|
||||
// FEXCore::ARMEmitter::VReg::v2, FEXCore::ARMEmitter::VReg::v3,
|
||||
|
||||
FEXCore::ARMEmitter::VReg::v2, FEXCore::ARMEmitter::VReg::v3,
|
||||
FEXCore::ARMEmitter::VReg::v4, FEXCore::ARMEmitter::VReg::v5,
|
||||
FEXCore::ARMEmitter::VReg::v6, FEXCore::ARMEmitter::VReg::v7,
|
||||
FEXCore::ARMEmitter::VReg::v8, FEXCore::ARMEmitter::VReg::v9,
|
||||
FEXCore::ARMEmitter::VReg::v10, FEXCore::ARMEmitter::VReg::v11,
|
||||
FEXCore::ARMEmitter::VReg::v12, FEXCore::ARMEmitter::VReg::v13,
|
||||
FEXCore::ARMEmitter::VReg::v14, FEXCore::ARMEmitter::VReg::v15,
|
||||
};
|
||||
|
||||
// I wish this could get constexpr generated from SRA's definition but impossible until libstdc++12, libc++15.
|
||||
// SRA GPRs that need to be spilled when calling a function with `preserve_all` ABI.
|
||||
constexpr std::array<FEXCore::ARMEmitter::Register, 7> PreserveAll_SRA = {
|
||||
FEXCore::ARMEmitter::Reg::r4, FEXCore::ARMEmitter::Reg::r5,
|
||||
FEXCore::ARMEmitter::Reg::r6, FEXCore::ARMEmitter::Reg::r7,
|
||||
FEXCore::ARMEmitter::Reg::r8,
|
||||
FEXCore::ARMEmitter::Reg::r16, FEXCore::ARMEmitter::Reg::r17,
|
||||
};
|
||||
|
||||
constexpr uint32_t PreserveAll_SRAMask = {
|
||||
[]() -> uint32_t {
|
||||
uint32_t Mask{};
|
||||
for (auto Reg : PreserveAll_SRA) {
|
||||
switch (Reg.Idx()) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 16:
|
||||
case 17:
|
||||
Mask |= (1U << Reg.Idx());
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
return Mask;
|
||||
}()
|
||||
};
|
||||
|
||||
// Dynamic GPRs
|
||||
constexpr std::array<FEXCore::ARMEmitter::Register, 1> PreserveAll_Dynamic = {
|
||||
// Only LR needs to get saved.
|
||||
FEXCore::ARMEmitter::Reg::r30
|
||||
};
|
||||
|
||||
// SRA FPRs that need to be spilled when calling a function with `preserve_all` ABI.
|
||||
constexpr std::array<FEXCore::ARMEmitter::Register, 0> PreserveAll_SRAFPR = {
|
||||
// None.
|
||||
};
|
||||
|
||||
constexpr uint32_t PreserveAll_SRAFPRMask = {
|
||||
[]() -> uint32_t {
|
||||
uint32_t Mask{};
|
||||
for (auto Reg : PreserveAll_SRAFPR) {
|
||||
Mask |= (1U << Reg.Idx());
|
||||
}
|
||||
return Mask;
|
||||
}()
|
||||
};
|
||||
|
||||
// Dynamic FPRs
|
||||
// - v0-v7
|
||||
constexpr std::array<FEXCore::ARMEmitter::VRegister, 6> PreserveAll_DynamicFPR = {
|
||||
// v0 ~ v1 are temps
|
||||
FEXCore::ARMEmitter::VReg::v2, FEXCore::ARMEmitter::VReg::v3,
|
||||
FEXCore::ARMEmitter::VReg::v4, FEXCore::ARMEmitter::VReg::v5,
|
||||
FEXCore::ARMEmitter::VReg::v6, FEXCore::ARMEmitter::VReg::v7,
|
||||
};
|
||||
|
||||
// SRA FPRs that need to be spilled when the host supports SVE-256bit with `preserve_all` ABI.
|
||||
// This is /all/ of the SRA registers
|
||||
constexpr std::array<FEXCore::ARMEmitter::VRegister, 16> PreserveAll_SRAFPRSVE = SRAFPR;
|
||||
|
||||
constexpr uint32_t PreserveAll_SRAFPRSVEMask = {
|
||||
[]() -> uint32_t {
|
||||
uint32_t Mask{};
|
||||
for (auto Reg : PreserveAll_SRAFPRSVE) {
|
||||
Mask |= (1U << Reg.Idx());
|
||||
}
|
||||
return Mask;
|
||||
}()
|
||||
};
|
||||
|
||||
// Dynamic FPRs when the host supports SVE-256bit.
|
||||
constexpr std::array<FEXCore::ARMEmitter::VRegister, 14> PreserveAll_DynamicFPRSVE = {
|
||||
// v0 ~ v1 are used as temps.
|
||||
FEXCore::ARMEmitter::VReg::v2, FEXCore::ARMEmitter::VReg::v3,
|
||||
FEXCore::ARMEmitter::VReg::v4, FEXCore::ARMEmitter::VReg::v5,
|
||||
FEXCore::ARMEmitter::VReg::v6, FEXCore::ARMEmitter::VReg::v7,
|
||||
FEXCore::ARMEmitter::VReg::v8, FEXCore::ARMEmitter::VReg::v9,
|
||||
@@ -127,11 +220,106 @@ namespace x32 {
|
||||
};
|
||||
|
||||
// v8..v15 = (lower 64bits) Callee saved
|
||||
constexpr std::array<FEXCore::ARMEmitter::VRegister, 20> RAFPR = {
|
||||
// v0 ~ v3 are used as temps.
|
||||
constexpr std::array<FEXCore::ARMEmitter::VRegister, 22> RAFPR = {
|
||||
// v0 ~ v1 are used as temps.
|
||||
// FEXCore::ARMEmitter::VReg::v0, FEXCore::ARMEmitter::VReg::v1,
|
||||
// FEXCore::ARMEmitter::VReg::v2, FEXCore::ARMEmitter::VReg::v3,
|
||||
|
||||
FEXCore::ARMEmitter::VReg::v2, FEXCore::ARMEmitter::VReg::v3,
|
||||
FEXCore::ARMEmitter::VReg::v4, FEXCore::ARMEmitter::VReg::v5,
|
||||
FEXCore::ARMEmitter::VReg::v6, FEXCore::ARMEmitter::VReg::v7,
|
||||
FEXCore::ARMEmitter::VReg::v8, FEXCore::ARMEmitter::VReg::v9,
|
||||
FEXCore::ARMEmitter::VReg::v10, FEXCore::ARMEmitter::VReg::v11,
|
||||
FEXCore::ARMEmitter::VReg::v12, FEXCore::ARMEmitter::VReg::v13,
|
||||
FEXCore::ARMEmitter::VReg::v14, FEXCore::ARMEmitter::VReg::v15,
|
||||
|
||||
FEXCore::ARMEmitter::VReg::v24, FEXCore::ARMEmitter::VReg::v25,
|
||||
FEXCore::ARMEmitter::VReg::v26, FEXCore::ARMEmitter::VReg::v27,
|
||||
FEXCore::ARMEmitter::VReg::v28, FEXCore::ARMEmitter::VReg::v29,
|
||||
FEXCore::ARMEmitter::VReg::v30, FEXCore::ARMEmitter::VReg::v31
|
||||
};
|
||||
|
||||
// I wish this could get constexpr generated from SRA's definition but impossible until libstdc++12, libc++15.
|
||||
// SRA GPRs that need to be spilled when calling a function with `preserve_all` ABI.
|
||||
constexpr std::array<FEXCore::ARMEmitter::Register, 5> PreserveAll_SRA = {
|
||||
FEXCore::ARMEmitter::Reg::r4, FEXCore::ARMEmitter::Reg::r5,
|
||||
FEXCore::ARMEmitter::Reg::r6, FEXCore::ARMEmitter::Reg::r7,
|
||||
FEXCore::ARMEmitter::Reg::r8,
|
||||
};
|
||||
|
||||
constexpr uint32_t PreserveAll_SRAMask = {
|
||||
[]() -> uint32_t {
|
||||
uint32_t Mask{};
|
||||
for (auto Reg : PreserveAll_SRA) {
|
||||
switch (Reg.Idx()) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 16:
|
||||
case 17:
|
||||
Mask |= (1U << Reg.Idx());
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
return Mask;
|
||||
}()
|
||||
};
|
||||
|
||||
// Dynamic GPRs
|
||||
constexpr std::array<FEXCore::ARMEmitter::Register, 3> PreserveAll_Dynamic = {
|
||||
FEXCore::ARMEmitter::Reg::r16, FEXCore::ARMEmitter::Reg::r17,
|
||||
FEXCore::ARMEmitter::Reg::r30
|
||||
};
|
||||
|
||||
// SRA FPRs that need to be spilled when calling a function with `preserve_all` ABI.
|
||||
constexpr std::array<FEXCore::ARMEmitter::Register, 0> PreserveAll_SRAFPR = {
|
||||
// None.
|
||||
};
|
||||
|
||||
constexpr uint32_t PreserveAll_SRAFPRMask = {
|
||||
[]() -> uint32_t {
|
||||
uint32_t Mask{};
|
||||
for (auto Reg : PreserveAll_SRAFPR) {
|
||||
Mask |= (1U << Reg.Idx());
|
||||
}
|
||||
return Mask;
|
||||
}()
|
||||
};
|
||||
|
||||
// Dynamic FPRs
|
||||
// - v0-v7
|
||||
constexpr std::array<FEXCore::ARMEmitter::VRegister, 6> PreserveAll_DynamicFPR = {
|
||||
// v0 ~ v1 are temps
|
||||
FEXCore::ARMEmitter::VReg::v2, FEXCore::ARMEmitter::VReg::v3,
|
||||
FEXCore::ARMEmitter::VReg::v4, FEXCore::ARMEmitter::VReg::v5,
|
||||
FEXCore::ARMEmitter::VReg::v6, FEXCore::ARMEmitter::VReg::v7,
|
||||
};
|
||||
|
||||
// SRA FPRs that need to be spilled when the host supports SVE-256bit with `preserve_all` ABI.
|
||||
// This is /all/ of the SRA registers
|
||||
constexpr std::array<FEXCore::ARMEmitter::VRegister, 8> PreserveAll_SRAFPRSVE = SRAFPR;
|
||||
|
||||
constexpr uint32_t PreserveAll_SRAFPRSVEMask = {
|
||||
[]() -> uint32_t {
|
||||
uint32_t Mask{};
|
||||
for (auto Reg : PreserveAll_SRAFPRSVE) {
|
||||
Mask |= (1U << Reg.Idx());
|
||||
}
|
||||
return Mask;
|
||||
}()
|
||||
};
|
||||
|
||||
// Dynamic FPRs when the host supports SVE-256bit.
|
||||
constexpr std::array<FEXCore::ARMEmitter::VRegister, 22> PreserveAll_DynamicFPRSVE = {
|
||||
// v0 ~ v1 are used as temps.
|
||||
FEXCore::ARMEmitter::VReg::v2, FEXCore::ARMEmitter::VReg::v3,
|
||||
FEXCore::ARMEmitter::VReg::v4, FEXCore::ARMEmitter::VReg::v5,
|
||||
FEXCore::ARMEmitter::VReg::v6, FEXCore::ARMEmitter::VReg::v7,
|
||||
FEXCore::ARMEmitter::VReg::v8, FEXCore::ARMEmitter::VReg::v9,
|
||||
@@ -532,6 +720,107 @@ void Arm64Emitter::FillStaticRegs(bool FPRs, uint32_t GPRFillMask, uint32_t FPRF
|
||||
}
|
||||
}
|
||||
|
||||
void Arm64Emitter::PushVectorRegisters(FEXCore::ARMEmitter::Register TmpReg, bool SVERegs, std::span<const FEXCore::ARMEmitter::VRegister> VRegs) {
|
||||
if (SVERegs) {
|
||||
size_t i = 0;
|
||||
|
||||
for (; i < (VRegs.size() % 4); i += 2) {
|
||||
const auto Reg1 = VRegs[i];
|
||||
const auto Reg2 = VRegs[i + 1];
|
||||
st2b(Reg1.Z(), Reg2.Z(), PRED_TMP_32B, TmpReg, 0);
|
||||
add(ARMEmitter::Size::i64Bit, TmpReg, TmpReg, 32 * 2);
|
||||
}
|
||||
|
||||
for (; i < VRegs.size(); i += 4) {
|
||||
const auto Reg1 = VRegs[i];
|
||||
const auto Reg2 = VRegs[i + 1];
|
||||
const auto Reg3 = VRegs[i + 2];
|
||||
const auto Reg4 = VRegs[i + 3];
|
||||
st4b(Reg1.Z(), Reg2.Z(), Reg3.Z(), Reg4.Z(), PRED_TMP_32B, TmpReg, 0);
|
||||
add(ARMEmitter::Size::i64Bit, TmpReg, TmpReg, 32 * 4);
|
||||
}
|
||||
}
|
||||
else {
|
||||
size_t i = 0;
|
||||
for (; i < (VRegs.size() % 4); i += 2) {
|
||||
const auto Reg1 = VRegs[i];
|
||||
const auto Reg2 = VRegs[i + 1];
|
||||
st1<ARMEmitter::SubRegSize::i64Bit>(Reg1.Q(), Reg2.Q(), TmpReg, 32);
|
||||
}
|
||||
|
||||
for (; i < VRegs.size(); i += 4) {
|
||||
const auto Reg1 = VRegs[i];
|
||||
const auto Reg2 = VRegs[i + 1];
|
||||
const auto Reg3 = VRegs[i + 2];
|
||||
const auto Reg4 = VRegs[i + 3];
|
||||
st1<ARMEmitter::SubRegSize::i64Bit>(Reg1.Q(), Reg2.Q(), Reg3.Q(), Reg4.Q(), TmpReg, 64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arm64Emitter::PushGeneralRegisters(FEXCore::ARMEmitter::Register TmpReg, std::span<const FEXCore::ARMEmitter::Register> Regs) {
|
||||
size_t i = 0;
|
||||
for (; i < (Regs.size() % 2); ++i) {
|
||||
const auto Reg1 = Regs[i];
|
||||
str<ARMEmitter::IndexType::POST>(Reg1.X(), TmpReg, 16);
|
||||
}
|
||||
|
||||
for (; i < Regs.size(); i += 2) {
|
||||
const auto Reg1 = Regs[i];
|
||||
const auto Reg2 = Regs[i + 1];
|
||||
stp<ARMEmitter::IndexType::POST>(Reg1.X(), Reg2.X(), TmpReg, 16);
|
||||
}
|
||||
}
|
||||
|
||||
void Arm64Emitter::PopVectorRegisters(bool SVERegs, std::span<const FEXCore::ARMEmitter::VRegister> VRegs) {
|
||||
if (SVERegs) {
|
||||
size_t i = 0;
|
||||
for (; i < (VRegs.size() % 4); i += 2) {
|
||||
const auto Reg1 = VRegs[i];
|
||||
const auto Reg2 = VRegs[i + 1];
|
||||
ld2b(Reg1.Z(), Reg2.Z(), PRED_TMP_32B.Zeroing(), ARMEmitter::Reg::rsp);
|
||||
add(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::rsp, ARMEmitter::Reg::rsp, 32 * 2);
|
||||
}
|
||||
|
||||
for (; i < VRegs.size(); i += 4) {
|
||||
const auto Reg1 = VRegs[i];
|
||||
const auto Reg2 = VRegs[i + 1];
|
||||
const auto Reg3 = VRegs[i + 2];
|
||||
const auto Reg4 = VRegs[i + 3];
|
||||
ld4b(Reg1.Z(), Reg2.Z(), Reg3.Z(), Reg4.Z(), PRED_TMP_32B.Zeroing(), ARMEmitter::Reg::rsp);
|
||||
add(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::rsp, ARMEmitter::Reg::rsp, 32 * 4);
|
||||
}
|
||||
} else {
|
||||
size_t i = 0;
|
||||
for (; i < (VRegs.size() % 4); i += 2) {
|
||||
const auto Reg1 = VRegs[i];
|
||||
const auto Reg2 = VRegs[i + 1];
|
||||
ld1<ARMEmitter::SubRegSize::i64Bit>(Reg1.Q(), Reg2.Q(), ARMEmitter::Reg::rsp, 32);
|
||||
}
|
||||
|
||||
for (; i < VRegs.size(); i += 4) {
|
||||
const auto Reg1 = VRegs[i];
|
||||
const auto Reg2 = VRegs[i + 1];
|
||||
const auto Reg3 = VRegs[i + 2];
|
||||
const auto Reg4 = VRegs[i + 3];
|
||||
ld1<ARMEmitter::SubRegSize::i64Bit>(Reg1.Q(), Reg2.Q(), Reg3.Q(), Reg4.Q(), ARMEmitter::Reg::rsp, 64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arm64Emitter::PopGeneralRegisters(std::span<const FEXCore::ARMEmitter::Register> Regs) {
|
||||
size_t i = 0;
|
||||
for (; i < (Regs.size() % 2); ++i) {
|
||||
const auto Reg1 = Regs[i];
|
||||
ldr<ARMEmitter::IndexType::POST>(Reg1.X(), ARMEmitter::Reg::rsp, 16);
|
||||
}
|
||||
for (; i < Regs.size(); i += 2) {
|
||||
const auto Reg1 = Regs[i];
|
||||
const auto Reg2 = Regs[i + 1];
|
||||
ldp<ARMEmitter::IndexType::POST>(Reg1.X(), Reg2.X(), ARMEmitter::Reg::rsp, 16);
|
||||
}
|
||||
}
|
||||
|
||||
void Arm64Emitter::PushDynamicRegsAndLR(FEXCore::ARMEmitter::Register TmpReg) {
|
||||
const auto CanUseSVE = EmitterCTX->HostFeatures.SupportsAVX;
|
||||
const auto GPRSize = (ConfiguredDynamicRegisterBase.size() + 1) * Core::CPUState::GPR_REG_SIZE;
|
||||
@@ -545,31 +834,13 @@ void Arm64Emitter::PushDynamicRegsAndLR(FEXCore::ARMEmitter::Register TmpReg) {
|
||||
// rsp capable move
|
||||
add(ARMEmitter::Size::i64Bit, TmpReg, ARMEmitter::Reg::rsp, 0);
|
||||
|
||||
if (CanUseSVE) {
|
||||
for (size_t i = 0; i < GeneralFPRegisters.size(); i += 4) {
|
||||
const auto Reg1 = GeneralFPRegisters[i];
|
||||
const auto Reg2 = GeneralFPRegisters[i + 1];
|
||||
const auto Reg3 = GeneralFPRegisters[i + 2];
|
||||
const auto Reg4 = GeneralFPRegisters[i + 3];
|
||||
st4b(Reg1.Z(), Reg2.Z(), Reg3.Z(), Reg4.Z(), PRED_TMP_32B, TmpReg, 0);
|
||||
add(ARMEmitter::Size::i64Bit, TmpReg, TmpReg, 32 * 4);
|
||||
}
|
||||
} else {
|
||||
LOGMAN_THROW_A_FMT(GeneralFPRegisters.size() % 4 == 0, "Needs to have multiple of 4 FPRs for RA");
|
||||
for (size_t i = 0; i < GeneralFPRegisters.size(); i += 4) {
|
||||
const auto Reg1 = GeneralFPRegisters[i];
|
||||
const auto Reg2 = GeneralFPRegisters[i + 1];
|
||||
const auto Reg3 = GeneralFPRegisters[i + 2];
|
||||
const auto Reg4 = GeneralFPRegisters[i + 3];
|
||||
st1<ARMEmitter::SubRegSize::i64Bit>(Reg1.Q(), Reg2.Q(), Reg3.Q(), Reg4.Q(), TmpReg, 64);
|
||||
}
|
||||
}
|
||||
LOGMAN_THROW_A_FMT(GeneralFPRegisters.size() % 2 == 0, "Needs to have multiple of 2 FPRs for RA");
|
||||
|
||||
for (size_t i = 0; i < ConfiguredDynamicRegisterBase.size(); i += 2) {
|
||||
const auto Reg1 = ConfiguredDynamicRegisterBase[i];
|
||||
const auto Reg2 = ConfiguredDynamicRegisterBase[i + 1];
|
||||
stp<ARMEmitter::IndexType::POST>(Reg1.X(), Reg2.X(), TmpReg, 16);
|
||||
}
|
||||
// Push the vector registers
|
||||
PushVectorRegisters(TmpReg, CanUseSVE, GeneralFPRegisters);
|
||||
|
||||
// Push the general registers.
|
||||
PushGeneralRegisters(TmpReg, ConfiguredDynamicRegisterBase);
|
||||
|
||||
str(ARMEmitter::XReg::lr, TmpReg, 0);
|
||||
}
|
||||
@@ -577,34 +848,107 @@ void Arm64Emitter::PushDynamicRegsAndLR(FEXCore::ARMEmitter::Register TmpReg) {
|
||||
void Arm64Emitter::PopDynamicRegsAndLR() {
|
||||
const auto CanUseSVE = EmitterCTX->HostFeatures.SupportsAVX;
|
||||
|
||||
if (CanUseSVE) {
|
||||
for (size_t i = 0; i < GeneralFPRegisters.size(); i += 4) {
|
||||
const auto Reg1 = GeneralFPRegisters[i];
|
||||
const auto Reg2 = GeneralFPRegisters[i + 1];
|
||||
const auto Reg3 = GeneralFPRegisters[i + 2];
|
||||
const auto Reg4 = GeneralFPRegisters[i + 3];
|
||||
ld4b(Reg1.Z(), Reg2.Z(), Reg3.Z(), Reg4.Z(), PRED_TMP_32B.Zeroing(), ARMEmitter::Reg::rsp);
|
||||
add(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::rsp, ARMEmitter::Reg::rsp, 32 * 4);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < GeneralFPRegisters.size(); i += 4) {
|
||||
const auto Reg1 = GeneralFPRegisters[i];
|
||||
const auto Reg2 = GeneralFPRegisters[i + 1];
|
||||
const auto Reg3 = GeneralFPRegisters[i + 2];
|
||||
const auto Reg4 = GeneralFPRegisters[i + 3];
|
||||
ld1<ARMEmitter::SubRegSize::i64Bit>(Reg1.Q(), Reg2.Q(), Reg3.Q(), Reg4.Q(), ARMEmitter::Reg::rsp, 64);
|
||||
}
|
||||
}
|
||||
// Pop vectors first
|
||||
PopVectorRegisters(CanUseSVE, GeneralFPRegisters);
|
||||
|
||||
for (size_t i = 0; i < ConfiguredDynamicRegisterBase.size(); i += 2) {
|
||||
const auto Reg1 = ConfiguredDynamicRegisterBase[i];
|
||||
const auto Reg2 = ConfiguredDynamicRegisterBase[i + 1];
|
||||
ldp<ARMEmitter::IndexType::POST>(Reg1.X(), Reg2.X(), ARMEmitter::Reg::rsp, 16);
|
||||
}
|
||||
// Pop GPRs second
|
||||
PopGeneralRegisters(ConfiguredDynamicRegisterBase);
|
||||
|
||||
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, 16);
|
||||
}
|
||||
|
||||
void Arm64Emitter::SpillForPreserveAllABICall(FEXCore::ARMEmitter::Register TmpReg, bool FPRs) {
|
||||
const auto CanUseSVE = EmitterCTX->HostFeatures.SupportsAVX;
|
||||
const auto FPRRegSize = CanUseSVE ? Core::CPUState::XMM_AVX_REG_SIZE
|
||||
: Core::CPUState::XMM_SSE_REG_SIZE;
|
||||
|
||||
std::span<const FEXCore::ARMEmitter::Register> DynamicGPRs{};
|
||||
std::span<const FEXCore::ARMEmitter::VRegister> DynamicFPRs{};
|
||||
uint32_t PreserveSRAMask{};
|
||||
uint32_t PreserveSRAFPRMask{};
|
||||
if (EmitterCTX->Config.Is64BitMode()) {
|
||||
DynamicGPRs = x64::PreserveAll_Dynamic;
|
||||
DynamicFPRs = x64::PreserveAll_DynamicFPR;
|
||||
PreserveSRAMask = x64::PreserveAll_SRAMask;
|
||||
PreserveSRAFPRMask = x64::PreserveAll_SRAFPRMask;
|
||||
|
||||
if (CanUseSVE) {
|
||||
DynamicFPRs = x64::PreserveAll_DynamicFPRSVE;
|
||||
PreserveSRAFPRMask = x64::PreserveAll_SRAFPRSVEMask;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DynamicGPRs = x32::PreserveAll_Dynamic;
|
||||
DynamicFPRs = x32::PreserveAll_DynamicFPR;
|
||||
PreserveSRAMask = x32::PreserveAll_SRAMask;
|
||||
PreserveSRAFPRMask = x32::PreserveAll_SRAFPRMask;
|
||||
|
||||
if (CanUseSVE) {
|
||||
DynamicFPRs = x32::PreserveAll_DynamicFPRSVE;
|
||||
PreserveSRAFPRMask = x32::PreserveAll_SRAFPRSVEMask;
|
||||
}
|
||||
}
|
||||
|
||||
const auto GPRSize = AlignUp(DynamicGPRs.size(), 2) * Core::CPUState::GPR_REG_SIZE;
|
||||
const auto FPRSize = DynamicFPRs.size() * FPRRegSize;
|
||||
const uint64_t SPOffset = AlignUp(GPRSize + FPRSize, 16);
|
||||
|
||||
// Spill the static registers.
|
||||
SpillStaticRegs(TmpReg, true, PreserveSRAMask, PreserveSRAFPRMask);
|
||||
|
||||
sub(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::rsp, ARMEmitter::Reg::rsp, SPOffset);
|
||||
|
||||
// rsp capable move
|
||||
add(ARMEmitter::Size::i64Bit, TmpReg, ARMEmitter::Reg::rsp, 0);
|
||||
|
||||
// Push the vector registers.
|
||||
PushVectorRegisters(TmpReg, CanUseSVE, DynamicFPRs);
|
||||
|
||||
// Push the general registers.
|
||||
PushGeneralRegisters(TmpReg, DynamicGPRs);
|
||||
}
|
||||
|
||||
void Arm64Emitter::FillForPreserveAllABICall(bool FPRs) {
|
||||
const auto CanUseSVE = EmitterCTX->HostFeatures.SupportsAVX;
|
||||
|
||||
std::span<const FEXCore::ARMEmitter::Register> DynamicGPRs{};
|
||||
std::span<const FEXCore::ARMEmitter::VRegister> DynamicFPRs{};
|
||||
uint32_t PreserveSRAMask{};
|
||||
uint32_t PreserveSRAFPRMask{};
|
||||
|
||||
if (EmitterCTX->Config.Is64BitMode()) {
|
||||
DynamicGPRs = x64::PreserveAll_Dynamic;
|
||||
DynamicFPRs = x64::PreserveAll_DynamicFPR;
|
||||
PreserveSRAMask = x64::PreserveAll_SRAMask;
|
||||
PreserveSRAFPRMask = x64::PreserveAll_SRAFPRMask;
|
||||
|
||||
if (CanUseSVE) {
|
||||
DynamicFPRs = x64::PreserveAll_DynamicFPRSVE;
|
||||
PreserveSRAFPRMask = x64::PreserveAll_SRAFPRSVEMask;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DynamicGPRs = x32::PreserveAll_Dynamic;
|
||||
DynamicFPRs = x32::PreserveAll_DynamicFPR;
|
||||
PreserveSRAMask = x32::PreserveAll_SRAMask;
|
||||
PreserveSRAFPRMask = x32::PreserveAll_SRAFPRMask;
|
||||
|
||||
if (CanUseSVE) {
|
||||
DynamicFPRs = x32::PreserveAll_DynamicFPRSVE;
|
||||
PreserveSRAFPRMask = x32::PreserveAll_SRAFPRSVEMask;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the static registers.
|
||||
FillStaticRegs(true, PreserveSRAMask, PreserveSRAFPRMask);
|
||||
|
||||
// Pop the vector registers.
|
||||
PopVectorRegisters(CanUseSVE, DynamicFPRs);
|
||||
|
||||
// Pop the general registers.
|
||||
PopGeneralRegisters(DynamicGPRs);
|
||||
}
|
||||
|
||||
void Arm64Emitter::Align16B() {
|
||||
uint64_t CurrentOffset = GetCursorAddress<uint64_t>();
|
||||
for (uint64_t i = (16 - (CurrentOffset & 0xF)); i != 0; i -= 4) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "FEXCore/Utils/EnumUtils.h"
|
||||
#include "Interface/Core/ArchHelpers/CodeEmitter/Emitter.h"
|
||||
#include "Interface/Core/ArchHelpers/CodeEmitter/Registers.h"
|
||||
|
||||
#include "Interface/Core/Dispatcher/Dispatcher.h"
|
||||
#include "Interface/Core/ObjectCache/Relocations.h"
|
||||
|
||||
#include <aarch64/assembler-aarch64.h>
|
||||
@@ -28,6 +28,10 @@
|
||||
#include <utility>
|
||||
#include <span>
|
||||
|
||||
namespace FEXCore::Context {
|
||||
class ContextImpl;
|
||||
}
|
||||
|
||||
namespace FEXCore::CPU {
|
||||
// Contains the address to the currently available CPU state
|
||||
constexpr auto STATE = FEXCore::ARMEmitter::XReg::x28;
|
||||
@@ -42,8 +46,6 @@ constexpr auto TMP4 = FEXCore::ARMEmitter::XReg::x3;
|
||||
// Vector temporaries
|
||||
constexpr auto VTMP1 = FEXCore::ARMEmitter::VReg::v0;
|
||||
constexpr auto VTMP2 = FEXCore::ARMEmitter::VReg::v1;
|
||||
constexpr auto VTMP3 = FEXCore::ARMEmitter::VReg::v2;
|
||||
constexpr auto VTMP4 = FEXCore::ARMEmitter::VReg::v3;
|
||||
|
||||
// Predicate register temporaries (used when AVX support is enabled)
|
||||
// PRED_TMP_16B indicates a predicate register that indicates the first 16 bytes set to 1.
|
||||
@@ -99,12 +101,52 @@ protected:
|
||||
// We can't guarantee only the lower 64bits are used so flush everything
|
||||
static constexpr uint32_t CALLER_FPR_MASK = ~0U;
|
||||
|
||||
// Generic push and pop vector registers.
|
||||
void PushVectorRegisters(FEXCore::ARMEmitter::Register TmpReg, bool SVERegs, std::span<const FEXCore::ARMEmitter::VRegister> VRegs);
|
||||
void PushGeneralRegisters(FEXCore::ARMEmitter::Register TmpReg, std::span<const FEXCore::ARMEmitter::Register> Regs);
|
||||
|
||||
void PopVectorRegisters(bool SVERegs, std::span<const FEXCore::ARMEmitter::VRegister> VRegs);
|
||||
void PopGeneralRegisters(std::span<const FEXCore::ARMEmitter::Register> Regs);
|
||||
|
||||
void PushDynamicRegsAndLR(FEXCore::ARMEmitter::Register TmpReg);
|
||||
void PopDynamicRegsAndLR();
|
||||
|
||||
void PushCalleeSavedRegisters();
|
||||
void PopCalleeSavedRegisters();
|
||||
|
||||
// Spills and fills SRA/Dynamic registers that are required for Arm64 `preserve_all` ABI.
|
||||
// This ABI changes most registers to be callee saved.
|
||||
// Caller Saved:
|
||||
// - X0-X8, X16-X18.
|
||||
// - v0-v7
|
||||
// - For 256-bit SVE hosts: top 128-bits of v8-v31
|
||||
//
|
||||
// Callee Saved:
|
||||
// - X9-X15, X19-X31
|
||||
// - Low 128-bits of v8-v31
|
||||
void SpillForPreserveAllABICall(FEXCore::ARMEmitter::Register TmpReg, bool FPRs = true);
|
||||
void FillForPreserveAllABICall(bool FPRs = true);
|
||||
|
||||
void SpillForABICall(bool SupportsPreserveAllABI, FEXCore::ARMEmitter::Register TmpReg, bool FPRs = true) {
|
||||
if (SupportsPreserveAllABI) {
|
||||
SpillForPreserveAllABICall(TMP1, true);
|
||||
}
|
||||
else {
|
||||
SpillStaticRegs(TMP1);
|
||||
PushDynamicRegsAndLR(TMP1);
|
||||
}
|
||||
}
|
||||
|
||||
void FillForABICall(bool SupportsPreserveAllABI, bool FPRs = true) {
|
||||
if (SupportsPreserveAllABI) {
|
||||
FillForPreserveAllABICall(true);
|
||||
}
|
||||
else {
|
||||
PopDynamicRegsAndLR();
|
||||
FillStaticRegs();
|
||||
}
|
||||
}
|
||||
|
||||
void Align16B();
|
||||
|
||||
#ifdef VIXL_SIMULATOR
|
||||
@@ -171,7 +213,15 @@ protected:
|
||||
// Call type
|
||||
dc32(vixl::aarch64::kCallRuntime);
|
||||
}
|
||||
|
||||
#else
|
||||
template<typename R, typename... P>
|
||||
void GenerateRuntimeCall(R (*Function)(P...)) {
|
||||
// Explicitly doing nothing.
|
||||
}
|
||||
template<typename R, typename... P>
|
||||
void GenerateIndirectRuntimeCall(ARMEmitter::Register Reg) {
|
||||
// Explicitly doing nothing.
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VIXL_SIMULATOR
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/* ALU instruction emitters.
|
||||
*
|
||||
* Almost all of these operations have `ARMEmitter::Size` as their first argument.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/* ASIMD instruction emitters.
|
||||
*
|
||||
* This contains emitters for vector operations explicitly.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/* Branch instruction emitters.
|
||||
*
|
||||
* Most of these instructions will use `BackwardLabel`, `ForwardLabel`, or `BiDirectionLabel` to determine where a branch targets.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include "Interface/Core/ArchHelpers/CodeEmitter/Buffer.h"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/* Load-store instruction emitters
|
||||
*
|
||||
* For GPR load-stores that take a `Size` argument as their first argument can be 32-bit or 64-bit.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/Utils/EnumUtils.h>
|
||||
@@ -20,12 +21,11 @@ namespace FEXCore::ARMEmitter {
|
||||
|
||||
friend constexpr auto operator<=>(const Register&, const Register&) = default;
|
||||
|
||||
uint32_t Idx() const {
|
||||
constexpr uint32_t Idx() const {
|
||||
return Index;
|
||||
}
|
||||
|
||||
WRegister W() const;
|
||||
XRegister X() const;
|
||||
constexpr WRegister W() const;
|
||||
constexpr XRegister X() const;
|
||||
|
||||
private:
|
||||
uint32_t Index;
|
||||
@@ -45,16 +45,15 @@ namespace FEXCore::ARMEmitter {
|
||||
|
||||
friend constexpr auto operator<=>(const WRegister&, const WRegister&) = default;
|
||||
|
||||
uint32_t Idx() const {
|
||||
constexpr uint32_t Idx() const {
|
||||
return Index;
|
||||
}
|
||||
|
||||
operator Register() const {
|
||||
constexpr operator Register() const {
|
||||
return Register(Index);
|
||||
}
|
||||
|
||||
XRegister X() const;
|
||||
Register R() const;
|
||||
constexpr XRegister X() const;
|
||||
constexpr Register R() const;
|
||||
|
||||
private:
|
||||
uint32_t Index;
|
||||
@@ -74,16 +73,15 @@ namespace FEXCore::ARMEmitter {
|
||||
|
||||
friend constexpr auto operator<=>(const XRegister&, const XRegister&) = default;
|
||||
|
||||
uint32_t Idx() const {
|
||||
constexpr uint32_t Idx() const {
|
||||
return Index;
|
||||
}
|
||||
|
||||
operator Register() const {
|
||||
constexpr operator Register() const {
|
||||
return Register(Index);
|
||||
}
|
||||
|
||||
WRegister W() const;
|
||||
Register R() const;
|
||||
constexpr WRegister W() const;
|
||||
constexpr Register R() const;
|
||||
|
||||
private:
|
||||
uint32_t Index;
|
||||
@@ -92,27 +90,27 @@ namespace FEXCore::ARMEmitter {
|
||||
static_assert(std::is_trivial_v<Register>, "Needs to be trivial");
|
||||
static_assert(std::is_standard_layout_v<Register>, "Needs to be standard");
|
||||
|
||||
inline WRegister Register::W() const {
|
||||
inline constexpr WRegister Register::W() const {
|
||||
return WRegister{Index};
|
||||
}
|
||||
|
||||
inline XRegister Register::X() const {
|
||||
inline constexpr XRegister Register::X() const {
|
||||
return XRegister{Index};
|
||||
}
|
||||
|
||||
inline XRegister WRegister::X() const {
|
||||
inline constexpr XRegister WRegister::X() const {
|
||||
return XRegister{Index};
|
||||
}
|
||||
|
||||
inline Register WRegister::R() const {
|
||||
inline constexpr Register WRegister::R() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline WRegister XRegister::W() const {
|
||||
inline constexpr WRegister XRegister::W() const {
|
||||
return WRegister{Index};
|
||||
}
|
||||
|
||||
inline Register XRegister::R() const {
|
||||
inline constexpr Register XRegister::R() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -259,7 +257,6 @@ namespace FEXCore::ARMEmitter {
|
||||
class QRegister;
|
||||
class ZRegister;
|
||||
|
||||
|
||||
/* Unsized ASIMD register class
|
||||
* This class doesn't imply a size when used, nor implies Vector or Scalar.
|
||||
* It does imply that this instruction isn't using the register for SVE.
|
||||
@@ -272,16 +269,16 @@ namespace FEXCore::ARMEmitter {
|
||||
|
||||
friend constexpr auto operator<=>(const VRegister&, const VRegister&) = default;
|
||||
|
||||
uint32_t Idx() const {
|
||||
constexpr uint32_t Idx() const {
|
||||
return Index;
|
||||
}
|
||||
|
||||
BRegister B() const;
|
||||
HRegister H() const;
|
||||
SRegister S() const;
|
||||
DRegister D() const;
|
||||
QRegister Q() const;
|
||||
ZRegister Z() const;
|
||||
constexpr BRegister B() const;
|
||||
constexpr HRegister H() const;
|
||||
constexpr SRegister S() const;
|
||||
constexpr DRegister D() const;
|
||||
constexpr QRegister Q() const;
|
||||
constexpr ZRegister Z() const;
|
||||
|
||||
private:
|
||||
uint32_t Index;
|
||||
@@ -301,20 +298,19 @@ namespace FEXCore::ARMEmitter {
|
||||
|
||||
friend constexpr auto operator<=>(const BRegister&, const BRegister&) = default;
|
||||
|
||||
uint32_t Idx() const {
|
||||
constexpr uint32_t Idx() const {
|
||||
return Index;
|
||||
}
|
||||
|
||||
operator VRegister () const {
|
||||
constexpr operator VRegister() const {
|
||||
return VRegister(Index);
|
||||
}
|
||||
|
||||
BRegister V() const;
|
||||
HRegister H() const;
|
||||
SRegister S() const;
|
||||
DRegister D() const;
|
||||
QRegister Q() const;
|
||||
ZRegister Z() const;
|
||||
constexpr BRegister V() const;
|
||||
constexpr HRegister H() const;
|
||||
constexpr SRegister S() const;
|
||||
constexpr DRegister D() const;
|
||||
constexpr QRegister Q() const;
|
||||
constexpr ZRegister Z() const;
|
||||
|
||||
private:
|
||||
uint32_t Index;
|
||||
@@ -334,20 +330,19 @@ namespace FEXCore::ARMEmitter {
|
||||
|
||||
friend constexpr auto operator<=>(const HRegister&, const HRegister&) = default;
|
||||
|
||||
uint32_t Idx() const {
|
||||
constexpr uint32_t Idx() const {
|
||||
return Index;
|
||||
}
|
||||
|
||||
operator VRegister() const {
|
||||
constexpr operator VRegister() const {
|
||||
return VRegister(Index);
|
||||
}
|
||||
|
||||
HRegister V() const;
|
||||
BRegister B() const;
|
||||
SRegister S() const;
|
||||
DRegister D() const;
|
||||
QRegister Q() const;
|
||||
ZRegister Z() const;
|
||||
constexpr HRegister V() const;
|
||||
constexpr BRegister B() const;
|
||||
constexpr SRegister S() const;
|
||||
constexpr DRegister D() const;
|
||||
constexpr QRegister Q() const;
|
||||
constexpr ZRegister Z() const;
|
||||
|
||||
private:
|
||||
uint32_t Index;
|
||||
@@ -367,20 +362,19 @@ namespace FEXCore::ARMEmitter {
|
||||
|
||||
friend constexpr auto operator<=>(const SRegister&, const SRegister&) = default;
|
||||
|
||||
uint32_t Idx() const {
|
||||
constexpr uint32_t Idx() const {
|
||||
return Index;
|
||||
}
|
||||
|
||||
operator VRegister() const {
|
||||
constexpr operator VRegister() const {
|
||||
return VRegister(Index);
|
||||
}
|
||||
|
||||
SRegister V() const;
|
||||
BRegister B() const;
|
||||
HRegister H() const;
|
||||
DRegister D() const;
|
||||
QRegister Q() const;
|
||||
ZRegister Z() const;
|
||||
constexpr SRegister V() const;
|
||||
constexpr BRegister B() const;
|
||||
constexpr HRegister H() const;
|
||||
constexpr DRegister D() const;
|
||||
constexpr QRegister Q() const;
|
||||
constexpr ZRegister Z() const;
|
||||
|
||||
private:
|
||||
uint32_t Index;
|
||||
@@ -401,20 +395,19 @@ namespace FEXCore::ARMEmitter {
|
||||
|
||||
friend constexpr auto operator<=>(const DRegister&, const DRegister&) = default;
|
||||
|
||||
uint32_t Idx() const {
|
||||
constexpr uint32_t Idx() const {
|
||||
return Index;
|
||||
}
|
||||
|
||||
operator VRegister() const {
|
||||
constexpr operator VRegister() const {
|
||||
return VRegister(Index);
|
||||
}
|
||||
|
||||
DRegister V() const;
|
||||
BRegister B() const;
|
||||
HRegister H() const;
|
||||
SRegister S() const;
|
||||
QRegister Q() const;
|
||||
ZRegister Z() const;
|
||||
constexpr DRegister V() const;
|
||||
constexpr BRegister B() const;
|
||||
constexpr HRegister H() const;
|
||||
constexpr SRegister S() const;
|
||||
constexpr QRegister Q() const;
|
||||
constexpr ZRegister Z() const;
|
||||
|
||||
private:
|
||||
uint32_t Index;
|
||||
@@ -435,20 +428,19 @@ namespace FEXCore::ARMEmitter {
|
||||
|
||||
friend constexpr auto operator<=>(const QRegister&, const QRegister&) = default;
|
||||
|
||||
uint32_t Idx() const {
|
||||
constexpr uint32_t Idx() const {
|
||||
return Index;
|
||||
}
|
||||
|
||||
operator VRegister () const {
|
||||
constexpr operator VRegister() const {
|
||||
return VRegister(Index);
|
||||
}
|
||||
|
||||
QRegister V() const;
|
||||
BRegister B() const;
|
||||
HRegister H() const;
|
||||
SRegister S() const;
|
||||
DRegister D() const;
|
||||
ZRegister Z() const;
|
||||
constexpr QRegister V() const;
|
||||
constexpr BRegister B() const;
|
||||
constexpr HRegister H() const;
|
||||
constexpr SRegister S() const;
|
||||
constexpr DRegister D() const;
|
||||
constexpr ZRegister Z() const;
|
||||
|
||||
private:
|
||||
uint32_t Index;
|
||||
@@ -468,16 +460,16 @@ namespace FEXCore::ARMEmitter {
|
||||
|
||||
friend constexpr auto operator<=>(const ZRegister&, const ZRegister&) = default;
|
||||
|
||||
uint32_t Idx() const {
|
||||
constexpr uint32_t Idx() const {
|
||||
return Index;
|
||||
}
|
||||
|
||||
VRegister V() const;
|
||||
BRegister B() const;
|
||||
HRegister H() const;
|
||||
SRegister S() const;
|
||||
DRegister D() const;
|
||||
QRegister Q() const;
|
||||
constexpr VRegister V() const;
|
||||
constexpr BRegister B() const;
|
||||
constexpr HRegister H() const;
|
||||
constexpr SRegister S() const;
|
||||
constexpr DRegister D() const;
|
||||
constexpr QRegister Q() const;
|
||||
|
||||
private:
|
||||
uint32_t Index;
|
||||
@@ -487,142 +479,142 @@ namespace FEXCore::ARMEmitter {
|
||||
static_assert(std::is_standard_layout_v<ZRegister>, "Needs to be standard");
|
||||
|
||||
// VRegister
|
||||
inline BRegister VRegister::B() const {
|
||||
inline constexpr BRegister VRegister::B() const {
|
||||
return BRegister{Index};
|
||||
}
|
||||
inline HRegister VRegister::H() const {
|
||||
inline constexpr HRegister VRegister::H() const {
|
||||
return HRegister{Index};
|
||||
}
|
||||
inline SRegister VRegister::S() const {
|
||||
inline constexpr SRegister VRegister::S() const {
|
||||
return SRegister{Index};
|
||||
}
|
||||
inline DRegister VRegister::D() const {
|
||||
inline constexpr DRegister VRegister::D() const {
|
||||
return DRegister{Index};
|
||||
}
|
||||
inline QRegister VRegister::Q() const {
|
||||
inline constexpr QRegister VRegister::Q() const {
|
||||
return QRegister{Index};
|
||||
}
|
||||
inline ZRegister VRegister::Z() const {
|
||||
inline constexpr ZRegister VRegister::Z() const {
|
||||
return ZRegister{Index};
|
||||
}
|
||||
|
||||
// BRegister
|
||||
inline BRegister BRegister::V() const {
|
||||
inline constexpr BRegister BRegister::V() const {
|
||||
return *this;
|
||||
}
|
||||
inline HRegister BRegister::H() const {
|
||||
inline constexpr HRegister BRegister::H() const {
|
||||
return HRegister{Index};
|
||||
}
|
||||
inline SRegister BRegister::S() const {
|
||||
inline constexpr SRegister BRegister::S() const {
|
||||
return SRegister{Index};
|
||||
}
|
||||
inline DRegister BRegister::D() const {
|
||||
inline constexpr DRegister BRegister::D() const {
|
||||
return DRegister{Index};
|
||||
}
|
||||
inline QRegister BRegister::Q() const {
|
||||
inline constexpr QRegister BRegister::Q() const {
|
||||
return QRegister{Index};
|
||||
}
|
||||
inline ZRegister BRegister::Z() const {
|
||||
inline constexpr ZRegister BRegister::Z() const {
|
||||
return ZRegister{Index};
|
||||
}
|
||||
|
||||
// HRegister
|
||||
inline HRegister HRegister::V() const {
|
||||
inline constexpr HRegister HRegister::V() const {
|
||||
return *this;
|
||||
}
|
||||
inline BRegister HRegister::B() const {
|
||||
inline constexpr BRegister HRegister::B() const {
|
||||
return BRegister{Index};
|
||||
}
|
||||
inline SRegister HRegister::S() const {
|
||||
inline constexpr SRegister HRegister::S() const {
|
||||
return SRegister{Index};
|
||||
}
|
||||
inline DRegister HRegister::D() const {
|
||||
inline constexpr DRegister HRegister::D() const {
|
||||
return DRegister{Index};
|
||||
}
|
||||
inline QRegister HRegister::Q() const {
|
||||
inline constexpr QRegister HRegister::Q() const {
|
||||
return QRegister{Index};
|
||||
}
|
||||
inline ZRegister HRegister::Z() const {
|
||||
inline constexpr ZRegister HRegister::Z() const {
|
||||
return ZRegister{Index};
|
||||
}
|
||||
|
||||
// SRegister
|
||||
inline SRegister SRegister::V() const {
|
||||
inline constexpr SRegister SRegister::V() const {
|
||||
return *this;
|
||||
}
|
||||
inline BRegister SRegister::B() const {
|
||||
inline constexpr BRegister SRegister::B() const {
|
||||
return BRegister{Index};
|
||||
}
|
||||
inline HRegister SRegister::H() const {
|
||||
inline constexpr HRegister SRegister::H() const {
|
||||
return HRegister{Index};
|
||||
}
|
||||
inline DRegister SRegister::D() const {
|
||||
inline constexpr DRegister SRegister::D() const {
|
||||
return DRegister{Index};
|
||||
}
|
||||
inline QRegister SRegister::Q() const {
|
||||
inline constexpr QRegister SRegister::Q() const {
|
||||
return QRegister{Index};
|
||||
}
|
||||
inline ZRegister SRegister::Z() const {
|
||||
inline constexpr ZRegister SRegister::Z() const {
|
||||
return ZRegister{Index};
|
||||
}
|
||||
|
||||
// DRegister
|
||||
inline DRegister DRegister::V() const {
|
||||
inline constexpr DRegister DRegister::V() const {
|
||||
return DRegister{Index};
|
||||
}
|
||||
inline BRegister DRegister::B() const {
|
||||
inline constexpr BRegister DRegister::B() const {
|
||||
return BRegister{Index};
|
||||
}
|
||||
inline HRegister DRegister::H() const {
|
||||
inline constexpr HRegister DRegister::H() const {
|
||||
return HRegister{Index};
|
||||
}
|
||||
inline SRegister DRegister::S() const {
|
||||
inline constexpr SRegister DRegister::S() const {
|
||||
return SRegister{Index};
|
||||
}
|
||||
inline QRegister DRegister::Q() const {
|
||||
inline constexpr QRegister DRegister::Q() const {
|
||||
return QRegister{Index};
|
||||
}
|
||||
inline ZRegister DRegister::Z() const {
|
||||
inline constexpr ZRegister DRegister::Z() const {
|
||||
return ZRegister{Index};
|
||||
}
|
||||
|
||||
// QRegister
|
||||
inline QRegister QRegister::V() const {
|
||||
inline constexpr QRegister QRegister::V() const {
|
||||
return *this;
|
||||
}
|
||||
inline BRegister QRegister::B() const {
|
||||
inline constexpr BRegister QRegister::B() const {
|
||||
return BRegister{Index};
|
||||
}
|
||||
inline HRegister QRegister::H() const {
|
||||
inline constexpr HRegister QRegister::H() const {
|
||||
return HRegister{Index};
|
||||
}
|
||||
inline SRegister QRegister::S() const {
|
||||
inline constexpr SRegister QRegister::S() const {
|
||||
return SRegister{Index};
|
||||
}
|
||||
inline DRegister QRegister::D() const {
|
||||
inline constexpr DRegister QRegister::D() const {
|
||||
return DRegister{Index};
|
||||
}
|
||||
inline ZRegister QRegister::Z() const {
|
||||
inline constexpr ZRegister QRegister::Z() const {
|
||||
return ZRegister{Index};
|
||||
}
|
||||
|
||||
// ZRegister
|
||||
inline VRegister ZRegister::V() const {
|
||||
inline constexpr VRegister ZRegister::V() const {
|
||||
return VRegister(Index);
|
||||
}
|
||||
inline BRegister ZRegister::B() const {
|
||||
inline constexpr BRegister ZRegister::B() const {
|
||||
return BRegister(Index);
|
||||
}
|
||||
inline HRegister ZRegister::H() const {
|
||||
inline constexpr HRegister ZRegister::H() const {
|
||||
return HRegister(Index);
|
||||
}
|
||||
inline SRegister ZRegister::S() const {
|
||||
inline constexpr SRegister ZRegister::S() const {
|
||||
return SRegister(Index);
|
||||
}
|
||||
inline DRegister ZRegister::D() const {
|
||||
inline constexpr DRegister ZRegister::D() const {
|
||||
return DRegister(Index);
|
||||
}
|
||||
inline QRegister ZRegister::Q() const {
|
||||
inline constexpr QRegister ZRegister::Q() const {
|
||||
return QRegister(Index);
|
||||
}
|
||||
|
||||
@@ -879,36 +871,28 @@ namespace FEXCore::ARMEmitter {
|
||||
}
|
||||
|
||||
// Zero-cost FPR->GPR
|
||||
inline
|
||||
Register ToReg(HRegister Reg) {
|
||||
return static_cast<Register>(Reg.Idx());
|
||||
inline constexpr Register ToReg(HRegister Reg) {
|
||||
return Register(Reg.Idx());
|
||||
}
|
||||
inline
|
||||
Register ToReg(SRegister Reg) {
|
||||
return static_cast<Register>(Reg.Idx());
|
||||
inline constexpr Register ToReg(SRegister Reg) {
|
||||
return Register(Reg.Idx());
|
||||
}
|
||||
inline
|
||||
Register ToReg(DRegister Reg) {
|
||||
return static_cast<Register>(Reg.Idx());
|
||||
inline constexpr Register ToReg(DRegister Reg) {
|
||||
return Register(Reg.Idx());
|
||||
}
|
||||
|
||||
inline
|
||||
Register ToReg(VRegister Reg) {
|
||||
return static_cast<Register>(Reg.Idx());
|
||||
inline constexpr Register ToReg(VRegister Reg) {
|
||||
return Register(Reg.Idx());
|
||||
}
|
||||
|
||||
// Zero-cost GPR->FPR
|
||||
inline
|
||||
VRegister ToVReg(Register Reg) {
|
||||
return static_cast<VRegister>(Reg.Idx());
|
||||
inline constexpr VRegister ToVReg(Register Reg) {
|
||||
return VRegister(Reg.Idx());
|
||||
}
|
||||
inline
|
||||
VRegister ToVReg(XRegister Reg) {
|
||||
return static_cast<VRegister>(Reg.Idx());
|
||||
inline constexpr VRegister ToVReg(XRegister Reg) {
|
||||
return VRegister(Reg.Idx());
|
||||
}
|
||||
inline
|
||||
VRegister ToVReg(WRegister Reg) {
|
||||
return static_cast<VRegister>(Reg.Idx());
|
||||
inline constexpr VRegister ToVReg(WRegister Reg) {
|
||||
return VRegister(Reg.Idx());
|
||||
}
|
||||
|
||||
class PRegisterZero;
|
||||
@@ -925,12 +909,12 @@ namespace FEXCore::ARMEmitter {
|
||||
|
||||
friend constexpr auto operator<=>(const PRegister&, const PRegister&) = default;
|
||||
|
||||
uint32_t Idx() const {
|
||||
constexpr uint32_t Idx() const {
|
||||
return Index;
|
||||
}
|
||||
|
||||
PRegisterZero Zeroing() const;
|
||||
PRegisterMerge Merging() const;
|
||||
constexpr PRegisterZero Zeroing() const;
|
||||
constexpr PRegisterMerge Merging() const;
|
||||
|
||||
private:
|
||||
uint32_t Index;
|
||||
@@ -948,14 +932,17 @@ namespace FEXCore::ARMEmitter {
|
||||
|
||||
friend constexpr auto operator<=>(const PRegisterZero&, const PRegisterZero&) = default;
|
||||
|
||||
uint32_t Idx() const {
|
||||
constexpr uint32_t Idx() const {
|
||||
return Index;
|
||||
}
|
||||
|
||||
operator PRegister() const;
|
||||
|
||||
PRegister P() const;
|
||||
PRegisterMerge Merging() const;
|
||||
constexpr operator PRegister() const {
|
||||
return PRegister(Index);
|
||||
}
|
||||
constexpr PRegister P() const {
|
||||
return PRegister(Index);
|
||||
}
|
||||
constexpr PRegisterMerge Merging() const;
|
||||
|
||||
private:
|
||||
uint32_t Index;
|
||||
@@ -973,14 +960,17 @@ namespace FEXCore::ARMEmitter {
|
||||
|
||||
friend constexpr auto operator<=>(const PRegisterMerge&, const PRegisterMerge&) = default;
|
||||
|
||||
uint32_t Idx() const {
|
||||
constexpr uint32_t Idx() const {
|
||||
return Index;
|
||||
}
|
||||
|
||||
operator PRegister() const;
|
||||
|
||||
PRegister P() const;
|
||||
PRegisterZero Zeroing() const;
|
||||
constexpr operator PRegister() const {
|
||||
return PRegister(Index);
|
||||
}
|
||||
constexpr PRegister P() const {
|
||||
return PRegister(Index);
|
||||
}
|
||||
constexpr PRegisterZero Zeroing() const;
|
||||
|
||||
private:
|
||||
uint32_t Index;
|
||||
@@ -989,39 +979,21 @@ namespace FEXCore::ARMEmitter {
|
||||
static_assert(std::is_trivial_v<PRegisterZero>, "Needs to be trivial");
|
||||
static_assert(std::is_standard_layout_v<PRegisterZero>, "Needs to be standard");
|
||||
|
||||
|
||||
// PRegister
|
||||
inline PRegisterZero PRegister::Zeroing() const {
|
||||
inline constexpr PRegisterZero PRegister::Zeroing() const {
|
||||
return PRegisterZero(Idx());
|
||||
}
|
||||
|
||||
inline PRegisterMerge PRegister::Merging() const {
|
||||
inline constexpr PRegisterMerge PRegister::Merging() const {
|
||||
return PRegisterMerge(Idx());
|
||||
}
|
||||
|
||||
// PRegisterZero
|
||||
inline PRegisterZero::operator PRegister() const {
|
||||
return PRegister(Index);
|
||||
}
|
||||
|
||||
inline PRegister PRegisterZero::P() const {
|
||||
return PRegister(Idx());
|
||||
}
|
||||
|
||||
inline PRegisterMerge PRegisterZero::Merging() const {
|
||||
inline constexpr PRegisterMerge PRegisterZero::Merging() const {
|
||||
return PRegisterMerge(Idx());
|
||||
}
|
||||
|
||||
// PRegisterMerge
|
||||
inline PRegisterMerge::operator PRegister() const {
|
||||
return PRegisterZero(Index);
|
||||
}
|
||||
|
||||
inline PRegister PRegisterMerge::P() const {
|
||||
return PRegister(Idx());
|
||||
}
|
||||
|
||||
inline PRegisterZero PRegisterMerge::Zeroing() const {
|
||||
inline constexpr PRegisterZero PRegisterMerge::Zeroing() const {
|
||||
return PRegisterZero(Idx());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/* SVE instruction emitters
|
||||
* These contain instruction emitters for AArch64 SVE and SVE2 operations.
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/* Scalar instruction emitters.
|
||||
*
|
||||
* These contain instruction emitters for scalar ASIMD operations explicitly.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/* System instruction emitters.
|
||||
*
|
||||
* This is mostly a mashup of various instruction types.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include "Interface/Core/BlockSamplingData.h"
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <cstring>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include "FEXCore/IR/IR.h"
|
||||
#include "FEXCore/Utils/AllocatorHooks.h"
|
||||
#include "Interface/Context/Context.h"
|
||||
@@ -126,6 +127,55 @@ constexpr static auto PSHUFD_LUT {
|
||||
}()
|
||||
};
|
||||
|
||||
constexpr static auto SHUFPS_LUT {
|
||||
[]() consteval {
|
||||
struct LUTType {
|
||||
uint64_t Val[2];
|
||||
};
|
||||
// 32-bit words in [127:96], [95:64], [63:32], [31:0] are selected using the 8-bit Index.
|
||||
// Expectation for this LUT is to simulate SHUFPS with ARM's TBL (two register) instruction.
|
||||
// SHUFPS behaviour:
|
||||
// Two 32-bits words from each source are selected from each source in the lower and upper halves of the 128-bit destination.
|
||||
// Dest[31:0] = Src1[<Word0>]
|
||||
// Dest[63:32] = Src1[<Word1>]
|
||||
// Dest[95:64] = Src2[<Word2>]
|
||||
// Dest[127:96] = Src2[<Word3>]
|
||||
|
||||
std::array<LUTType, 256> TotalLUT{};
|
||||
const uint64_t WordSelectionSrc1[4] = {
|
||||
0x03'02'01'00,
|
||||
0x07'06'05'04,
|
||||
0x0b'0a'09'08,
|
||||
0x0f'0e'0d'0c,
|
||||
};
|
||||
|
||||
// Src2 needs to offset each byte index by 16-bytes to pull from the second source.
|
||||
const uint64_t WordSelectionSrc2[4] = {
|
||||
0x03'02'01'00 + (0x10101010),
|
||||
0x07'06'05'04 + (0x10101010),
|
||||
0x0b'0a'09'08 + (0x10101010),
|
||||
0x0f'0e'0d'0c + (0x10101010),
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < 256; ++i) {
|
||||
auto &LUT = TotalLUT[i];
|
||||
const auto Word0 = (i >> 0) & 0b11;
|
||||
const auto Word1 = (i >> 2) & 0b11;
|
||||
const auto Word2 = (i >> 4) & 0b11;
|
||||
const auto Word3 = (i >> 6) & 0b11;
|
||||
|
||||
LUT.Val[0] =
|
||||
(WordSelectionSrc1[Word0] << 0) |
|
||||
(WordSelectionSrc1[Word1] << 32);
|
||||
|
||||
LUT.Val[1] =
|
||||
(WordSelectionSrc2[Word2] << 0) |
|
||||
(WordSelectionSrc2[Word3] << 32);
|
||||
}
|
||||
return TotalLUT;
|
||||
}()
|
||||
};
|
||||
|
||||
CPUBackend::CPUBackend(FEXCore::Core::InternalThreadState *ThreadState, size_t InitialCodeSize, size_t MaxCodeSize)
|
||||
: ThreadState(ThreadState), InitialCodeSize(InitialCodeSize), MaxCodeSize(MaxCodeSize) {
|
||||
|
||||
@@ -136,10 +186,14 @@ CPUBackend::CPUBackend(FEXCore::Core::InternalThreadState *ThreadState, size_t I
|
||||
Common.NamedVectorConstantPointers[i] = reinterpret_cast<uint64_t>(NamedVectorConstants[i]);
|
||||
}
|
||||
|
||||
// Copy named vector constants.
|
||||
memcpy(Common.NamedVectorConstants, NamedVectorConstants, sizeof(NamedVectorConstants));
|
||||
|
||||
// Initialize Indexed named vector constants.
|
||||
Common.IndexedNamedVectorConstantPointers[FEXCore::IR::IndexNamedVectorConstant::INDEXED_NAMED_VECTOR_PSHUFLW] = reinterpret_cast<uint64_t>(PSHUFLW_LUT.data());
|
||||
Common.IndexedNamedVectorConstantPointers[FEXCore::IR::IndexNamedVectorConstant::INDEXED_NAMED_VECTOR_PSHUFHW] = reinterpret_cast<uint64_t>(PSHUFHW_LUT.data());
|
||||
Common.IndexedNamedVectorConstantPointers[FEXCore::IR::IndexNamedVectorConstant::INDEXED_NAMED_VECTOR_PSHUFD] = reinterpret_cast<uint64_t>(PSHUFD_LUT.data());
|
||||
Common.IndexedNamedVectorConstantPointers[FEXCore::IR::IndexNamedVectorConstant::INDEXED_NAMED_VECTOR_SHUFPS] = reinterpret_cast<uint64_t>(SHUFPS_LUT.data());
|
||||
|
||||
#ifndef FEX_DISABLE_TELEMETRY
|
||||
// Fill in telemetry values
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
$info$
|
||||
tags: opcodes|cpuid
|
||||
@@ -20,9 +21,6 @@ $end_info$
|
||||
#include "git_version.h"
|
||||
|
||||
#include <cstring>
|
||||
#ifdef _M_X86_64
|
||||
#include "Interface/Core/Dispatcher/X86Dispatcher.h"
|
||||
#endif
|
||||
|
||||
namespace FEXCore {
|
||||
namespace ProductNames {
|
||||
@@ -66,7 +64,6 @@ namespace ProductNames {
|
||||
static const char ARM_Firestorm[] = "Apple Firestorm";
|
||||
static const char ARM_Icestorm[] = "Apple Icestorm";
|
||||
#else
|
||||
static const char UNKNOWN[] = "Unknown CPU";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -342,38 +339,15 @@ void CPUIDEmu::SetupHostHybridFlag() {
|
||||
|
||||
#else
|
||||
static uint32_t GetCycleCounterFrequency() {
|
||||
uint32_t data[4];
|
||||
Xbyak::util::Cpu::getCpuid(0, data);
|
||||
if (data[0] >= 0x15) {
|
||||
Xbyak::util::Cpu::getCpuid(0x15, data);
|
||||
|
||||
if (data[0] && data[1] && data[2]) {
|
||||
return data[2] * data[1] / data[0];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CPUIDEmu::SetupHostHybridFlag() {
|
||||
uint32_t data[4];
|
||||
Xbyak::util::Cpu::getCpuid(0, data);
|
||||
if (data[0] >= 0x7) {
|
||||
Xbyak::util::Cpu::getCpuid(0x7, data);
|
||||
// Bit 15 of edx claims hybrid CPU
|
||||
Hybrid = (data[3] & (1U << 15)) != 0;
|
||||
}
|
||||
|
||||
size_t CPUs = FEXCore::CPUInfo::CalculateNumberOfCPUs();
|
||||
PerCPUData.resize(CPUs);
|
||||
for (size_t i = 0; i < CPUs; ++i) {
|
||||
PerCPUData[i].IsBig = true;
|
||||
PerCPUData[i].ProductName = ProductNames::UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_0h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_0h(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
|
||||
// EBX, EDX, ECX become the manufacturer id string
|
||||
@@ -392,7 +366,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_0h(uint32_t Leaf) {
|
||||
}
|
||||
|
||||
// Processor Info and Features bits
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_01h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_01h(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
uint32_t CoreCount = Cores();
|
||||
|
||||
@@ -477,7 +451,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_01h(uint32_t Leaf) {
|
||||
}
|
||||
|
||||
// 2: Cache and TLB information
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_02h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_02h(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
|
||||
// returns default values from i7 model 1Ah
|
||||
@@ -502,7 +476,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_02h(uint32_t Leaf) {
|
||||
}
|
||||
|
||||
// 4: Deterministic cache parameters for each level
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_04h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_04h(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
constexpr uint32_t CacheType_Data = 1;
|
||||
constexpr uint32_t CacheType_Instruction = 2;
|
||||
@@ -608,16 +582,21 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_04h(uint32_t Leaf) {
|
||||
return Res;
|
||||
}
|
||||
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_06h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_06h(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
Res.eax = (1 << 2); // Always running APIC
|
||||
Res.ecx = (0 << 3); // Intel performance energy bias preference (EPB)
|
||||
return Res;
|
||||
}
|
||||
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_07h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_07h(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
if (Leaf == 0) {
|
||||
// Disable Enhanced REP MOVS when TSO is enabled.
|
||||
// vcruntime140 memmove will use `rep movsb` in this case which completely destroys perf in Hades(appId 1145360)
|
||||
// This is due to LRCPC performance on Cortex being abysmal.
|
||||
const uint32_t SupportsEnhancedREPMOVS = CTX->SoftwareTSORequired() ? 0 : 1;
|
||||
|
||||
// Number of subfunctions
|
||||
Res.eax = 0x0;
|
||||
Res.ebx =
|
||||
@@ -630,7 +609,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_07h(uint32_t Leaf) {
|
||||
(1 << 6) | // FPU data pointer updated only on exception
|
||||
(1 << 7) | // SMEP support
|
||||
(SupportsAVX() << 8) | // BMI2
|
||||
(0 << 9) | // Enhanced REP MOVSB/STOSB
|
||||
(SupportsEnhancedREPMOVS << 9) | // Enhanced REP MOVSB/STOSB
|
||||
(1 << 10) | // INVPCID for system software control of process-context
|
||||
(0 << 11) | // Restricted transactional memory
|
||||
(0 << 12) | // Intel resource directory technology Monitoring
|
||||
@@ -726,7 +705,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_07h(uint32_t Leaf) {
|
||||
return Res;
|
||||
}
|
||||
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_0Dh(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_0Dh(uint32_t Leaf) const {
|
||||
// Leaf 0
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
|
||||
@@ -780,7 +759,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_0Dh(uint32_t Leaf) {
|
||||
return Res;
|
||||
}
|
||||
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_15h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_15h(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
// TSC frequency = ECX * EBX / EAX
|
||||
uint32_t FrequencyHz = GetCycleCounterFrequency();
|
||||
@@ -792,7 +771,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_15h(uint32_t Leaf) {
|
||||
return Res;
|
||||
}
|
||||
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_1Ah(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_1Ah(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
if (Hybrid) {
|
||||
uint32_t CPU = GetCPUID();
|
||||
@@ -805,7 +784,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_1Ah(uint32_t Leaf) {
|
||||
}
|
||||
|
||||
// Hypervisor CPUID information leaf
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_4000_0000h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_4000_0000h(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
// Maximum supported hypervisor leafs
|
||||
// We only expose the information leaf
|
||||
@@ -827,7 +806,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_4000_0000h(uint32_t Leaf) {
|
||||
}
|
||||
|
||||
// Hypervisor CPUID information leaf
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_4000_0001h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_4000_0001h(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
if (Leaf == 0) {
|
||||
// EAX[3:0] Is the host architecture that FEX is running under
|
||||
@@ -846,7 +825,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_4000_0001h(uint32_t Leaf) {
|
||||
}
|
||||
|
||||
// Highest extended function implemented
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0000h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0000h(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
Res.eax = 0x8000001F;
|
||||
|
||||
@@ -865,7 +844,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0000h(uint32_t Leaf) {
|
||||
}
|
||||
|
||||
// Extended processor and feature bits
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0001h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0001h(uint32_t Leaf) const {
|
||||
|
||||
// RDTSCP is disabled on WIN32/Wine because there is no sane way to query processor ID.
|
||||
#ifndef _WIN32
|
||||
@@ -955,33 +934,33 @@ constexpr ssize_t DESCRIBE_STR_SIZE = std::char_traits<char>::length(GIT_DESCRIB
|
||||
static_assert(DESCRIBE_STR_SIZE < 32);
|
||||
|
||||
//Processor brand string
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0002h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0002h(uint32_t Leaf) const {
|
||||
return Function_8000_0002h(Leaf, GetCPUID());
|
||||
}
|
||||
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0003h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0003h(uint32_t Leaf) const {
|
||||
return Function_8000_0003h(Leaf, GetCPUID());
|
||||
}
|
||||
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0004h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0004h(uint32_t Leaf) const {
|
||||
return Function_8000_0004h(Leaf, GetCPUID());
|
||||
}
|
||||
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0002h(uint32_t Leaf, uint32_t CPU) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0002h(uint32_t Leaf, uint32_t CPU) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
memset(&Res, ' ', sizeof(FEXCore::CPUID::FunctionResults));
|
||||
memcpy(&Res, &ProcessorBrand[0], std::min(ssize_t{16L}, DESCRIBE_STR_SIZE));
|
||||
return Res;
|
||||
}
|
||||
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0003h(uint32_t Leaf, uint32_t CPU) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0003h(uint32_t Leaf, uint32_t CPU) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
memset(&Res, ' ', sizeof(FEXCore::CPUID::FunctionResults));
|
||||
memcpy(&Res, &ProcessorBrand[16], std::max(ssize_t{0L}, DESCRIBE_STR_SIZE - 16));
|
||||
return Res;
|
||||
}
|
||||
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0004h(uint32_t Leaf, uint32_t CPU) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0004h(uint32_t Leaf, uint32_t CPU) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
auto &Data = PerCPUData[CPU];
|
||||
memcpy(&Res, Data.ProductName, std::min(strlen(Data.ProductName), sizeof(FEXCore::CPUID::FunctionResults)));
|
||||
@@ -989,7 +968,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0004h(uint32_t Leaf, uin
|
||||
}
|
||||
|
||||
// L1 Cache and TLB identifiers
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0005h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0005h(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
|
||||
// L1 TLB Information for 2MB and 4MB pages
|
||||
@@ -1024,7 +1003,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0005h(uint32_t Leaf) {
|
||||
}
|
||||
|
||||
// L2 Cache identifiers
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0006h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0006h(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
|
||||
// L2 TLB Information for 2MB and 4MB pages
|
||||
@@ -1058,7 +1037,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0006h(uint32_t Leaf) {
|
||||
}
|
||||
|
||||
// Advanced power management
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0007h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0007h(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
Res.eax = (1 << 2); // APIC timer not affected by p-state
|
||||
Res.edx =
|
||||
@@ -1067,7 +1046,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0007h(uint32_t Leaf) {
|
||||
}
|
||||
|
||||
// Virtual and physical address sizes
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0008h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0008h(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
Res.eax =
|
||||
(48 << 0) | // PhysAddrSize = 48-bit
|
||||
@@ -1089,7 +1068,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0008h(uint32_t Leaf) {
|
||||
}
|
||||
|
||||
// TLB 1GB page identifiers
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0019h(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0019h(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
Res.eax =
|
||||
(0xF << 28) | // L1 DTLB associativity for 1GB pages
|
||||
@@ -1106,7 +1085,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0019h(uint32_t Leaf) {
|
||||
}
|
||||
|
||||
// Deterministic cache parameters for each level
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_001Dh(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_001Dh(uint32_t Leaf) const {
|
||||
// This is nearly a copy of CPUID function 4h
|
||||
// There are some minor changes though
|
||||
|
||||
@@ -1201,12 +1180,12 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_001Dh(uint32_t Leaf) {
|
||||
return Res;
|
||||
}
|
||||
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_Reserved(uint32_t Leaf) {
|
||||
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_Reserved(uint32_t Leaf) const {
|
||||
FEXCore::CPUID::FunctionResults Res{};
|
||||
return Res;
|
||||
}
|
||||
|
||||
FEXCore::CPUID::XCRResults CPUIDEmu::XCRFunction_0h() {
|
||||
FEXCore::CPUID::XCRResults CPUIDEmu::XCRFunction_0h() const {
|
||||
// This just returns XCR0
|
||||
FEXCore::CPUID::XCRResults Res{
|
||||
.eax = static_cast<uint32_t>(XCR0),
|
||||
|
||||
Loaded 100 of 634 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user