mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-07-25 15:19:50 -06:00
Compare commits
130 Commits
1.3.1
...
update/dot
Author | SHA1 | Date | |
---|---|---|---|
d60914ecec | |||
15881cb385 | |||
ebbfcc32e2 | |||
a53de86a19 | |||
3311842a16 | |||
2403bd4f3c | |||
483d42ec38 | |||
fbb2f4bde0 | |||
81b454282a | |||
6c5f21e4e9 | |||
00b784e046 | |||
bb1ab14214 | |||
2075c1a543 | |||
99cbfc3822 | |||
203a759775 | |||
32b91b5ba9 | |||
0ec18c0f43 | |||
7f91c0fcea | |||
983ee714e9 | |||
1c92e8171f | |||
31c63708e4 | |||
0eba6c75b2 | |||
aa53b9b39c | |||
dc4dabc790 | |||
7a8285bcb5 | |||
76a1a65135 | |||
be6e34f7e8 | |||
231c0f46e4 | |||
763c13555c | |||
72c480fd56 | |||
29a785aed4 | |||
f6f27786d3 | |||
755f7fa513 | |||
909a674443 | |||
731d722042 | |||
3437eedff4 | |||
fc8b92e2de | |||
b08b1afcff | |||
10eca602b1 | |||
42df9aae7a | |||
56765f3251 | |||
77bcf56230 | |||
b7ca8d66ca | |||
29fa21afc1 | |||
4df476f91c | |||
e01a99cc9a | |||
e9949b2a72 | |||
ef68c366fb | |||
7617863704 | |||
1781bd2d36 | |||
1e3aac32de | |||
a9e112d8d2 | |||
bcf2b3ae96 | |||
b06daf784e | |||
fbe80cc1fd | |||
b771793ed3 | |||
dd6e33ae31 | |||
b8a2096dc6 | |||
7e3d22b5da | |||
26932ced08 | |||
d99a6a0f0a | |||
58e2f957a7 | |||
40f12bd8df | |||
1067827dcf | |||
28932a0ea3 | |||
429203e5d2 | |||
301978a35d | |||
13017a0eb4 | |||
60e59d2e2b | |||
a9380092a7 | |||
ee4466351f | |||
a0ad3c5dd3 | |||
93f30754e1 | |||
089be24825 | |||
3642c17669 | |||
1109dc8011 | |||
c37778c337 | |||
d15d9e65c2 | |||
cf819c572b | |||
b43ce7bce4 | |||
5587926192 | |||
50211d5f2d | |||
634cfae98e | |||
07b1e849f9 | |||
a742e9ff8e | |||
c55e6c2f9b | |||
860abda318 | |||
5c523243bc | |||
5bedfe2ca4 | |||
ff7a607b49 | |||
81c1b14c0d | |||
3c98be1a78 | |||
fbc566e0b4 | |||
1ebc8c2ce6 | |||
60e12ac1af | |||
d48ca5e7a3 | |||
754c535957 | |||
4ac4ad399b | |||
48c0118779 | |||
bb1d7daaa3 | |||
6e1dac93be | |||
735812e926 | |||
c0c021c7a9 | |||
f284a99cb0 | |||
bd0790f5e4 | |||
883b2968cd | |||
4deba433b8 | |||
ea57e7c3b0 | |||
103365205e | |||
4a61922639 | |||
91553bb1f8 | |||
1cdb6fa933 | |||
fbc3ba30b9 | |||
fecdce2ca6 | |||
7c2bc153a3 | |||
caf9fcac29 | |||
0bda9b1b64 | |||
c62982aa24 | |||
39499c87d7 | |||
3b3cd92a73 | |||
c1ec40b71e | |||
eefc4cfe28 | |||
1a3046d459 | |||
5a3d6f9da8 | |||
ad88e32296 | |||
b71a4cb745 | |||
844b1d8b9a | |||
c4ea0e0df2 | |||
0ae536a757 | |||
e96f1df058 |
@ -16,6 +16,17 @@ tab_width = 4
|
||||
# New line preferences
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
|
||||
dotnet_style_prefer_auto_properties = true:silent
|
||||
dotnet_style_object_initializer = true:suggestion
|
||||
dotnet_style_collection_initializer = true:suggestion
|
||||
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
|
||||
dotnet_style_prefer_conditional_expression_over_return = true:silent
|
||||
dotnet_style_operator_placement_when_wrapping = beginning_of_line
|
||||
dotnet_style_explicit_tuple_names = true:suggestion
|
||||
|
||||
# Markdown, JSON, YAML, props and csproj files
|
||||
[*.{md,json,yml,props,csproj}]
|
||||
@ -106,7 +117,7 @@ csharp_style_conditional_delegate_call = true:suggestion
|
||||
csharp_prefer_static_local_function = true:suggestion
|
||||
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent
|
||||
csharp_style_prefer_readonly_struct = true
|
||||
csharp_style_prefer_method_group_conversion = true
|
||||
csharp_style_prefer_method_group_conversion = true:silent
|
||||
|
||||
# Code-block preferences
|
||||
csharp_prefer_braces = true:silent
|
||||
@ -177,9 +188,9 @@ csharp_preserve_single_line_statements = false
|
||||
|
||||
# Naming rules
|
||||
|
||||
dotnet_naming_rule.interfaces_should_be_prefixed_with_I.severity = suggestion
|
||||
dotnet_naming_rule.interfaces_should_be_prefixed_with_i.severity = suggestion
|
||||
dotnet_naming_rule.interfaces_should_be_prefixed_with_I.symbols = interface
|
||||
dotnet_naming_rule.interfaces_should_be_prefixed_with_I.style = IPascalCase
|
||||
dotnet_naming_rule.interfaces_should_be_prefixed_with_i.style = IPascalCase
|
||||
|
||||
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
|
||||
@ -236,28 +247,22 @@ dotnet_naming_style.IPascalCase.required_suffix =
|
||||
dotnet_naming_style.IPascalCase.word_separator =
|
||||
dotnet_naming_style.IPascalCase.capitalization = pascal_case
|
||||
|
||||
# TODO:
|
||||
# .NET 8 migration (new warnings are caused by the NET 8 C# compiler and analyzer)
|
||||
# The following info messages might need to be fixed in the source code instead of hiding the actual message
|
||||
# Without the following lines, dotnet format would fail
|
||||
# Disable "Collection initialization can be simplified"
|
||||
# Other settings
|
||||
csharp_style_prefer_top_level_statements = true:suggestion
|
||||
csharp_style_prefer_primary_constructors = false:suggestion
|
||||
csharp_prefer_system_threading_lock = true:suggestion
|
||||
|
||||
|
||||
# Analyzers
|
||||
dotnet_diagnostic.CA1069.severity = none # CA1069: Enums values should not be duplicated
|
||||
# Disable Collection initialization can be simplified
|
||||
dotnet_diagnostic.IDE0028.severity = none
|
||||
dotnet_diagnostic.IDE0300.severity = none
|
||||
dotnet_diagnostic.IDE0301.severity = none
|
||||
dotnet_diagnostic.IDE0302.severity = none
|
||||
dotnet_diagnostic.IDE0305.severity = none
|
||||
# Disable "'new' expression can be simplified"
|
||||
dotnet_diagnostic.IDE0090.severity = none
|
||||
# Disable "Use primary constructor"
|
||||
dotnet_diagnostic.IDE0290.severity = none
|
||||
# Disable "Member '' does not access instance data and can be marked as static"
|
||||
dotnet_diagnostic.CA1822.severity = none
|
||||
# Disable "Change type of field '' from '' to '' for improved performance"
|
||||
dotnet_diagnostic.CA1859.severity = none
|
||||
# Disable "Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array"
|
||||
dotnet_diagnostic.CA1861.severity = none
|
||||
# Disable "Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'"
|
||||
dotnet_diagnostic.CA1862.severity = none
|
||||
dotnet_diagnostic.CS9113.severity = none # CS9113: Parameter 'value' is unread
|
||||
dotnet_diagnostic.IDE0130.severity = none # IDE0130: Namespace does not match folder structure
|
||||
|
||||
[src/Ryujinx/UI/ViewModels/**.cs]
|
||||
# Disable "mark members as static" rule for ViewModels
|
||||
|
180
.github/workflows/canary.yml
vendored
180
.github/workflows/canary.yml
vendored
@ -21,60 +21,9 @@ env:
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
RYUJINX_BASE_VERSION: "1.3"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO: "Ryujinx"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Canary-Releases"
|
||||
RELEASE: 1
|
||||
|
||||
jobs:
|
||||
tag:
|
||||
name: Create tag
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Get version info
|
||||
id: version_info
|
||||
run: |
|
||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Install GitLabCli
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
||||
chmod +x gli
|
||||
mv gli $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create GitLab tag
|
||||
run: gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateTag "Canary-${{ steps.version_info.outputs.build_version }}|master"
|
||||
|
||||
- name: Create release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
name: "Canary ${{ steps.version_info.outputs.build_version }}"
|
||||
tag: ${{ steps.version_info.outputs.build_version }}
|
||||
body: |
|
||||
# Canary builds:
|
||||
|
||||
These builds are experimental and may sometimes not work, use [regular builds](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/Stable-Releases/releases/latest) instead if that sounds like something you don't want to deal with.
|
||||
|
||||
| Platform | Artifact |
|
||||
|--|--|
|
||||
| Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
|
||||
| Windows ARM 64-bit | [Canary Windows ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) |
|
||||
| Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
|
||||
| Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
||||
| macOS | [Canary macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
||||
|
||||
**[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})**
|
||||
omitBodyDuringUpdate: true
|
||||
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
|
||||
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
|
||||
release:
|
||||
name: Release for ${{ matrix.platform.name }}
|
||||
runs-on: ${{ matrix.platform.os }}
|
||||
@ -82,7 +31,7 @@ jobs:
|
||||
matrix:
|
||||
platform:
|
||||
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
||||
- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
|
||||
#- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
|
||||
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
|
||||
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
|
||||
steps:
|
||||
@ -108,11 +57,8 @@ jobs:
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place '/^Name=Ryujinx$/s/Name=Ryujinx/Name=Ryujinx-Canary/' distribution/linux/Ryujinx.desktop
|
||||
sed -r --in-place '/^Name=Ryujinx$/s/Name=Ryujinx/Name=Ryujinx-Canary/' distribution/linux/Ryujinx.desktop
|
||||
shell: bash
|
||||
|
||||
- name: Create output dir
|
||||
@ -129,7 +75,24 @@ jobs:
|
||||
rm libarmeilleure-jitsupport.dylib
|
||||
7z a ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
||||
popd
|
||||
|
||||
gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe'
|
||||
|
||||
./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip"
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install GitLabCli
|
||||
if: matrix.platform.os == 'ubuntu-latest'
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
||||
chmod +x gli
|
||||
mv gli $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Packing Linux builds
|
||||
if: matrix.platform.os == 'ubuntu-latest'
|
||||
@ -139,6 +102,8 @@ jobs:
|
||||
chmod +x Ryujinx.sh Ryujinx
|
||||
tar -czvf ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
||||
popd
|
||||
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz"
|
||||
shell: bash
|
||||
|
||||
- name: Build AppImage (Linux)
|
||||
@ -169,41 +134,17 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|Canary-Releases|latest|*-$ARCH_NAME.AppImage.zsync"
|
||||
export UFLAG="gh-releases-zsync|${{ secrets.RC_OWNER }}${{ secrets.RC_CANARY_NAME }}|latest|*-$ARCH_NAME.AppImage.zsync"
|
||||
BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
|
||||
|
||||
pushd publish_appimage
|
||||
mv Ryujinx.AppImage ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage
|
||||
mv Ryujinx.AppImage.zsync ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
|
||||
popd
|
||||
shell: bash
|
||||
|
||||
- name: Pushing new release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
name: ${{ steps.version_info.outputs.build_version }}
|
||||
artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*"
|
||||
tag: ${{ steps.version_info.outputs.build_version }}
|
||||
body: |
|
||||
# Canary builds:
|
||||
|
||||
These builds are experimental and may sometimes not work, use [regular builds](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/latest) instead if that sounds like something you don't want to deal with.
|
||||
|
||||
| Platform | Artifact |
|
||||
|--|--|
|
||||
| Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
|
||||
| Windows ARM 64-bit | [Canary Windows ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) |
|
||||
| Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
|
||||
| Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
||||
| macOS | [Canary macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
||||
|
||||
**[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})**
|
||||
omitBodyDuringUpdate: true
|
||||
allowUpdates: true
|
||||
replacesArtifacts: true
|
||||
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
|
||||
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
popd
|
||||
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage"
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync"
|
||||
shell: bash
|
||||
|
||||
macos_release:
|
||||
name: Release MacOS universal
|
||||
@ -220,6 +161,16 @@ jobs:
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 17
|
||||
|
||||
- name: Install GitLabCli
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
||||
chmod +x gli
|
||||
mv gli $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install rcodesign
|
||||
run: |
|
||||
@ -246,24 +197,53 @@ jobs:
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
shell: bash
|
||||
|
||||
- name: Publish macOS Ryujinx
|
||||
run: |
|
||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 1
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=UploadGenericPackage "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|publish_ava/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz"
|
||||
|
||||
- name: Pushing new release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
name: "Canary ${{ steps.version_info.outputs.build_version }}"
|
||||
artifacts: "publish_ava/*.tar.gz"
|
||||
tag: ${{ steps.version_info.outputs.build_version }}
|
||||
body: ""
|
||||
omitBodyDuringUpdate: true
|
||||
allowUpdates: true
|
||||
replacesArtifacts: true
|
||||
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
|
||||
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
create_gitlab_release:
|
||||
name: Create GitLab Release
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- macos_release
|
||||
- release
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get version info
|
||||
id: version_info
|
||||
run: |
|
||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Install GitLabCli
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
||||
chmod +x gli
|
||||
mv gli $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create tag
|
||||
run: |
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateTag "Canary-${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}"
|
||||
|
||||
- name: Create release
|
||||
run: |
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=CreateReleaseFromGenericPackageFiles "Ryubing-Canary|${{ steps.version_info.outputs.build_version }}|main|Canary ${{ steps.version_info.outputs.build_version }}|**Full Changelog:** [${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}](https://git.ryujinx.app/ryubing/ryujinx/-/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }})"
|
||||
|
||||
- name: Send notification webhook
|
||||
run: |
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/canary --command=SendUpdateMessage "${{ steps.version_info.outputs.build_version }}|FF4500|${{ secrets.CANARY_DISCORD_WEBHOOK }}|https://avatars.githubusercontent.com/u/192939710?s=200&v=4|false"
|
||||
|
||||
- name: Notify update server of new builds
|
||||
run: |
|
||||
curl 'https://update.ryujinx.app/api/v1/admin/refresh_cache?rc=canary' -X PATCH -H 'accept: */*' -H 'Authorization: ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }}'
|
||||
|
224
.github/workflows/debug_release.yml
vendored
Normal file
224
.github/workflows/debug_release.yml
vendored
Normal file
@ -0,0 +1,224 @@
|
||||
name: Release job (Debug)
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs: {}
|
||||
|
||||
concurrency: release
|
||||
|
||||
env:
|
||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
RYUJINX_BASE_VERSION: "1.3"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release"
|
||||
RELEASE: 1
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Release for ${{ matrix.platform.name }}
|
||||
runs-on: ${{ matrix.platform.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
platform:
|
||||
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
||||
#- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
|
||||
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
|
||||
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
global-json-file: global.json
|
||||
|
||||
- name: Overwrite csc problem matcher
|
||||
run: echo "::add-matcher::.github/csc.json"
|
||||
|
||||
- name: Get version info
|
||||
id: version_info
|
||||
run: |
|
||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} + 10))" >> $GITHUB_OUTPUT
|
||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Configure for release
|
||||
run: |
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
shell: bash
|
||||
|
||||
- name: Create output dir
|
||||
run: "mkdir release_output"
|
||||
|
||||
- name: Publish
|
||||
run: |
|
||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained
|
||||
|
||||
- name: Packing Windows builds
|
||||
if: matrix.platform.os == 'windows-latest'
|
||||
run: |
|
||||
pushd publish
|
||||
rm libarmeilleure-jitsupport.dylib
|
||||
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
||||
popd
|
||||
|
||||
gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe'
|
||||
|
||||
./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip"
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install GitLabCli
|
||||
if: matrix.platform.os == 'ubuntu-latest'
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
||||
chmod +x gli
|
||||
mv gli $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Packing Linux builds
|
||||
if: matrix.platform.os == 'ubuntu-latest'
|
||||
run: |
|
||||
pushd publish
|
||||
rm libarmeilleure-jitsupport.dylib
|
||||
chmod +x Ryujinx.sh Ryujinx
|
||||
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
||||
popd
|
||||
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz"
|
||||
shell: bash
|
||||
|
||||
- name: Build AppImage (Linux)
|
||||
if: matrix.platform.os == 'ubuntu-latest'
|
||||
run: |
|
||||
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
|
||||
PLATFORM_NAME="${{ matrix.platform.name }}"
|
||||
|
||||
sudo apt install -y zsync desktop-file-utils appstream
|
||||
|
||||
mkdir -p tools
|
||||
export PATH="$PATH:$(readlink -f tools)"
|
||||
|
||||
# Setup appimagetool
|
||||
wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
|
||||
chmod +x tools/appimagetool
|
||||
chmod +x distribution/linux/appimage/build-appimage.sh
|
||||
|
||||
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
|
||||
if [ "$PLATFORM_NAME" = "linux-x64" ]; then
|
||||
ARCH_NAME=x64
|
||||
export ARCH=x86_64
|
||||
elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
|
||||
ARCH_NAME=arm64
|
||||
export ARCH=aarch64
|
||||
else
|
||||
echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|*-$ARCH_NAME.AppImage.zsync"
|
||||
BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
|
||||
|
||||
pushd publish_appimage
|
||||
mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage
|
||||
mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
|
||||
popd
|
||||
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage"
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync"
|
||||
shell: bash
|
||||
|
||||
macos_release:
|
||||
name: Release MacOS universal
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
global-json-file: global.json
|
||||
|
||||
- name: Setup LLVM 17
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 17
|
||||
|
||||
- name: Install GitLabCli
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
||||
chmod +x gli
|
||||
mv gli $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install rcodesign
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R indygreg/apple-platform-rs -O apple-codesign.tar.gz -p 'apple-codesign-*-x86_64-unknown-linux-musl.tar.gz'
|
||||
tar -xzvf apple-codesign.tar.gz --wildcards '*/rcodesign' --strip-components=1
|
||||
rm apple-codesign.tar.gz
|
||||
mv rcodesign $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get version info
|
||||
id: version_info
|
||||
run: |
|
||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} + 10))" >> $GITHUB_OUTPUT
|
||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Configure for release
|
||||
run: |
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
shell: bash
|
||||
|
||||
- name: Publish macOS Ryujinx
|
||||
run: |
|
||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|publish/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz"
|
||||
|
||||
create_gitlab_release:
|
||||
name: Create GitLab Release
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- macos_release
|
||||
- release
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get version info
|
||||
id: version_info
|
||||
run: |
|
||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} + 10))" >> $GITHUB_OUTPUT
|
||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Install GitLabCli
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
||||
chmod +x gli
|
||||
mv gli $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create release
|
||||
run: |
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateReleaseFromGenericPackageFiles "Ryubing|${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}|test|THIS IS NOT INTENDED FOR END USER USAGE"
|
166
.github/workflows/release.yml
vendored
166
.github/workflows/release.yml
vendored
@ -11,57 +11,9 @@ env:
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
RYUJINX_BASE_VERSION: "1.3"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "release"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_OWNER: "Ryubing"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO: "Ryujinx"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "Stable-Releases"
|
||||
RELEASE: 1
|
||||
|
||||
jobs:
|
||||
tag:
|
||||
name: Create tag
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Get version info
|
||||
id: version_info
|
||||
run: |
|
||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Install GitLabCli
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
||||
chmod +x gli
|
||||
mv gli $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create GitLab tag
|
||||
run: gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateTag "${{ steps.version_info.outputs.build_version }}|master"
|
||||
|
||||
- name: Create release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
name: ${{ steps.version_info.outputs.build_version }}
|
||||
tag: ${{ steps.version_info.outputs.build_version }}
|
||||
body: |
|
||||
# Stable builds:
|
||||
| Platform | Artifact |
|
||||
|--|--|
|
||||
| Windows 64-bit | [Stable Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
|
||||
| Windows ARM 64-bit | [Stable Windows ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) |
|
||||
| Linux 64-bit | [Stable Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
|
||||
| Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
||||
| macOS | [Stable macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
||||
|
||||
**[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }})**
|
||||
omitBodyDuringUpdate: true
|
||||
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
|
||||
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
|
||||
release:
|
||||
name: Release for ${{ matrix.platform.name }}
|
||||
runs-on: ${{ matrix.platform.os }}
|
||||
@ -69,7 +21,7 @@ jobs:
|
||||
matrix:
|
||||
platform:
|
||||
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
||||
- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
|
||||
#- { name: win-arm64, os: windows-latest, zip_os_name: win_arm64 }
|
||||
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
|
||||
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
|
||||
steps:
|
||||
@ -95,9 +47,6 @@ jobs:
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
shell: bash
|
||||
|
||||
@ -115,7 +64,24 @@ jobs:
|
||||
rm libarmeilleure-jitsupport.dylib
|
||||
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
|
||||
popd
|
||||
|
||||
gh release download -R GreemDev/GLI -O gli.exe -p 'GitLabCli-win_x64.exe'
|
||||
|
||||
./gli.exe --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip"
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install GitLabCli
|
||||
if: matrix.platform.os == 'ubuntu-latest'
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
||||
chmod +x gli
|
||||
mv gli $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Packing Linux builds
|
||||
if: matrix.platform.os == 'ubuntu-latest'
|
||||
@ -125,7 +91,11 @@ jobs:
|
||||
chmod +x Ryujinx.sh Ryujinx
|
||||
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
|
||||
popd
|
||||
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz"
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build AppImage (Linux)
|
||||
if: matrix.platform.os == 'ubuntu-latest'
|
||||
@ -162,32 +132,11 @@ jobs:
|
||||
mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage
|
||||
mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
|
||||
popd
|
||||
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage"
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync"
|
||||
shell: bash
|
||||
|
||||
- name: Pushing new release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
name: ${{ steps.version_info.outputs.build_version }}
|
||||
artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*"
|
||||
tag: ${{ steps.version_info.outputs.build_version }}
|
||||
body: |
|
||||
# Stable builds:
|
||||
| Platform | Artifact |
|
||||
|--|--|
|
||||
| Windows 64-bit | [Stable Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
|
||||
| Windows ARM 64-bit | [Stable Windows ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_arm64.zip) |
|
||||
| Linux 64-bit | [Stable Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
|
||||
| Linux ARM 64-bit | [Stable Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
|
||||
| macOS | [Stable macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
|
||||
|
||||
**[Full Changelog](https://git.ryujinx.app/ryubing/ryujinx/-/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }})**
|
||||
omitBodyDuringUpdate: true
|
||||
allowUpdates: true
|
||||
replacesArtifacts: true
|
||||
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
|
||||
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
|
||||
macos_release:
|
||||
name: Release MacOS universal
|
||||
runs-on: ubuntu-24.04
|
||||
@ -203,6 +152,16 @@ jobs:
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 17
|
||||
|
||||
- name: Install GitLabCli
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
||||
chmod +x gli
|
||||
mv gli $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install rcodesign
|
||||
run: |
|
||||
@ -227,26 +186,49 @@ jobs:
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||
shell: bash
|
||||
|
||||
- name: Publish macOS Ryujinx
|
||||
run: |
|
||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=UploadGenericPackage "Ryubing|${{ steps.version_info.outputs.build_version }}|publish/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz"
|
||||
|
||||
create_gitlab_release:
|
||||
name: Create GitLab Release
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- macos_release
|
||||
- release
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get version info
|
||||
id: version_info
|
||||
run: |
|
||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Pushing new release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
name: ${{ steps.version_info.outputs.build_version }}
|
||||
artifacts: "publish/*.tar.gz"
|
||||
tag: ${{ steps.version_info.outputs.build_version }}
|
||||
body: ""
|
||||
omitBodyDuringUpdate: true
|
||||
allowUpdates: true
|
||||
replacesArtifacts: true
|
||||
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
|
||||
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
- name: Install GitLabCli
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
||||
chmod +x gli
|
||||
mv gli $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create release
|
||||
run: |
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=CreateReleaseFromGenericPackageFiles "Ryubing|${{ steps.version_info.outputs.build_version }}|${{ steps.version_info.outputs.git_short_hash }}|${{ steps.version_info.outputs.build_version }}|msd:${{ steps.version_info.outputs.build_version }}"
|
||||
|
||||
- name: Send notification webhook
|
||||
run: |
|
||||
gli --access-token=${{ secrets.GITLAB_TOKEN }} --project=ryubing/ryujinx --command=SendUpdateMessage "${{ steps.version_info.outputs.build_version }}|32cd32|${{ secrets.STABLE_DISCORD_WEBHOOK }}|https://avatars.githubusercontent.com/u/192939710?s=200&v=4|false"
|
||||
|
||||
- name: Notify update server of new builds
|
||||
run: |
|
||||
curl 'https://update.ryujinx.app/api/v1/admin/refresh_cache?rc=stable' -X PATCH -H 'accept: */*' -H 'Authorization: ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }}'
|
||||
|
18
BuildAndPushLibraries.sh
Normal file
18
BuildAndPushLibraries.sh
Normal file
@ -0,0 +1,18 @@
|
||||
function pub {
|
||||
dotnet publish -c release
|
||||
}
|
||||
|
||||
function package {
|
||||
cd src/$1
|
||||
pub
|
||||
mv bin/Release/$1.1.0.0.nupkg ../../pkgs/$1.1.0.0.nupkg
|
||||
cd ../../
|
||||
}
|
||||
|
||||
rm -rf pkgs
|
||||
mkdir pkgs
|
||||
|
||||
package ARMeilleure
|
||||
package Ryujinx.Memory
|
||||
|
||||
dotnet nuget push pkgs/*.nupkg --source RyubingPkgs
|
11
CHANGELOG.md
11
CHANGELOG.md
@ -2,18 +2,17 @@
|
||||
|
||||
All updates to this Ryujinx branch will be documented in this file.
|
||||
|
||||
## [1.3.2](<https://git.ryujinx.app/ryubing/ryujinx/-/releases/1.3.2>) - 2025-06-09
|
||||
|
||||
## [1.2.86](<https://git.ryujinx.app/ryubing/ryujinx/-/releases/1.2.86>) - 2025-03-13
|
||||
A list of notable changes can be found on the release linked in the version number above.
|
||||
## [1.3.1](<https://git.ryujinx.app/ryubing/ryujinx/-/releases/1.3.1>) - 2025-04-23
|
||||
|
||||
## [1.2.86](<https://github.com/Ryubing/Stable-Releases/releases/tag/1.2.86>) - 2025-03-13
|
||||
|
||||
## [1.2.82](<https://web.archive.org/web/20250312010534/https://github.com/Ryubing/Ryujinx/releases/tag/1.2.82>) - 2025-02-16
|
||||
A list of notable changes can be found on the release linked in the version number above.
|
||||
|
||||
## [1.2.80-81](<https://web.archive.org/web/20250302064257/https://github.com/Ryubing/Ryujinx/releases/tag/1.2.81>) - 2025-01-22
|
||||
A list of notable changes can be found on the release linked in the version number above.
|
||||
|
||||
## [1.2.78](<https://web.archive.org/web/20250301174537/https://github.com/Ryubing/Ryujinx/releases/tag/1.2.78>) - 2024-12-19
|
||||
A list of notable changes can be found on the release linked in the version number above.
|
||||
|
||||
## [1.2.73-1.2.76](<https://web.archive.org/web/20250209202612/https://github.com/Ryubing/Ryujinx/releases/tag/1.2.76>) - 2024-11-19
|
||||
A list of notable changes can be found on the release linked in the version number above.
|
||||
@ -252,4 +251,4 @@ Added Low-power PPTC mode strings to the translation files.
|
||||
- Autoload DLC/Updates from dir ([#12](https://github.com/GreemDev/Ryujinx/pull/12)).
|
||||
- Changed executable icon to rainbow logo.
|
||||
- Extract Data > Logo now also extracts the square thumbnail you see for the game in the UI.
|
||||
- The "use random UUID hack" checkbox in the Amiibo screen now remembers its last state when you reopen the window in a given session.
|
||||
- The "use random UUID hack" checkbox in the Amiibo screen now remembers its last state when you reopen the window in a given session.
|
||||
|
@ -1,6 +1,6 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<LangVersion>preview</LangVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
@ -23,7 +23,6 @@
|
||||
<PackageVersion Include="DynamicData" Version="9.0.4" />
|
||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
|
||||
<PackageVersion Include="Humanizer" Version="2.14.1" />
|
||||
<PackageVersion Include="LibHac" Version="0.19.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.3.0" />
|
||||
@ -41,7 +40,10 @@
|
||||
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||
<PackageVersion Include="Ryujinx.LibHac" Version="0.20.0" />
|
||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
||||
<PackageVersion Include="Ryujinx.UpdateClient" Version="1.0.29" />
|
||||
<PackageVersion Include="Ryujinx.Systems.Update.Common" Version="1.0.29" />
|
||||
<PackageVersion Include="Gommon" Version="2.7.1.1" />
|
||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageVersion Include="Sep" Version="0.6.0" />
|
||||
|
14
README.md
14
README.md
@ -7,8 +7,8 @@
|
||||
|
||||
# Ryujinx
|
||||
|
||||
[](https://github.com/Ryubing/Stable-Releases/releases/latest)
|
||||
[](https://github.com/Ryubing/Canary-Releases/releases/latest)
|
||||
[](https://update.ryujinx.app/latest/stable)
|
||||
[](https://update.ryujinx.app/latest/canary)
|
||||
<br>
|
||||
<a href="https://discord.gg/PEuzjrFXUA">
|
||||
<img src="https://img.shields.io/discord/1294443224030511104?color=5865F2&label=Ryubing&logo=discord&logoColor=white" alt="Discord">
|
||||
@ -31,7 +31,7 @@
|
||||
<br>
|
||||
This is not a Ryujinx revival project. This is not a Phoenix project.
|
||||
<br>
|
||||
Guides and documentation can be found on the <a href="https://git.ryujinx.app/ryubing/ryujinx/-/wikis/home">Wiki tab</a>.
|
||||
Guides and documentation can be found on the <a href="https://git.ryujinx.app/groups/ryubing/-/wikis/home">Wiki tab</a>.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
@ -49,13 +49,13 @@ Stable builds are made every so often, based on the `master` branch, that then g
|
||||
These stable builds exist so that the end user can get a more **enjoyable and stable experience**.
|
||||
They are released every month or so, to ensure consistent updates, while not being an annoying amount of individual updates to download over the course of that month.
|
||||
|
||||
You can find the latest stable release [here](https://github.com/Ryubing/Stable-Releases/releases/latest).
|
||||
You can find the stable releases [here](https://git.ryujinx.app/ryubing/ryujinx/-/releases).
|
||||
|
||||
Canary builds are compiled automatically for each commit on the `master` branch.
|
||||
While we strive to ensure optimal stability and performance prior to pushing an update, these builds **may be unstable or completely broken**.
|
||||
These canary builds are only recommended for experienced users.
|
||||
|
||||
You can find the latest canary release [here](https://github.com/Ryubing/Canary-Releases/releases/latest).
|
||||
You can find the canary releases [here](https://git.ryujinx.app/ryubing/canary/-/releases).
|
||||
|
||||
## Documentation
|
||||
|
||||
@ -111,7 +111,7 @@ See [LICENSE.txt](LICENSE.txt) and [THIRDPARTY.md](distribution/legal/THIRDPARTY
|
||||
|
||||
## Credits
|
||||
|
||||
- [LibHac](https://github.com/Thealexbarney/LibHac) is used for our file-system.
|
||||
- [LibHac](https://git.ryujinx.app/ryubing/libhac) is used for our file-system.
|
||||
- [AmiiboAPI](https://www.amiiboapi.com) is used in our Amiibo emulation.
|
||||
- [ldn_mitm](https://github.com/spacemeowx2/ldn_mitm) is used for one of our available multiplayer modes.
|
||||
- [ShellLink](https://github.com/securifybv/ShellLink) is used for Windows shortcut generation.
|
||||
- [ShellLink](https://github.com/securifybv/ShellLink) is used for Windows shortcut generation.
|
@ -77,17 +77,19 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Gene
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
.github\workflows\build.yml = .github\workflows\build.yml
|
||||
.github\workflows\canary.yml = .github\workflows\canary.yml
|
||||
Directory.Packages.props = Directory.Packages.props
|
||||
Directory.Build.props = Directory.Build.props
|
||||
.github\workflows\release.yml = .github\workflows\release.yml
|
||||
nuget.config = nuget.config
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
1292
assets/locales.json
1292
assets/locales.json
File diff suppressed because it is too large
Load Diff
@ -33,23 +33,29 @@ echo -n "APPL????" > "$APP_BUNDLE_DIRECTORY/Contents/PkgInfo"
|
||||
echo "Running bundle fix up python script"
|
||||
python3 bundle_fix_up.py "$APP_BUNDLE_DIRECTORY" MacOS/Ryujinx
|
||||
|
||||
# Resign all dyplib files as ad-hoc after changing them
|
||||
find "$APP_BUNDLE_DIRECTORY/Contents/Frameworks" -type f -name "*.dylib" -exec codesign --force --sign - {} \;
|
||||
|
||||
# Now sign it
|
||||
echo "Starting signing process"
|
||||
if ! [ -x "$(command -v codesign)" ];
|
||||
then
|
||||
if ! [ -x "$(command -v rcodesign)" ];
|
||||
then
|
||||
echo "Cannot find rcodesign on your system, please install rcodesign."
|
||||
echo "Cannot find rcodesign on your system, please install rcodesign and ensure it is in your search path."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# cargo install apple-codesign
|
||||
echo "Using rcodesign for ad-hoc signing"
|
||||
|
||||
echo "Resigning all frameworks dylib files as ad-hoc"
|
||||
find "$APP_BUNDLE_DIRECTORY/Contents/Frameworks" -type f -name "*.dylib" -exec rcodesign sign {} \;
|
||||
|
||||
echo "Signing app bundle as ad-hoc"
|
||||
rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$APP_BUNDLE_DIRECTORY"
|
||||
else
|
||||
echo "Using codesign for ad-hoc signing"
|
||||
|
||||
echo "Resigning all frameworks dylib files as ad-hoc"
|
||||
find "$APP_BUNDLE_DIRECTORY/Contents/Frameworks" -type f -name "*.dylib" -exec codesign --force --sign - {} \;
|
||||
|
||||
echo "Signing app bundle as ad-hoc"
|
||||
codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f -s - "$APP_BUNDLE_DIRECTORY"
|
||||
fi
|
||||
|
@ -20,6 +20,18 @@ SOURCE_REVISION_ID=$6
|
||||
CONFIGURATION=$7
|
||||
CANARY=$8
|
||||
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
echo "Clearing xattr on all dot undercsore files"
|
||||
find "$BASE_DIR" -type f -name "._*" -exec sh -c '
|
||||
for f; do
|
||||
dir=$(dirname "$f")
|
||||
base=$(basename "$f")
|
||||
orig="$dir/${base#._}"
|
||||
[ -f "$orig" ] && xattr -c "$orig" || true
|
||||
done
|
||||
' sh {} +
|
||||
fi
|
||||
|
||||
if [ "$CANARY" == "1" ]; then
|
||||
RELEASE_TAR_FILE_NAME=ryujinx-canary-$VERSION-macos_universal.app.tar
|
||||
elif [ "$VERSION" == "1.1.0" ]; then
|
||||
|
@ -20,6 +20,18 @@ SOURCE_REVISION_ID=$6
|
||||
CONFIGURATION=$7
|
||||
CANARY=$8
|
||||
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
echo "Clearing xattr on all dot undercsore files"
|
||||
find "$BASE_DIR" -type f -name "._*" -exec sh -c '
|
||||
for f; do
|
||||
dir=$(dirname "$f")
|
||||
base=$(basename "$f")
|
||||
orig="$dir/${base#._}"
|
||||
[ -f "$orig" ] && xattr -c "$orig" || true
|
||||
done
|
||||
' sh {} +
|
||||
fi
|
||||
|
||||
if [ "$CANARY" == "1" ]; then
|
||||
RELEASE_TAR_FILE_NAME=nogui-ryujinx-canary-$VERSION-macos_universal.tar
|
||||
elif [ "$VERSION" == "1.1.0" ]; then
|
||||
|
@ -601,6 +601,7 @@
|
||||
010060200A4BE000,"Brawlout",ldn-untested;online,playable,2021-06-04 17:35:35
|
||||
0100C1B00E1CA000,"Brawlout Demo",demo,playable,2021-02-13 22:46:53
|
||||
010022C016DC8000,"Breakout: Recharged",slow,ingame,2022-11-06 15:32:57
|
||||
010048A021C40000,"Breakout Beyond",,playable,2025-04-26 19:11:35
|
||||
01000AA013A5E000,"Breathedge",UE4;nvdec,playable,2021-05-06 15:44:28
|
||||
01003D50100F4000,"Breathing Fear",,playable,2020-07-14 15:12:29
|
||||
010026800BB06000,"Brick Breaker",nvdec;online,playable,2020-12-15 18:26:23
|
||||
@ -1124,6 +1125,7 @@
|
||||
0100034012606000,"Family Mysteries: Poisonous Promises",audio;crash,menus,2021-11-26 12:35:06
|
||||
010017C012726000,"Fantasy Friends",,playable,2022-10-17 19:42:39
|
||||
0100767008502000,"FANTASY HERO ~unsigned legacy~",,playable,2022-07-26 12:28:52
|
||||
0100755017EE0000,"FANTASY LIFE i: The Girl Who Steals Time",gpu;crash;vulkan-backend-bug,ingame,2025-06-08 20:41:00
|
||||
0100944003820000,"Fantasy Strike",online,playable,2021-02-27 01:59:18
|
||||
01000E2012F6E000,"Fantasy Tavern Sextet -Vol.1 New World Days-",gpu;crash;Needs Update,ingame,2022-12-05 16:48:00
|
||||
01005C10136CA000,"Fantasy Tavern Sextet -Vol.2 Adventurer's Days-",gpu;slow;crash,ingame,2021-11-06 02:57:29
|
||||
@ -2028,6 +2030,7 @@
|
||||
0100628004BCE000,"Nights of Azure 2: Bride of the New Moon",crash;nvdec;regression,menus,2022-11-24 16:00:39
|
||||
010042300C4F6000,"Nightshade/百花百狼",nvdec,playable,2020-05-10 19:43:31
|
||||
0100AA0008736000,"Nihilumbra",,playable,2020-05-10 16:00:12
|
||||
01009FA01FF6C000,"Nikoderiko: The Magical World",gpu,ingame,2025-04-26 19:13:31
|
||||
0100D03003F0E000,"Nine Parchments",ldn-untested,playable,2022-08-07 12:32:08
|
||||
0100E2F014F46000,"NINJA GAIDEN Σ",nvdec,playable,2022-11-13 16:27:02
|
||||
0100696014F4A000,"NINJA GAIDEN Σ2",nvdec,playable,2024-07-31 21:53:48
|
||||
@ -2433,6 +2436,7 @@
|
||||
0100E9C010EA8000,"Rise of Insanity",,playable,2020-08-30 15:42:14
|
||||
01006BA00E652000,"Rise: Race The Future",,playable,2021-02-27 13:29:06
|
||||
010020C012F48000,"Rising Hell",,playable,2022-10-31 13:54:02
|
||||
0100D1801A0F4000,"Risk of Rain Returns",,playable,2025-06-28 04:24:04
|
||||
010076D00E4BA000,"Risk of Rain 2",online-broken,playable,2024-03-04 17:01:05
|
||||
0100E8300A67A000,"RISK® Global Domination",nvdec;online-broken,playable,2022-08-01 18:53:28
|
||||
010042500FABA000,"Ritual: Crown of Horns",,playable,2021-01-26 16:01:47
|
||||
@ -2743,6 +2747,7 @@
|
||||
01005D701264A000,"SpyHack",,playable,2021-04-15 10:53:51
|
||||
010077B00E046000,"Spyro™ Reignited Trilogy",nvdec;UE4,playable,2022-09-11 18:38:33
|
||||
0100085012A0E000,"Squeakers",,playable,2020-12-13 12:13:05
|
||||
0100E1D01EB2E000,"Squeakross: Home Squeak Home",,playable,2025-06-16 02:02:00
|
||||
010009300D31C000,"Squidgies Takeover",,playable,2020-07-20 22:28:08
|
||||
0100FCD0102EC000,"Squidlit",,playable,2020-08-06 12:38:32
|
||||
0100EBF00E702000,"STAR OCEAN First Departure R",nvdec,playable,2021-07-05 19:29:16
|
||||
@ -3013,6 +3018,7 @@
|
||||
01009B101044C000,"The Legend of Heroes: Trails of Cold Steel III Demo",demo;nvdec,playable,2021-04-23 01:07:32
|
||||
0100D3C010DE8000,"The Legend of Heroes: Trails of Cold Steel IV",nvdec,playable,2021-04-23 14:01:05
|
||||
01005E5013862000,"THE LEGEND OF HEROES: ZERO NO KISEKI KAI [英雄傳說 零之軌跡:改]",crash,nothing,2021-09-30 14:41:07
|
||||
01009C901ACEE000,"The Legend of Nayuta: Boundless Trails",,ingame,2025-06-12 15:47
|
||||
01008CF01BAAC000,"The Legend of Zelda Echoes of Wisdom",nvdec;ASTC;intel-vendor-bug,playable,2024-10-01 14:11:01
|
||||
0100509005AF2000,"The Legend of Zelda: Breath of the Wild Demo",demo,ingame,2022-12-24 05:02:58
|
||||
01007EF00011E000,"The Legend of Zelda™: Breath of the Wild",gpu;amd-vendor-bug;mac-bug,ingame,2024-09-23 19:35:46
|
||||
|
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "9.0.100",
|
||||
"version": "10.0.100",
|
||||
"rollForward": "latestFeature"
|
||||
}
|
||||
}
|
||||
|
26
nuget.config
26
nuget.config
@ -1,7 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
<!-- Only needed when using pre-release versions of Ryujinx.LibHac. -->
|
||||
<!--<add key="LibHacAlpha" value="https://git.ryujinx.app/api/v4/projects/17/packages/nuget/index.json" />-->
|
||||
<add key="Ryujinx.UpdateClient" value="https://git.ryujinx.app/api/v4/projects/71/packages/nuget/index.json" />
|
||||
</packageSources>
|
||||
<packageSourceMapping>
|
||||
<!-- key value for <packageSource> should match key values from <packageSources> element -->
|
||||
<!-- These are defined and .NET still yells about multiple package sources with no mappings. Not sure what to do, this is in the docs lol -->
|
||||
<packageSource key="nuget.org">
|
||||
<package pattern="*" />
|
||||
</packageSource>
|
||||
<packageSource key="Ryujinx.UpdateClient">
|
||||
<package pattern="Ryujinx.UpdateClient" />
|
||||
<package pattern="Ryujinx.Systems.Update.Common" />
|
||||
</packageSource>
|
||||
<!--<packageSource key="LibHacAlpha">
|
||||
<package pattern="Ryujinx.LibHac" />
|
||||
</packageSource>-->
|
||||
</packageSourceMapping>
|
||||
</configuration>
|
||||
|
@ -3,10 +3,10 @@
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Memory\Ryujinx.Memory.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -254,7 +254,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
private static bool IsMemoryLoadOrStore(Instruction inst)
|
||||
{
|
||||
return inst == Instruction.Load || inst == Instruction.Store;
|
||||
return inst is Instruction.Load or Instruction.Store;
|
||||
}
|
||||
|
||||
private static bool ConstTooLong(Operand constOp, OperandType accessType)
|
||||
|
@ -25,9 +25,9 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
static class ComparisonArm64Extensions
|
||||
{
|
||||
public static ArmCondition ToArmCondition(this Comparison comp)
|
||||
extension(Comparison comparison)
|
||||
{
|
||||
return comp switch
|
||||
public ArmCondition Arm => comparison switch
|
||||
{
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Comparison.Equal => ArmCondition.Eq,
|
||||
@ -42,7 +42,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Comparison.LessUI => ArmCondition.LtUn,
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
_ => throw new ArgumentException(null, nameof(comp)),
|
||||
_ => throw new ArgumentException(null, nameof(comparison))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -181,10 +181,10 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
public void Fmov(Operand rd, Operand rn, bool topHalf)
|
||||
{
|
||||
Debug.Assert(rd.Type.IsInteger() != rn.Type.IsInteger());
|
||||
Debug.Assert(rd.Type.IsInteger != rn.Type.IsInteger);
|
||||
Debug.Assert(rd.Type == OperandType.I64 || rn.Type == OperandType.I64 || !topHalf);
|
||||
|
||||
uint opcode = rd.Type.IsInteger() ? 0b110u : 0b111u;
|
||||
uint opcode = rd.Type.IsInteger ? 0b110u : 0b111u;
|
||||
|
||||
uint rmode = topHalf ? 1u << 19 : 0u;
|
||||
uint ftype = rd.Type == OperandType.FP64 || rn.Type == OperandType.FP64 ? 1u << 22 : 0u;
|
||||
@ -411,7 +411,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
public void Mov(Operand rd, Operand rn)
|
||||
{
|
||||
if (rd.Type.IsInteger())
|
||||
if (rd.Type.IsInteger)
|
||||
{
|
||||
Orr(rd, Factory.Register(ZrRegister, RegisterType.Integer, rd.Type), rn);
|
||||
}
|
||||
@ -774,6 +774,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
instI |= 1 << 22; // sh flag
|
||||
imm >>= 12;
|
||||
}
|
||||
|
||||
WriteInstructionAuto(instI | (EncodeUImm12(imm, 0) << 10), rd, rn);
|
||||
}
|
||||
else
|
||||
@ -972,7 +973,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
uint instruction;
|
||||
int scale;
|
||||
|
||||
if (type.IsInteger())
|
||||
if (type.IsInteger)
|
||||
{
|
||||
instruction = intInst;
|
||||
|
||||
@ -1008,7 +1009,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
uint instruction;
|
||||
|
||||
if (type.IsInteger())
|
||||
if (type.IsInteger)
|
||||
{
|
||||
instruction = intInst;
|
||||
|
||||
|
@ -52,7 +52,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
// Any value AND all ones will be equal itself, so it's effectively a no-op.
|
||||
// Any value OR all ones will be equal all ones, so one can just use MOV.
|
||||
// Any value XOR all ones will be equal its inverse, so one can just use MVN.
|
||||
if (value == 0 || value == ulong.MaxValue)
|
||||
if (value is 0 or ulong.MaxValue)
|
||||
{
|
||||
immN = 0;
|
||||
immS = 0;
|
||||
|
@ -1,6 +1,7 @@
|
||||
using ARMeilleure.CodeGen.Linking;
|
||||
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using Microsoft.IO;
|
||||
using Ryujinx.Common.Memory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -14,7 +15,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
private const int CbnzInstLength = 4;
|
||||
private const int LdrLitInstLength = 4;
|
||||
|
||||
private readonly Stream _stream;
|
||||
private readonly RecyclableMemoryStream _stream;
|
||||
|
||||
public int StreamOffset => (int)_stream.Length;
|
||||
|
||||
|
@ -189,8 +189,8 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
// The only blocks which can have 0 successors are exit blocks.
|
||||
Operation last = block.Operations.Last;
|
||||
|
||||
Debug.Assert(last.Instruction == Instruction.Tailcall ||
|
||||
last.Instruction == Instruction.Return);
|
||||
Debug.Assert(last.Instruction is Instruction.Tailcall or
|
||||
Instruction.Return);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -250,7 +250,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
// ValidateBinOp(dest, src1, src2);
|
||||
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
context.Assembler.Add(dest, src1, src2);
|
||||
}
|
||||
@ -268,7 +268,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
ValidateBinOp(dest, src1, src2);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.And(dest, src1, src2);
|
||||
}
|
||||
@ -281,7 +281,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
ValidateBinOp(dest, src1, src2);
|
||||
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
context.Assembler.Eor(dest, src1, src2);
|
||||
}
|
||||
@ -298,7 +298,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
ValidateUnOp(dest, source);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.Mvn(dest, source);
|
||||
}
|
||||
@ -311,7 +311,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
ValidateBinOp(dest, src1, src2);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.Orr(dest, src1, src2);
|
||||
}
|
||||
@ -322,7 +322,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||
|
||||
ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition();
|
||||
ArmCondition cond = ((Comparison)comp.AsInt32()).Arm;
|
||||
|
||||
GenerateCompareCommon(context, operation);
|
||||
|
||||
@ -336,7 +336,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
ValidateUnOp(dest, source);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.Rev(dest, source);
|
||||
}
|
||||
@ -354,7 +354,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Debug.Assert(dest.Type == OperandType.I32);
|
||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||
|
||||
ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition();
|
||||
ArmCondition cond = ((Comparison)comp.AsInt32()).Arm;
|
||||
|
||||
GenerateCompareCommon(context, operation);
|
||||
|
||||
@ -428,7 +428,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
EnsureSameType(src1, src2);
|
||||
|
||||
Debug.Assert(src1.Type.IsInteger());
|
||||
Debug.Assert(src1.Type.IsInteger);
|
||||
|
||||
context.Assembler.Cmp(src1, src2);
|
||||
}
|
||||
@ -442,7 +442,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
EnsureSameType(dest, src2, src3);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger);
|
||||
Debug.Assert(src1.Type == OperandType.I32);
|
||||
|
||||
context.Assembler.Cmp(src1, Const(src1.Type, 0));
|
||||
@ -464,11 +464,11 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64);
|
||||
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64);
|
||||
Debug.Assert(dest.Type != source.Type);
|
||||
Debug.Assert(source.Type != OperandType.V128);
|
||||
|
||||
if (source.Type.IsInteger())
|
||||
if (source.Type.IsInteger)
|
||||
{
|
||||
context.Assembler.ScvtfScalar(dest, source);
|
||||
}
|
||||
@ -483,9 +483,9 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64);
|
||||
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64);
|
||||
Debug.Assert(dest.Type != source.Type);
|
||||
Debug.Assert(source.Type.IsInteger());
|
||||
Debug.Assert(source.Type.IsInteger);
|
||||
|
||||
context.Assembler.UcvtfScalar(dest, source);
|
||||
}
|
||||
@ -497,7 +497,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
EnsureSameType(dest, source);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() || source.Kind != OperandKind.Constant);
|
||||
Debug.Assert(dest.Type.IsInteger || source.Kind != OperandKind.Constant);
|
||||
|
||||
// Moves to the same register are useless.
|
||||
if (dest.Kind == source.Kind && dest.Value == source.Value)
|
||||
@ -529,7 +529,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
EnsureSameType(dest, source);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.Clz(dest, source);
|
||||
}
|
||||
@ -542,7 +542,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
ValidateBinOp(dest, dividend, divisor);
|
||||
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
context.Assembler.Sdiv(dest, dividend, divisor);
|
||||
}
|
||||
@ -576,7 +576,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Operand value = operation.Destination;
|
||||
Operand address = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(value.Type.IsInteger());
|
||||
Debug.Assert(value.Type.IsInteger);
|
||||
|
||||
context.Assembler.LdrhRiUn(value, address, 0);
|
||||
}
|
||||
@ -586,7 +586,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Operand value = operation.Destination;
|
||||
Operand address = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(value.Type.IsInteger());
|
||||
Debug.Assert(value.Type.IsInteger);
|
||||
|
||||
context.Assembler.LdrbRiUn(value, address, 0);
|
||||
}
|
||||
@ -604,7 +604,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
EnsureSameType(dest, src1, src2);
|
||||
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
context.Assembler.Mul(dest, src1, src2);
|
||||
}
|
||||
@ -647,7 +647,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
ValidateUnOp(dest, source);
|
||||
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
context.Assembler.Neg(dest, source);
|
||||
}
|
||||
@ -732,7 +732,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
|
||||
|
||||
context.Assembler.Sxth(dest, source);
|
||||
}
|
||||
@ -742,7 +742,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
|
||||
|
||||
context.Assembler.Sxtw(dest, source);
|
||||
}
|
||||
@ -752,7 +752,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
|
||||
|
||||
context.Assembler.Sxtb(dest, source);
|
||||
}
|
||||
@ -823,7 +823,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Operand value = operation.GetSource(1);
|
||||
Operand address = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(value.Type.IsInteger());
|
||||
Debug.Assert(value.Type.IsInteger);
|
||||
|
||||
context.Assembler.StrhRiUn(value, address, 0);
|
||||
}
|
||||
@ -833,7 +833,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Operand value = operation.GetSource(1);
|
||||
Operand address = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(value.Type.IsInteger());
|
||||
Debug.Assert(value.Type.IsInteger);
|
||||
|
||||
context.Assembler.StrbRiUn(value, address, 0);
|
||||
}
|
||||
@ -858,7 +858,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
// ValidateBinOp(dest, src1, src2);
|
||||
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
context.Assembler.Sub(dest, src1, src2);
|
||||
}
|
||||
@ -882,7 +882,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
if (dest != default)
|
||||
{
|
||||
Debug.Assert(!dest.Type.IsInteger() && source.Type.IsInteger());
|
||||
Debug.Assert(!dest.Type.IsInteger && source.Type.IsInteger);
|
||||
|
||||
OperandType destType = source.Type == OperandType.I64 ? OperandType.FP64 : OperandType.FP32;
|
||||
|
||||
@ -901,9 +901,9 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
byte index = src2.AsByte();
|
||||
|
||||
Debug.Assert(index < OperandType.V128.GetSizeInBytes() / dest.Type.GetSizeInBytes());
|
||||
Debug.Assert(index < OperandType.V128.ByteSize / dest.Type.ByteSize);
|
||||
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
context.Assembler.Umov(dest, src1, index, dest.Type == OperandType.I64 ? 3 : 2);
|
||||
}
|
||||
@ -959,7 +959,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
byte index = src3.AsByte();
|
||||
|
||||
if (src2.Type.IsInteger())
|
||||
if (src2.Type.IsInteger)
|
||||
{
|
||||
context.Assembler.Ins(dest, src2, index, src2.Type == OperandType.I64 ? 3 : 2);
|
||||
}
|
||||
@ -1007,7 +1007,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
Operand dest = operation.Destination;
|
||||
|
||||
Debug.Assert(!dest.Type.IsInteger());
|
||||
Debug.Assert(!dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.CmeqVector(dest, dest, dest, 2);
|
||||
}
|
||||
@ -1016,7 +1016,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
Operand dest = operation.Destination;
|
||||
|
||||
Debug.Assert(!dest.Type.IsInteger());
|
||||
Debug.Assert(!dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.EorVector(dest, dest, dest);
|
||||
}
|
||||
@ -1046,7 +1046,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
|
||||
|
||||
context.Assembler.Uxth(dest, source);
|
||||
}
|
||||
@ -1056,7 +1056,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
|
||||
|
||||
// We can eliminate the move if source is already 32-bit and the registers are the same.
|
||||
if (dest.Value == source.Value && source.Type == OperandType.I32)
|
||||
@ -1072,7 +1072,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
|
||||
|
||||
context.Assembler.Uxtb(dest, source);
|
||||
}
|
||||
@ -1169,7 +1169,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
context.Assembler.StrRiPre(Register(reg, type), Register(SpRegister), -calleeSaveRegionSize);
|
||||
}
|
||||
|
||||
offset += type.GetSizeInBytes();
|
||||
offset += type.ByteSize;
|
||||
}
|
||||
|
||||
while (mask != 0)
|
||||
@ -1195,7 +1195,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
context.Assembler.StpRiPre(Register(reg, type), Register(reg2, type), Register(SpRegister), -calleeSaveRegionSize);
|
||||
}
|
||||
|
||||
offset += type.GetSizeInBytes() * 2;
|
||||
offset += type.ByteSize * 2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1273,7 +1273,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
mask &= ~(1 << reg2);
|
||||
|
||||
offset -= type.GetSizeInBytes() * 2;
|
||||
offset -= type.ByteSize * 2;
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
@ -1286,7 +1286,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
}
|
||||
else
|
||||
{
|
||||
offset -= type.GetSizeInBytes();
|
||||
offset -= type.ByteSize;
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
@ -1435,12 +1435,12 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
OperandType valueType = GetMemOpValueType(currentOp);
|
||||
|
||||
if (valueType != GetMemOpValueType(nextOp) || op1Offset + valueType.GetSizeInBytes() != op2Offset)
|
||||
if (valueType != GetMemOpValueType(nextOp) || op1Offset + valueType.ByteSize != op2Offset)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CodeGenCommon.ConstFitsOnSImm7(op1Offset, valueType.GetSizeInBytesLog2()))
|
||||
if (!CodeGenCommon.ConstFitsOnSImm7(op1Offset, valueType.ByteSizeLog2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -1463,7 +1463,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
private static bool IsLoadOrStore(Operation operation)
|
||||
{
|
||||
return operation.Instruction == Instruction.Load || operation.Instruction == Instruction.Store;
|
||||
return operation.Instruction is Instruction.Load or Instruction.Store;
|
||||
}
|
||||
|
||||
private static OperandType GetMemOpValueType(Operation operation)
|
||||
@ -1499,6 +1499,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (memOp.Index != default)
|
||||
{
|
||||
return false;
|
||||
@ -1548,12 +1549,12 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
// EnsureSameReg (dest, src1);
|
||||
EnsureSameType(dest, src1);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && src2.Type == OperandType.I32);
|
||||
Debug.Assert(dest.Type.IsInteger && src2.Type == OperandType.I32);
|
||||
}
|
||||
|
||||
private static void EnsureSameReg(Operand op1, Operand op2)
|
||||
{
|
||||
Debug.Assert(op1.Kind == OperandKind.Register || op1.Kind == OperandKind.Memory);
|
||||
Debug.Assert(op1.Kind is OperandKind.Register or OperandKind.Memory);
|
||||
Debug.Assert(op1.Kind == op2.Kind);
|
||||
Debug.Assert(op1.Value == op2.Value);
|
||||
}
|
||||
|
@ -462,7 +462,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
instruction |= (sz << 22);
|
||||
|
||||
if (rd.Type.IsInteger())
|
||||
if (rd.Type.IsInteger)
|
||||
{
|
||||
context.Assembler.WriteInstructionAuto(instruction, rd, rn);
|
||||
}
|
||||
@ -490,7 +490,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
instruction |= (sz << 22);
|
||||
instruction |= (64 - fBits) << 10;
|
||||
|
||||
if (rd.Type.IsInteger())
|
||||
if (rd.Type.IsInteger)
|
||||
{
|
||||
Debug.Assert(rd.Type != OperandType.I32 || fBits <= 32);
|
||||
|
||||
@ -509,7 +509,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
context.Assembler.WriteInstruction(instruction, rd, rn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void GenerateScalarTernary(
|
||||
|
@ -137,6 +137,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
return val != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
if (src1.Kind == OperandKind.Constant)
|
||||
{
|
||||
if (!src1.Type.IsInteger())
|
||||
if (!src1.Type.IsInteger)
|
||||
{
|
||||
// Handle non-integer types (FP32, FP64 and V128).
|
||||
// For instructions without an immediate operand, we do the following:
|
||||
@ -161,7 +161,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
if (src2.Kind == OperandKind.Constant)
|
||||
{
|
||||
if (!src2.Type.IsInteger())
|
||||
if (!src2.Type.IsInteger)
|
||||
{
|
||||
src2 = AddFloatConstantCopy(constants, nodes, node, src2);
|
||||
|
||||
@ -191,7 +191,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
if (src.Kind == OperandKind.Constant)
|
||||
{
|
||||
if (!src.Type.IsInteger())
|
||||
if (!src.Type.IsInteger)
|
||||
{
|
||||
src = AddFloatConstantCopy(constants, nodes, node, src);
|
||||
|
||||
@ -282,7 +282,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
bool passOnReg;
|
||||
|
||||
if (source.Type.IsInteger())
|
||||
if (source.Type.IsInteger)
|
||||
{
|
||||
passOnReg = intCount < intMax;
|
||||
}
|
||||
@ -309,7 +309,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
if (passOnReg)
|
||||
{
|
||||
Operand argReg = source.Type.IsInteger()
|
||||
Operand argReg = source.Type.IsInteger
|
||||
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
|
||||
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
|
||||
|
||||
@ -327,7 +327,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
InsertConstantRegCopies(constants, nodes, nodes.AddBefore(node, spillOp));
|
||||
|
||||
stackOffset += source.Type.GetSizeInBytes();
|
||||
stackOffset += source.Type.ByteSize;
|
||||
}
|
||||
}
|
||||
|
||||
@ -345,7 +345,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand retReg = dest.Type.IsInteger()
|
||||
Operand retReg = dest.Type.IsInteger
|
||||
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
|
||||
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
|
||||
|
||||
@ -385,7 +385,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
bool passOnReg;
|
||||
|
||||
if (source.Type.IsInteger())
|
||||
if (source.Type.IsInteger)
|
||||
{
|
||||
passOnReg = intCount + 1 < intMax;
|
||||
}
|
||||
@ -408,7 +408,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
if (passOnReg)
|
||||
{
|
||||
Operand argReg = source.Type.IsInteger()
|
||||
Operand argReg = source.Type.IsInteger
|
||||
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
|
||||
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
|
||||
|
||||
@ -521,7 +521,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand retReg = source.Type.IsInteger()
|
||||
Operand retReg = source.Type.IsInteger
|
||||
? Gpr(CallingConvention.GetIntReturnRegister(), source.Type)
|
||||
: Xmm(CallingConvention.GetVecReturnRegister(), source.Type);
|
||||
|
||||
@ -551,7 +551,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
OperandType argType = cctx.FuncArgTypes[cIndex];
|
||||
|
||||
if (argType.IsInteger())
|
||||
if (argType.IsInteger)
|
||||
{
|
||||
intCount++;
|
||||
}
|
||||
@ -567,7 +567,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
bool passOnReg;
|
||||
|
||||
if (source.Type.IsInteger())
|
||||
if (source.Type.IsInteger)
|
||||
{
|
||||
passOnReg = intCount < CallingConvention.GetArgumentsOnRegsCount();
|
||||
}
|
||||
@ -606,7 +606,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
Operand pArg = Local(dest.Type);
|
||||
|
||||
Operand argReg = dest.Type.IsInteger()
|
||||
Operand argReg = dest.Type.IsInteger
|
||||
? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type)
|
||||
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type);
|
||||
|
||||
@ -736,19 +736,19 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
IntrinsicInfo info = IntrinsicTable.GetInfo(intrinsic & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask));
|
||||
|
||||
return info.Type == IntrinsicType.ScalarBinaryRd ||
|
||||
info.Type == IntrinsicType.ScalarTernaryFPRdByElem ||
|
||||
info.Type == IntrinsicType.ScalarTernaryShlRd ||
|
||||
info.Type == IntrinsicType.ScalarTernaryShrRd ||
|
||||
info.Type == IntrinsicType.Vector128BinaryRd ||
|
||||
info.Type == IntrinsicType.VectorBinaryRd ||
|
||||
info.Type == IntrinsicType.VectorInsertByElem ||
|
||||
info.Type == IntrinsicType.VectorTernaryRd ||
|
||||
info.Type == IntrinsicType.VectorTernaryRdBitwise ||
|
||||
info.Type == IntrinsicType.VectorTernaryFPRdByElem ||
|
||||
info.Type == IntrinsicType.VectorTernaryRdByElem ||
|
||||
info.Type == IntrinsicType.VectorTernaryShlRd ||
|
||||
info.Type == IntrinsicType.VectorTernaryShrRd;
|
||||
return info.Type is IntrinsicType.ScalarBinaryRd or
|
||||
IntrinsicType.ScalarTernaryFPRdByElem or
|
||||
IntrinsicType.ScalarTernaryShlRd or
|
||||
IntrinsicType.ScalarTernaryShrRd or
|
||||
IntrinsicType.Vector128BinaryRd or
|
||||
IntrinsicType.VectorBinaryRd or
|
||||
IntrinsicType.VectorInsertByElem or
|
||||
IntrinsicType.VectorTernaryRd or
|
||||
IntrinsicType.VectorTernaryRdBitwise or
|
||||
IntrinsicType.VectorTernaryFPRdByElem or
|
||||
IntrinsicType.VectorTernaryRdByElem or
|
||||
IntrinsicType.VectorTernaryShlRd or
|
||||
IntrinsicType.VectorTernaryShrRd;
|
||||
}
|
||||
|
||||
private static bool HasConstSrc1(Operation node, ulong value)
|
||||
@ -849,7 +849,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
Comparison compType = (Comparison)comp.AsInt32();
|
||||
|
||||
return compType == Comparison.Equal || compType == Comparison.NotEqual;
|
||||
return compType is Comparison.Equal or Comparison.NotEqual;
|
||||
}
|
||||
}
|
||||
|
||||
@ -871,9 +871,9 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
IntrinsicInfo info = IntrinsicTable.GetInfo(intrinsic & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask));
|
||||
|
||||
// Those have integer inputs that don't support consts.
|
||||
return info.Type != IntrinsicType.ScalarFPConvGpr &&
|
||||
info.Type != IntrinsicType.ScalarFPConvFixedGpr &&
|
||||
info.Type != IntrinsicType.SetRegister;
|
||||
return info.Type is not IntrinsicType.ScalarFPConvGpr and
|
||||
not IntrinsicType.ScalarFPConvFixedGpr and
|
||||
not IntrinsicType.SetRegister;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -51,7 +51,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
if (trueSucc == block.ListNext)
|
||||
{
|
||||
Comparison comp = (Comparison)branchOp.GetSource(2).AsInt32();
|
||||
Comparison compInv = comp.Invert();
|
||||
Comparison compInv = comp.Inverse;
|
||||
|
||||
branchOp.SetSource(2, Const((int)compInv));
|
||||
|
||||
|
@ -37,6 +37,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateBinaryI64(operation, (x, y) => x + y);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.BitwiseAnd:
|
||||
@ -48,6 +49,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateBinaryI64(operation, (x, y) => x & y);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.BitwiseExclusiveOr:
|
||||
@ -59,6 +61,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateBinaryI64(operation, (x, y) => x ^ y);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.BitwiseNot:
|
||||
@ -70,6 +73,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateUnaryI64(operation, (x) => ~x);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.BitwiseOr:
|
||||
@ -81,6 +85,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateBinaryI64(operation, (x, y) => x | y);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.ConvertI64ToI32:
|
||||
@ -88,6 +93,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateUnaryI32(operation, (x) => x);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.Compare:
|
||||
@ -129,6 +135,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.Copy:
|
||||
@ -140,6 +147,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateUnaryI64(operation, (x) => x);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.Divide:
|
||||
@ -151,6 +159,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateBinaryI64(operation, (x, y) => y != 0 ? x / y : 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.DivideUI:
|
||||
@ -162,6 +171,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateBinaryI64(operation, (x, y) => y != 0 ? (long)((ulong)x / (ulong)y) : 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.Multiply:
|
||||
@ -173,6 +183,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateBinaryI64(operation, (x, y) => x * y);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.Negate:
|
||||
@ -184,6 +195,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateUnaryI64(operation, (x) => -x);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.ShiftLeft:
|
||||
@ -195,6 +207,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateBinaryI64(operation, (x, y) => x << (int)y);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.ShiftRightSI:
|
||||
@ -206,6 +219,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateBinaryI64(operation, (x, y) => x >> (int)y);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.ShiftRightUI:
|
||||
@ -217,6 +231,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateBinaryI64(operation, (x, y) => (long)((ulong)x >> (int)y));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.SignExtend16:
|
||||
@ -228,6 +243,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateUnaryI64(operation, (x) => (short)x);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.SignExtend32:
|
||||
@ -239,6 +255,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateUnaryI64(operation, (x) => (int)x);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.SignExtend8:
|
||||
@ -250,6 +267,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateUnaryI64(operation, (x) => (sbyte)x);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.ZeroExtend16:
|
||||
@ -261,6 +279,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateUnaryI64(operation, (x) => (ushort)x);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.ZeroExtend32:
|
||||
@ -272,6 +291,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateUnaryI64(operation, (x) => (uint)x);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.ZeroExtend8:
|
||||
@ -283,6 +303,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateUnaryI64(operation, (x) => (byte)x);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.Subtract:
|
||||
@ -294,6 +315,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
{
|
||||
EvaluateBinaryI64(operation, (x, y) => x - y);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
}
|
||||
else if (otherCompType == Comparison.Equal)
|
||||
{
|
||||
propCompType = compType.Invert();
|
||||
propCompType = compType.Inverse;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -227,11 +227,11 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
|
||||
private static bool HasSideEffects(Operation node)
|
||||
{
|
||||
return node.Instruction == Instruction.Call
|
||||
|| node.Instruction == Instruction.Tailcall
|
||||
|| node.Instruction == Instruction.CompareAndSwap
|
||||
|| node.Instruction == Instruction.CompareAndSwap16
|
||||
|| node.Instruction == Instruction.CompareAndSwap8;
|
||||
return node.Instruction is Instruction.Call
|
||||
or Instruction.Tailcall
|
||||
or Instruction.CompareAndSwap
|
||||
or Instruction.CompareAndSwap16
|
||||
or Instruction.CompareAndSwap8;
|
||||
}
|
||||
|
||||
private static bool IsPropagableCompare(Operation operation)
|
||||
|
@ -105,7 +105,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
Operand x = operation.GetSource(0);
|
||||
Operand y = operation.GetSource(1);
|
||||
|
||||
if (x == y && x.Type.IsInteger())
|
||||
if (x == y && x.Type.IsInteger)
|
||||
{
|
||||
operation.TurnIntoCopy(Const(x.Type, 0));
|
||||
}
|
||||
@ -161,7 +161,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
|
||||
private static bool IsConstEqual(Operand operand, ulong comparand)
|
||||
{
|
||||
if (operand.Kind != OperandKind.Constant || !operand.Type.IsInteger())
|
||||
if (operand.Kind != OperandKind.Constant || !operand.Type.IsInteger)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
{
|
||||
OperandType type = types[copyDest];
|
||||
|
||||
type = type.IsInteger() ? OperandType.I64 : OperandType.V128;
|
||||
type = type.IsInteger ? OperandType.I64 : OperandType.V128;
|
||||
|
||||
EmitXorSwap(sequence, GetRegister(copyDest, type), GetRegister(copySource, type));
|
||||
|
||||
|
@ -178,7 +178,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
}
|
||||
else if (dest.Kind == OperandKind.Register)
|
||||
{
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
intFixedRegisters |= 1 << dest.GetRegister().Index;
|
||||
}
|
||||
@ -236,7 +236,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
{
|
||||
Register reg = info.Register.GetRegister();
|
||||
|
||||
if (local.Type.IsInteger())
|
||||
if (local.Type.IsInteger)
|
||||
{
|
||||
intLocalFreeRegisters |= 1 << reg.Index;
|
||||
}
|
||||
@ -254,7 +254,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
|
||||
if (temp == default || info.Sequence != sequence)
|
||||
{
|
||||
temp = local.Type.IsInteger()
|
||||
temp = local.Type.IsInteger
|
||||
? GetSpillTemp(local, intSpillTempRegisters, ref intLocalUse)
|
||||
: GetSpillTemp(local, vecSpillTempRegisters, ref vecLocalUse);
|
||||
|
||||
@ -335,7 +335,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
|
||||
if (info.UsesAllocated == 0)
|
||||
{
|
||||
int mask = dest.Type.IsInteger()
|
||||
int mask = dest.Type.IsInteger
|
||||
? intLocalFreeRegisters
|
||||
: vecLocalFreeRegisters;
|
||||
|
||||
@ -343,9 +343,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
{
|
||||
int selectedReg = BitOperations.TrailingZeroCount(mask);
|
||||
|
||||
info.Register = Register(selectedReg, info.Type.ToRegisterType(), info.Type);
|
||||
info.Register = Register(selectedReg, info.Type.Register, info.Type);
|
||||
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
intLocalFreeRegisters &= ~(1 << selectedReg);
|
||||
intUsedRegisters |= 1 << selectedReg;
|
||||
@ -359,7 +359,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
else
|
||||
{
|
||||
info.Register = default;
|
||||
info.SpillOffset = Const(stackAlloc.Allocate(dest.Type.GetSizeInBytes()));
|
||||
info.SpillOffset = Const(stackAlloc.Allocate(dest.Type.ByteSize));
|
||||
}
|
||||
}
|
||||
|
||||
@ -377,7 +377,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
|
||||
if (temp == default || info.Sequence != sequence)
|
||||
{
|
||||
temp = dest.Type.IsInteger()
|
||||
temp = dest.Type.IsInteger
|
||||
? GetSpillTemp(dest, intSpillTempRegisters, ref intLocalAsg)
|
||||
: GetSpillTemp(dest, vecSpillTempRegisters, ref vecLocalAsg);
|
||||
|
||||
@ -443,7 +443,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
|
||||
useMask |= 1 << selectedReg;
|
||||
|
||||
return Register(selectedReg, local.Type.ToRegisterType(), local.Type);
|
||||
return Register(selectedReg, local.Type.Register, local.Type);
|
||||
}
|
||||
|
||||
private static int UsesCount(Operand local)
|
||||
|
@ -208,7 +208,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
|
||||
private bool TryAllocateRegWithoutSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount)
|
||||
{
|
||||
RegisterType regType = current.Local.Type.ToRegisterType();
|
||||
RegisterType regType = current.Local.Type.Register;
|
||||
|
||||
Span<int> freePositions = stackalloc int[registersCount];
|
||||
|
||||
@ -318,7 +318,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
|
||||
private void AllocateRegWithSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount)
|
||||
{
|
||||
RegisterType regType = current.Local.Type.ToRegisterType();
|
||||
RegisterType regType = current.Local.Type.Register;
|
||||
|
||||
Span<int> usePositions = stackalloc int[registersCount];
|
||||
Span<int> blockedPositions = stackalloc int[registersCount];
|
||||
@ -847,7 +847,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
// If this is a copy (or copy-like operation), set the copy source interval as well.
|
||||
// This is used for register preferencing later on, which allows the copy to be eliminated
|
||||
// in some cases.
|
||||
if (node.Instruction == Instruction.Copy || node.Instruction == Instruction.ZeroExtend32)
|
||||
if (node.Instruction is Instruction.Copy or Instruction.ZeroExtend32)
|
||||
{
|
||||
Operand source = node.GetSource(0);
|
||||
|
||||
@ -1120,8 +1120,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
|
||||
private static bool IsLocalOrRegister(OperandKind kind)
|
||||
{
|
||||
return kind == OperandKind.LocalVariable ||
|
||||
kind == OperandKind.Register;
|
||||
return kind is OperandKind.LocalVariable or
|
||||
OperandKind.Register;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
|
||||
public int Allocate(OperandType type)
|
||||
{
|
||||
return Allocate(type.GetSizeInBytes());
|
||||
return Allocate(type.ByteSize);
|
||||
}
|
||||
|
||||
public int Allocate(int sizeInBytes)
|
||||
|
@ -385,7 +385,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
ref readonly InstructionInfo info = ref _instTable[(int)X86Instruction.Movd];
|
||||
|
||||
if (source.Type.IsInteger() || source.Kind == OperandKind.Memory)
|
||||
if (source.Type.IsInteger || source.Kind == OperandKind.Memory)
|
||||
{
|
||||
WriteOpCode(dest, default, source, OperandType.None, info.Flags, info.OpRRM, rrm: true);
|
||||
}
|
||||
@ -416,11 +416,11 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
InstructionFlags flags = info.Flags | InstructionFlags.RexW;
|
||||
|
||||
if (source.Type.IsInteger() || source.Kind == OperandKind.Memory)
|
||||
if (source.Type.IsInteger || source.Kind == OperandKind.Memory)
|
||||
{
|
||||
WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRRM, rrm: true);
|
||||
}
|
||||
else if (dest.Type.IsInteger() || dest.Kind == OperandKind.Memory)
|
||||
else if (dest.Type.IsInteger || dest.Kind == OperandKind.Memory)
|
||||
{
|
||||
WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRMR);
|
||||
}
|
||||
@ -1478,7 +1478,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
private static bool Is64Bits(OperandType type)
|
||||
{
|
||||
return type == OperandType.I64 || type == OperandType.FP64;
|
||||
return type is OperandType.I64 or OperandType.FP64;
|
||||
}
|
||||
|
||||
private static bool IsImm8(ulong immediate, OperandType type)
|
||||
|
@ -13,7 +13,6 @@ namespace ARMeilleure.CodeGen.X86
|
||||
private const int BadOp = 0;
|
||||
|
||||
[Flags]
|
||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
||||
private enum InstructionFlags
|
||||
{
|
||||
None = 0,
|
||||
|
@ -1,5 +1,6 @@
|
||||
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using Microsoft.IO;
|
||||
using Ryujinx.Common.Memory;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
@ -8,7 +9,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
class CodeGenContext
|
||||
{
|
||||
private readonly Stream _stream;
|
||||
private readonly RecyclableMemoryStream _stream;
|
||||
private readonly Operand[] _blockLabels;
|
||||
|
||||
public int StreamOffset => (int)_stream.Length;
|
||||
|
@ -175,8 +175,8 @@ namespace ARMeilleure.CodeGen.X86
|
||||
// The only blocks which can have 0 successors are exit blocks.
|
||||
Operation last = block.Operations.Last;
|
||||
|
||||
Debug.Assert(last.Instruction == Instruction.Tailcall ||
|
||||
last.Instruction == Instruction.Return);
|
||||
Debug.Assert(last.Instruction is Instruction.Tailcall or
|
||||
Instruction.Return);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -289,7 +289,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
EnsureSameType(dest, source);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.Popcnt(dest, source, dest.Type);
|
||||
|
||||
@ -303,7 +303,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
EnsureSameType(dest, source);
|
||||
|
||||
Debug.Assert(!dest.Type.IsInteger());
|
||||
Debug.Assert(!dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.WriteInstruction(info.Inst, dest, source);
|
||||
|
||||
@ -315,7 +315,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && !source.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger && !source.Type.IsInteger);
|
||||
|
||||
if (operation.Intrinsic == Intrinsic.X86Cvtsi2si)
|
||||
{
|
||||
@ -349,8 +349,8 @@ namespace ARMeilleure.CodeGen.X86
|
||||
EnsureSameReg(dest, src1);
|
||||
}
|
||||
|
||||
Debug.Assert(!dest.Type.IsInteger());
|
||||
Debug.Assert(!src2.Type.IsInteger() || src2.Kind == OperandKind.Constant);
|
||||
Debug.Assert(!dest.Type.IsInteger);
|
||||
Debug.Assert(!src2.Type.IsInteger || src2.Kind == OperandKind.Constant);
|
||||
|
||||
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2);
|
||||
|
||||
@ -370,7 +370,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
EnsureSameReg(dest, src1);
|
||||
}
|
||||
|
||||
Debug.Assert(!dest.Type.IsInteger() && src2.Type.IsInteger());
|
||||
Debug.Assert(!dest.Type.IsInteger && src2.Type.IsInteger);
|
||||
|
||||
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src2.Type);
|
||||
|
||||
@ -385,7 +385,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
EnsureSameReg(dest, src1);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && src1.Type.IsInteger() && src2.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger && src1.Type.IsInteger && src2.Type.IsInteger);
|
||||
|
||||
context.Assembler.WriteInstruction(info.Inst, dest, src2, dest.Type);
|
||||
|
||||
@ -405,7 +405,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
EnsureSameReg(dest, src1);
|
||||
}
|
||||
|
||||
Debug.Assert(!dest.Type.IsInteger() && src2.Kind == OperandKind.Constant);
|
||||
Debug.Assert(!dest.Type.IsInteger && src2.Kind == OperandKind.Constant);
|
||||
|
||||
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2.AsByte());
|
||||
|
||||
@ -421,7 +421,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
EnsureSameType(dest, src1, src2, src3);
|
||||
|
||||
Debug.Assert(!dest.Type.IsInteger());
|
||||
Debug.Assert(!dest.Type.IsInteger);
|
||||
|
||||
if (info.Inst == X86Instruction.Blendvpd && HardwareCapabilities.SupportsVexEncoding)
|
||||
{
|
||||
@ -461,7 +461,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
EnsureSameReg(dest, src1);
|
||||
}
|
||||
|
||||
Debug.Assert(!dest.Type.IsInteger() && src3.Kind == OperandKind.Constant);
|
||||
Debug.Assert(!dest.Type.IsInteger && src3.Kind == OperandKind.Constant);
|
||||
|
||||
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src3.AsByte());
|
||||
|
||||
@ -478,7 +478,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Debug.Assert(HardwareCapabilities.SupportsVexEncoding);
|
||||
|
||||
Debug.Assert(dest.Kind == OperandKind.Register && src1.Kind == OperandKind.Register && src2.Kind == OperandKind.Register);
|
||||
Debug.Assert(src3.Kind == OperandKind.Register || src3.Kind == OperandKind.Memory);
|
||||
Debug.Assert(src3.Kind is OperandKind.Register or OperandKind.Memory);
|
||||
|
||||
EnsureSameType(dest, src1, src2, src3);
|
||||
Debug.Assert(dest.Type == OperandType.V128);
|
||||
@ -512,7 +512,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand src1 = operation.GetSource(0);
|
||||
Operand src2 = operation.GetSource(1);
|
||||
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
// If Destination and Source 1 Operands are the same, perform a standard add as there are no benefits to using LEA.
|
||||
if (dest.Kind == src1.Kind && dest.Value == src1.Value)
|
||||
@ -567,7 +567,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
ValidateBinOp(dest, src1, src2);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger);
|
||||
|
||||
// Note: GenerateCompareCommon makes the assumption that BitwiseAnd will emit only a single `and`
|
||||
// instruction.
|
||||
@ -582,7 +582,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
ValidateBinOp(dest, src1, src2);
|
||||
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
context.Assembler.Xor(dest, src2, dest.Type);
|
||||
}
|
||||
@ -599,7 +599,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
ValidateUnOp(dest, source);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.Not(dest);
|
||||
}
|
||||
@ -612,7 +612,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
ValidateBinOp(dest, src1, src2);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.Or(dest, src2, dest.Type);
|
||||
}
|
||||
@ -623,7 +623,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||
|
||||
X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition();
|
||||
X86Condition cond = ((Comparison)comp.AsInt32()).X86;
|
||||
|
||||
GenerateCompareCommon(context, operation);
|
||||
|
||||
@ -637,7 +637,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
ValidateUnOp(dest, source);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.Bswap(dest);
|
||||
}
|
||||
@ -661,7 +661,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Debug.Assert(dest.Type == OperandType.I32);
|
||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||
|
||||
X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition();
|
||||
X86Condition cond = ((Comparison)comp.AsInt32()).X86;
|
||||
|
||||
GenerateCompareCommon(context, operation);
|
||||
|
||||
@ -676,7 +676,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
EnsureSameType(src1, src2);
|
||||
|
||||
Debug.Assert(src1.Type.IsInteger());
|
||||
Debug.Assert(src1.Type.IsInteger);
|
||||
|
||||
if (src2.Kind == OperandKind.Constant && src2.Value == 0)
|
||||
{
|
||||
@ -766,7 +766,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
EnsureSameReg(dest, src3);
|
||||
EnsureSameType(dest, src2, src3);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger);
|
||||
Debug.Assert(src1.Type == OperandType.I32);
|
||||
|
||||
context.Assembler.Test(src1, src1, src1.Type);
|
||||
@ -788,13 +788,13 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64);
|
||||
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64);
|
||||
|
||||
if (dest.Type == OperandType.FP32)
|
||||
{
|
||||
Debug.Assert(source.Type.IsInteger() || source.Type == OperandType.FP64);
|
||||
Debug.Assert(source.Type.IsInteger || source.Type == OperandType.FP64);
|
||||
|
||||
if (source.Type.IsInteger())
|
||||
if (source.Type.IsInteger)
|
||||
{
|
||||
context.Assembler.Xorps(dest, dest, dest);
|
||||
context.Assembler.Cvtsi2ss(dest, dest, source, source.Type);
|
||||
@ -808,9 +808,9 @@ namespace ARMeilleure.CodeGen.X86
|
||||
}
|
||||
else /* if (dest.Type == OperandType.FP64) */
|
||||
{
|
||||
Debug.Assert(source.Type.IsInteger() || source.Type == OperandType.FP32);
|
||||
Debug.Assert(source.Type.IsInteger || source.Type == OperandType.FP32);
|
||||
|
||||
if (source.Type.IsInteger())
|
||||
if (source.Type.IsInteger)
|
||||
{
|
||||
context.Assembler.Xorps(dest, dest, dest);
|
||||
context.Assembler.Cvtsi2sd(dest, dest, source, source.Type);
|
||||
@ -831,7 +831,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
EnsureSameType(dest, source);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() || source.Kind != OperandKind.Constant);
|
||||
Debug.Assert(dest.Type.IsInteger || source.Kind != OperandKind.Constant);
|
||||
|
||||
// Moves to the same register are useless.
|
||||
if (dest.Kind == source.Kind && dest.Value == source.Value)
|
||||
@ -845,7 +845,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
// Assemble "mov reg, 0" as "xor reg, reg" as the later is more efficient.
|
||||
context.Assembler.Xor(dest, dest, OperandType.I32);
|
||||
}
|
||||
else if (dest.Type.IsInteger())
|
||||
else if (dest.Type.IsInteger)
|
||||
{
|
||||
context.Assembler.Mov(dest, source, dest.Type);
|
||||
}
|
||||
@ -862,7 +862,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
EnsureSameType(dest, source);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.Bsr(dest, source, dest.Type);
|
||||
|
||||
@ -894,12 +894,12 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand dividend = operation.GetSource(0);
|
||||
Operand divisor = operation.GetSource(1);
|
||||
|
||||
if (!dest.Type.IsInteger())
|
||||
if (!dest.Type.IsInteger)
|
||||
{
|
||||
ValidateBinOp(dest, dividend, divisor);
|
||||
}
|
||||
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
divisor = operation.GetSource(2);
|
||||
|
||||
@ -932,7 +932,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
Operand rdx = Register(X86Register.Rdx);
|
||||
|
||||
Debug.Assert(divisor.Type.IsInteger());
|
||||
Debug.Assert(divisor.Type.IsInteger);
|
||||
|
||||
context.Assembler.Xor(rdx, rdx, OperandType.I32);
|
||||
context.Assembler.Div(divisor);
|
||||
@ -967,7 +967,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand value = operation.Destination;
|
||||
Operand address = Memory(operation.GetSource(0), value.Type);
|
||||
|
||||
Debug.Assert(value.Type.IsInteger());
|
||||
Debug.Assert(value.Type.IsInteger);
|
||||
|
||||
context.Assembler.Movzx16(value, address, value.Type);
|
||||
}
|
||||
@ -977,7 +977,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand value = operation.Destination;
|
||||
Operand address = Memory(operation.GetSource(0), value.Type);
|
||||
|
||||
Debug.Assert(value.Type.IsInteger());
|
||||
Debug.Assert(value.Type.IsInteger);
|
||||
|
||||
context.Assembler.Movzx8(value, address, value.Type);
|
||||
}
|
||||
@ -1000,7 +1000,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
EnsureSameType(dest, src1, src2);
|
||||
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
if (src2.Kind == OperandKind.Constant)
|
||||
{
|
||||
@ -1046,7 +1046,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
ValidateUnOp(dest, source);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.Neg(dest);
|
||||
}
|
||||
@ -1107,7 +1107,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
|
||||
|
||||
context.Assembler.Movsx16(dest, source, dest.Type);
|
||||
}
|
||||
@ -1117,7 +1117,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
|
||||
|
||||
context.Assembler.Movsx32(dest, source, dest.Type);
|
||||
}
|
||||
@ -1127,7 +1127,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
|
||||
|
||||
context.Assembler.Movsx8(dest, source, dest.Type);
|
||||
}
|
||||
@ -1187,7 +1187,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand value = operation.GetSource(1);
|
||||
Operand address = Memory(operation.GetSource(0), value.Type);
|
||||
|
||||
Debug.Assert(value.Type.IsInteger());
|
||||
Debug.Assert(value.Type.IsInteger);
|
||||
|
||||
context.Assembler.Mov16(address, value);
|
||||
}
|
||||
@ -1197,7 +1197,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand value = operation.GetSource(1);
|
||||
Operand address = Memory(operation.GetSource(0), value.Type);
|
||||
|
||||
Debug.Assert(value.Type.IsInteger());
|
||||
Debug.Assert(value.Type.IsInteger);
|
||||
|
||||
context.Assembler.Mov8(address, value);
|
||||
}
|
||||
@ -1210,7 +1210,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
ValidateBinOp(dest, src1, src2);
|
||||
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
context.Assembler.Sub(dest, src2, dest.Type);
|
||||
}
|
||||
@ -1236,7 +1236,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(!dest.Type.IsInteger() && source.Type.IsInteger());
|
||||
Debug.Assert(!dest.Type.IsInteger && source.Type.IsInteger);
|
||||
|
||||
if (source.Type == OperandType.I32)
|
||||
{
|
||||
@ -1259,7 +1259,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
byte index = src2.AsByte();
|
||||
|
||||
Debug.Assert(index < OperandType.V128.GetSizeInBytes() / dest.Type.GetSizeInBytes());
|
||||
Debug.Assert(index < OperandType.V128.ByteSize / dest.Type.ByteSize);
|
||||
|
||||
if (dest.Type == OperandType.I32)
|
||||
{
|
||||
@ -1541,7 +1541,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
Operand dest = operation.Destination;
|
||||
|
||||
Debug.Assert(!dest.Type.IsInteger());
|
||||
Debug.Assert(!dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.Pcmpeqw(dest, dest, dest);
|
||||
}
|
||||
@ -1550,7 +1550,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
Operand dest = operation.Destination;
|
||||
|
||||
Debug.Assert(!dest.Type.IsInteger());
|
||||
Debug.Assert(!dest.Type.IsInteger);
|
||||
|
||||
context.Assembler.Xorps(dest, dest, dest);
|
||||
}
|
||||
@ -1580,7 +1580,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
|
||||
|
||||
context.Assembler.Movzx16(dest, source, OperandType.I32);
|
||||
}
|
||||
@ -1590,7 +1590,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
|
||||
|
||||
// We can eliminate the move if source is already 32-bit and the registers are the same.
|
||||
if (dest.Value == source.Value && source.Type == OperandType.I32)
|
||||
@ -1606,7 +1606,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand dest = operation.Destination;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
|
||||
Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
|
||||
|
||||
context.Assembler.Movzx8(dest, source, OperandType.I32);
|
||||
}
|
||||
@ -1713,17 +1713,17 @@ namespace ARMeilleure.CodeGen.X86
|
||||
EnsureSameReg(dest, src1);
|
||||
EnsureSameType(dest, src1);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && src2.Type == OperandType.I32);
|
||||
Debug.Assert(dest.Type.IsInteger && src2.Type == OperandType.I32);
|
||||
}
|
||||
|
||||
private static void EnsureSameReg(Operand op1, Operand op2)
|
||||
{
|
||||
if (!op1.Type.IsInteger() && HardwareCapabilities.SupportsVexEncoding)
|
||||
if (!op1.Type.IsInteger && HardwareCapabilities.SupportsVexEncoding)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Assert(op1.Kind == OperandKind.Register || op1.Kind == OperandKind.Memory);
|
||||
Debug.Assert(op1.Kind is OperandKind.Register or OperandKind.Memory);
|
||||
Debug.Assert(op1.Kind == op2.Kind);
|
||||
Debug.Assert(op1.Value == op2.Value);
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
PreAllocatorSystemV.InsertCallCopies(block.Operations, node);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.ConvertToFPUI:
|
||||
@ -81,13 +82,15 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
nextNode = PreAllocatorSystemV.InsertLoadArgumentCopy(cctx, ref buffer, block.Operations, preservedArgs, node);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.Negate:
|
||||
if (!node.GetSource(0).Type.IsInteger())
|
||||
if (!node.GetSource(0).Type.IsInteger)
|
||||
{
|
||||
GenerateNegate(block.Operations, node);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.Return:
|
||||
@ -99,6 +102,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
PreAllocatorSystemV.InsertReturnCopy(block.Operations, node);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.Tailcall:
|
||||
@ -110,6 +114,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
PreAllocatorSystemV.InsertTailcallCopies(block.Operations, node);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.VectorInsert8:
|
||||
@ -117,6 +122,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
GenerateVectorInsert8(block.Operations, node);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Instruction.Extended:
|
||||
@ -132,6 +138,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
node.SetSources([Const(stackOffset)]);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -152,7 +159,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
if (src1.Kind == OperandKind.Constant)
|
||||
{
|
||||
if (!src1.Type.IsInteger())
|
||||
if (!src1.Type.IsInteger)
|
||||
{
|
||||
// Handle non-integer types (FP32, FP64 and V128).
|
||||
// For instructions without an immediate operand, we do the following:
|
||||
@ -201,7 +208,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
if (src2.Kind == OperandKind.Constant)
|
||||
{
|
||||
if (!src2.Type.IsInteger())
|
||||
if (!src2.Type.IsInteger)
|
||||
{
|
||||
src2 = AddXmmCopy(nodes, node, src2);
|
||||
|
||||
@ -291,7 +298,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
// - The dividend is always in RDX:RAX.
|
||||
// - The result is always in RAX.
|
||||
// - Additionally it also writes the remainder in RDX.
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
Operand src1 = node.GetSource(0);
|
||||
|
||||
@ -312,9 +319,9 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
case Instruction.Extended:
|
||||
{
|
||||
bool isBlend = node.Intrinsic == Intrinsic.X86Blendvpd ||
|
||||
node.Intrinsic == Intrinsic.X86Blendvps ||
|
||||
node.Intrinsic == Intrinsic.X86Pblendvb;
|
||||
bool isBlend = node.Intrinsic is Intrinsic.X86Blendvpd or
|
||||
Intrinsic.X86Blendvps or
|
||||
Intrinsic.X86Pblendvb;
|
||||
|
||||
// BLENDVPD, BLENDVPS, PBLENDVB last operand is always implied to be XMM0 when VEX is not supported.
|
||||
// SHA256RNDS2 always has an implied XMM0 as a last operand.
|
||||
@ -459,7 +466,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand dest = node.Destination;
|
||||
Operand source = node.GetSource(0);
|
||||
|
||||
Debug.Assert(source.Type.IsInteger(), $"Invalid source type \"{source.Type}\".");
|
||||
Debug.Assert(source.Type.IsInteger, $"Invalid source type \"{source.Type}\".");
|
||||
|
||||
Operation currentNode = node;
|
||||
|
||||
@ -513,8 +520,8 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand dest = node.Destination;
|
||||
Operand source = node.GetSource(0);
|
||||
|
||||
Debug.Assert(dest.Type == OperandType.FP32 ||
|
||||
dest.Type == OperandType.FP64, $"Invalid destination type \"{dest.Type}\".");
|
||||
Debug.Assert(dest.Type is OperandType.FP32 or
|
||||
OperandType.FP64, $"Invalid destination type \"{dest.Type}\".");
|
||||
|
||||
Operation currentNode = node;
|
||||
|
||||
@ -647,10 +654,10 @@ namespace ARMeilleure.CodeGen.X86
|
||||
switch (operation.Instruction)
|
||||
{
|
||||
case Instruction.Add:
|
||||
return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger();
|
||||
return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger;
|
||||
case Instruction.Multiply:
|
||||
case Instruction.Subtract:
|
||||
return !HardwareCapabilities.SupportsVexEncoding || operation.Destination.Type.IsInteger();
|
||||
return !HardwareCapabilities.SupportsVexEncoding || operation.Destination.Type.IsInteger;
|
||||
|
||||
case Instruction.BitwiseAnd:
|
||||
case Instruction.BitwiseExclusiveOr:
|
||||
@ -665,7 +672,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
return true;
|
||||
|
||||
case Instruction.Divide:
|
||||
return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger();
|
||||
return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger;
|
||||
|
||||
case Instruction.VectorInsert:
|
||||
case Instruction.VectorInsert16:
|
||||
@ -761,7 +768,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
Comparison compType = (Comparison)comp.AsInt32();
|
||||
|
||||
return compType == Comparison.Equal || compType == Comparison.NotEqual;
|
||||
return compType is Comparison.Equal or Comparison.NotEqual;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
bool passOnReg;
|
||||
|
||||
if (source.Type.IsInteger())
|
||||
if (source.Type.IsInteger)
|
||||
{
|
||||
passOnReg = intCount < intMax;
|
||||
}
|
||||
@ -62,7 +62,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
if (passOnReg)
|
||||
{
|
||||
Operand argReg = source.Type.IsInteger()
|
||||
Operand argReg = source.Type.IsInteger
|
||||
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
|
||||
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
|
||||
|
||||
@ -80,7 +80,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
InsertConstantRegCopies(nodes, nodes.AddBefore(node, spillOp));
|
||||
|
||||
stackOffset += source.Type.GetSizeInBytes();
|
||||
stackOffset += source.Type.ByteSize;
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,7 +102,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand retReg = dest.Type.IsInteger()
|
||||
Operand retReg = dest.Type.IsInteger
|
||||
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
|
||||
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
|
||||
|
||||
@ -137,7 +137,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
bool passOnReg;
|
||||
|
||||
if (source.Type.IsInteger())
|
||||
if (source.Type.IsInteger)
|
||||
{
|
||||
passOnReg = intCount + 1 < intMax;
|
||||
}
|
||||
@ -160,7 +160,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
if (passOnReg)
|
||||
{
|
||||
Operand argReg = source.Type.IsInteger()
|
||||
Operand argReg = source.Type.IsInteger
|
||||
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
|
||||
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
|
||||
|
||||
@ -210,7 +210,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
OperandType argType = cctx.FuncArgTypes[cIndex];
|
||||
|
||||
if (argType.IsInteger())
|
||||
if (argType.IsInteger)
|
||||
{
|
||||
intCount++;
|
||||
}
|
||||
@ -226,7 +226,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
bool passOnReg;
|
||||
|
||||
if (source.Type.IsInteger())
|
||||
if (source.Type.IsInteger)
|
||||
{
|
||||
passOnReg = intCount < CallingConvention.GetIntArgumentsOnRegsCount();
|
||||
}
|
||||
@ -265,7 +265,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
Operand pArg = Local(dest.Type);
|
||||
|
||||
Operand argReg = dest.Type.IsInteger()
|
||||
Operand argReg = dest.Type.IsInteger
|
||||
? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type)
|
||||
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type);
|
||||
|
||||
@ -320,7 +320,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand retReg = source.Type.IsInteger()
|
||||
Operand retReg = source.Type.IsInteger
|
||||
? Gpr(CallingConvention.GetIntReturnRegister(), source.Type)
|
||||
: Xmm(CallingConvention.GetVecReturnRegister(), source.Type);
|
||||
|
||||
|
@ -40,7 +40,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
if (dest != default && dest.Type == OperandType.V128)
|
||||
{
|
||||
int stackOffset = AllocateOnStack(dest.Type.GetSizeInBytes());
|
||||
int stackOffset = AllocateOnStack(dest.Type.ByteSize);
|
||||
|
||||
arg0Reg = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64);
|
||||
|
||||
@ -76,7 +76,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
Operand stackAddr = Local(OperandType.I64);
|
||||
|
||||
int stackOffset = AllocateOnStack(source.Type.GetSizeInBytes());
|
||||
int stackOffset = AllocateOnStack(source.Type.ByteSize);
|
||||
|
||||
nodes.AddBefore(node, Operation(Instruction.StackAlloc, stackAddr, Const(stackOffset)));
|
||||
|
||||
@ -96,7 +96,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
int argIndex = index + retArgs;
|
||||
|
||||
if (source.Type.IsInteger())
|
||||
if (source.Type.IsInteger)
|
||||
{
|
||||
argReg = Gpr(CallingConvention.GetIntArgumentRegister(argIndex), source.Type);
|
||||
}
|
||||
@ -140,7 +140,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand retReg = dest.Type.IsInteger()
|
||||
Operand retReg = dest.Type.IsInteger
|
||||
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
|
||||
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
|
||||
|
||||
@ -171,7 +171,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
for (int index = 0; index < argsCount; index++)
|
||||
{
|
||||
Operand source = node.GetSource(1 + index);
|
||||
Operand argReg = source.Type.IsInteger()
|
||||
Operand argReg = source.Type.IsInteger
|
||||
? Gpr(CallingConvention.GetIntArgumentRegister(index), source.Type)
|
||||
: Xmm(CallingConvention.GetVecArgumentRegister(index), source.Type);
|
||||
|
||||
@ -219,7 +219,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
Operand argReg, pArg;
|
||||
|
||||
if (dest.Type.IsInteger())
|
||||
if (dest.Type.IsInteger)
|
||||
{
|
||||
argReg = Gpr(CallingConvention.GetIntArgumentRegister(index), dest.Type);
|
||||
pArg = Local(dest.Type);
|
||||
@ -283,7 +283,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Operand source = node.GetSource(0);
|
||||
Operand retReg;
|
||||
|
||||
if (source.Type.IsInteger())
|
||||
if (source.Type.IsInteger)
|
||||
{
|
||||
retReg = Gpr(CallingConvention.GetIntReturnRegister(), source.Type);
|
||||
}
|
||||
|
@ -25,9 +25,9 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
static class ComparisonX86Extensions
|
||||
{
|
||||
public static X86Condition ToX86Condition(this Comparison comp)
|
||||
extension(Comparison comparison)
|
||||
{
|
||||
return comp switch
|
||||
public X86Condition X86 => comparison switch
|
||||
{
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Comparison.Equal => X86Condition.Equal,
|
||||
@ -42,7 +42,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Comparison.LessUI => X86Condition.Below,
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
_ => throw new ArgumentException(null, nameof(comp)),
|
||||
_ => throw new ArgumentException(null, nameof(comparison))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -248,12 +248,12 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
private static bool IsMemoryLoadOrStore(Instruction inst)
|
||||
{
|
||||
return inst == Instruction.Load ||
|
||||
inst == Instruction.Load16 ||
|
||||
inst == Instruction.Load8 ||
|
||||
inst == Instruction.Store ||
|
||||
inst == Instruction.Store16 ||
|
||||
inst == Instruction.Store8;
|
||||
return inst is Instruction.Load or
|
||||
Instruction.Load16 or
|
||||
Instruction.Load8 or
|
||||
Instruction.Store or
|
||||
Instruction.Store16 or
|
||||
Instruction.Store8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
||||
enum X86Register
|
||||
{
|
||||
Invalid = -1,
|
||||
|
@ -22,11 +22,11 @@ namespace ARMeilleure.Decoders
|
||||
|
||||
static class ConditionExtensions
|
||||
{
|
||||
public static Condition Invert(this Condition cond)
|
||||
extension(Condition condition)
|
||||
{
|
||||
// Bit 0 of all conditions is basically a negation bit, so
|
||||
// inverting this bit has the effect of inverting the condition.
|
||||
return (Condition)((int)cond ^ 1);
|
||||
public Condition Inverse => (Condition)((int)condition ^ 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -254,8 +254,8 @@ namespace ARMeilleure.Decoders
|
||||
}
|
||||
|
||||
// Compare and branch instructions are always conditional.
|
||||
if (opCode.Instruction.Name == InstName.Cbz ||
|
||||
opCode.Instruction.Name == InstName.Cbnz)
|
||||
if (opCode.Instruction.Name is InstName.Cbz or
|
||||
InstName.Cbnz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -274,9 +274,10 @@ namespace ARMeilleure.Decoders
|
||||
{
|
||||
if (opCode is OpCodeT32)
|
||||
{
|
||||
return opCode.Instruction.Name != InstName.Tst && opCode.Instruction.Name != InstName.Teq &&
|
||||
opCode.Instruction.Name != InstName.Cmp && opCode.Instruction.Name != InstName.Cmn;
|
||||
return opCode.Instruction.Name is not InstName.Tst and not InstName.Teq and
|
||||
not InstName.Cmp and not InstName.Cmn;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -284,7 +285,7 @@ namespace ARMeilleure.Decoders
|
||||
// register (Rt == 15 or (mask & (1 << 15)) != 0), and cases where there is
|
||||
// a write back to PC (wback == true && Rn == 15), however the later may
|
||||
// be "undefined" depending on the CPU, so compilers should not produce that.
|
||||
if (opCode is IOpCode32Mem || opCode is IOpCode32MemMult)
|
||||
if (opCode is IOpCode32Mem or IOpCode32MemMult)
|
||||
{
|
||||
int rt, rn;
|
||||
|
||||
@ -326,15 +327,15 @@ namespace ARMeilleure.Decoders
|
||||
}
|
||||
|
||||
// Explicit branch instructions.
|
||||
return opCode is IOpCode32BImm ||
|
||||
opCode is IOpCode32BReg;
|
||||
return opCode is IOpCode32BImm or
|
||||
IOpCode32BReg;
|
||||
}
|
||||
|
||||
private static bool IsCall(OpCode opCode)
|
||||
{
|
||||
return opCode.Instruction.Name == InstName.Bl ||
|
||||
opCode.Instruction.Name == InstName.Blr ||
|
||||
opCode.Instruction.Name == InstName.Blx;
|
||||
return opCode.Instruction.Name is InstName.Bl or
|
||||
InstName.Blr or
|
||||
InstName.Blx;
|
||||
}
|
||||
|
||||
private static bool IsException(OpCode opCode)
|
||||
@ -344,9 +345,9 @@ namespace ARMeilleure.Decoders
|
||||
|
||||
private static bool IsTrap(OpCode opCode)
|
||||
{
|
||||
return opCode.Instruction.Name == InstName.Brk ||
|
||||
opCode.Instruction.Name == InstName.Trap ||
|
||||
opCode.Instruction.Name == InstName.Und;
|
||||
return opCode.Instruction.Name is InstName.Brk or
|
||||
InstName.Trap or
|
||||
InstName.Und;
|
||||
}
|
||||
|
||||
public static OpCode DecodeOpCode(IMemoryManager memory, ulong address, ExecutionMode mode)
|
||||
|
@ -162,6 +162,7 @@ namespace ARMeilleure.Decoders
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ namespace ARMeilleure.Decoders
|
||||
Instruction = InstDescriptor.Undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
Q = ((opCode >> 21) & 0x1) != 0;
|
||||
|
||||
RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;
|
||||
|
@ -40,7 +40,7 @@ namespace ARMeilleure.Decoders
|
||||
Rn = (opCode >> 16) & 0xf;
|
||||
|
||||
WBack = Rm != RegisterAlias.Aarch32Pc;
|
||||
RegisterIndex = Rm != RegisterAlias.Aarch32Pc && Rm != RegisterAlias.Aarch32Sp;
|
||||
RegisterIndex = Rm is not RegisterAlias.Aarch32Pc and not RegisterAlias.Aarch32Sp;
|
||||
|
||||
Regs = _regsMap[(opCode >> 8) & 0xf];
|
||||
|
||||
|
@ -45,7 +45,7 @@ namespace ARMeilleure.Decoders
|
||||
Rn = (opCode >> 16) & 0xf;
|
||||
|
||||
WBack = Rm != RegisterAlias.Aarch32Pc;
|
||||
RegisterIndex = Rm != RegisterAlias.Aarch32Pc && Rm != RegisterAlias.Aarch32Sp;
|
||||
RegisterIndex = Rm is not RegisterAlias.Aarch32Pc and not RegisterAlias.Aarch32Sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,8 +28,8 @@ namespace ARMeilleure.Decoders
|
||||
MemOp type = WBack ? (MemOp)((opCode >> 10) & 3) : MemOp.Unsigned;
|
||||
|
||||
PostIdx = type == MemOp.PostIndexed;
|
||||
Unscaled = type == MemOp.Unscaled ||
|
||||
type == MemOp.Unprivileged;
|
||||
Unscaled = type is MemOp.Unscaled or
|
||||
MemOp.Unprivileged;
|
||||
|
||||
// Unscaled and Unprivileged doesn't write back,
|
||||
// but they do use the 9-bits Signed Immediate.
|
||||
|
@ -1381,6 +1381,7 @@ namespace ARMeilleure.Decoders
|
||||
{
|
||||
thumbEncoding = $"1110{thumbEncoding.AsSpan(4)}";
|
||||
}
|
||||
|
||||
SetT32(thumbEncoding, name, emitter, makeOpT32);
|
||||
}
|
||||
|
||||
@ -1409,6 +1410,7 @@ namespace ARMeilleure.Decoders
|
||||
{
|
||||
throw new ArgumentException("Invalid ASIMD instruction encoding");
|
||||
}
|
||||
|
||||
SetT32(thumbEncoding, name, emitter, makeOpT32);
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ namespace ARMeilleure.Diagnostics
|
||||
{
|
||||
class IRDumper
|
||||
{
|
||||
private const string Indentation = " ";
|
||||
private const char Indentation = ' ';
|
||||
|
||||
private int _indentLevel;
|
||||
|
||||
@ -30,14 +30,11 @@ namespace ARMeilleure.Diagnostics
|
||||
|
||||
private void Indent()
|
||||
{
|
||||
_builder.EnsureCapacity(_builder.Capacity + _indentLevel * Indentation.Length);
|
||||
if (_indentLevel == 0)
|
||||
return;
|
||||
|
||||
for (int index = 0; index < _indentLevel; index++)
|
||||
{
|
||||
#pragma warning disable CA1834 // Use StringBuilder.Append(char) for single character strings
|
||||
_builder.Append(Indentation);
|
||||
#pragma warning restore CA1834
|
||||
}
|
||||
_builder.EnsureCapacity(_builder.Capacity + _indentLevel);
|
||||
_builder.Append(Indentation, _indentLevel);
|
||||
}
|
||||
|
||||
private void IncreaseIndentation()
|
||||
@ -235,8 +232,8 @@ namespace ARMeilleure.Diagnostics
|
||||
{
|
||||
_builder.Append('.').Append(operation.Intrinsic);
|
||||
}
|
||||
else if (operation.Instruction == Instruction.BranchIf ||
|
||||
operation.Instruction == Instruction.Compare)
|
||||
else if (operation.Instruction is Instruction.BranchIf or
|
||||
Instruction.Compare)
|
||||
{
|
||||
comparison = true;
|
||||
}
|
||||
@ -262,6 +259,7 @@ namespace ARMeilleure.Diagnostics
|
||||
DumpOperand(source);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -899,6 +899,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
n = context.ShiftLeft(n, Const(shift));
|
||||
}
|
||||
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
if (shift == 32)
|
||||
@ -909,6 +910,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
n = context.ShiftRightSI(n, Const(shift));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -266,7 +266,7 @@ namespace ARMeilleure.Instructions
|
||||
}
|
||||
}
|
||||
|
||||
private static Exception InvalidOpCodeType(OpCode opCode)
|
||||
private static InvalidOperationException InvalidOpCodeType(OpCode opCode)
|
||||
{
|
||||
return new InvalidOperationException($"Invalid OpCode type \"{opCode?.GetType().Name ?? "null"}\".");
|
||||
}
|
||||
@ -318,6 +318,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
m = GetRrxC(context, m, setCarry);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static Operand EmitCrc32(ArmEmitterContext context, Operand crc, Operand value, int size, bool castagnoli)
|
||||
{
|
||||
Debug.Assert(crc.Type.IsInteger() && value.Type.IsInteger());
|
||||
Debug.Assert(size >= 0 && size < 4);
|
||||
Debug.Assert(crc.Type.IsInteger && value.Type.IsInteger);
|
||||
Debug.Assert(size is >= 0 and < 4);
|
||||
Debug.Assert((size < 3) || (value.Type == OperandType.I64));
|
||||
|
||||
if (castagnoli && Optimizations.UseSse42)
|
||||
|
@ -90,6 +90,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
value = context.ConvertI64ToI32(value);
|
||||
}
|
||||
|
||||
Operand reg = Register(GetRegisterAlias(context.Mode, regIndex), RegisterType.Integer, OperandType.I32);
|
||||
|
||||
context.Copy(reg, value);
|
||||
|
@ -140,7 +140,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
if (pair)
|
||||
{
|
||||
Debug.Assert(op.Size == 2 || op.Size == 3, "Invalid size for pairwise store.");
|
||||
Debug.Assert(op.Size is 2 or 3, "Invalid size for pairwise store.");
|
||||
|
||||
Operand t2 = GetIntOrZR(context, op.Rt2);
|
||||
|
||||
|
@ -42,6 +42,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
context.Store(exValuePtr, Const(0UL));
|
||||
}
|
||||
|
||||
if (size < 4)
|
||||
{
|
||||
context.Store(context.Add(exValuePtr, Const(exValuePtr.Type, 8L)), Const(0UL));
|
||||
|
@ -59,7 +59,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
Operand value = GetInt(context, rt);
|
||||
|
||||
if (ext == Extension.Sx32 || ext == Extension.Sx64)
|
||||
if (ext is Extension.Sx32 or Extension.Sx64)
|
||||
{
|
||||
OperandType destType = ext == Extension.Sx64 ? OperandType.I64 : OperandType.I32;
|
||||
|
||||
@ -123,9 +123,9 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
private static bool IsSimd(ArmEmitterContext context)
|
||||
{
|
||||
return context.CurrOp is IOpCodeSimd &&
|
||||
!(context.CurrOp is OpCodeSimdMemMs ||
|
||||
context.CurrOp is OpCodeSimdMemSs);
|
||||
return context.CurrOp is IOpCodeSimd and
|
||||
not (OpCodeSimdMemMs or
|
||||
OpCodeSimdMemSs);
|
||||
}
|
||||
|
||||
public static Operand EmitReadInt(ArmEmitterContext context, Operand address, int size)
|
||||
@ -157,7 +157,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.Copy(temp, value);
|
||||
|
||||
if (!context.Memory.Type.IsHostMappedOrTracked())
|
||||
if (!context.Memory.Type.IsHostMappedOrTracked)
|
||||
{
|
||||
context.Branch(lblEnd);
|
||||
|
||||
@ -198,7 +198,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
SetInt(context, rt, value);
|
||||
|
||||
if (!context.Memory.Type.IsHostMappedOrTracked())
|
||||
if (!context.Memory.Type.IsHostMappedOrTracked)
|
||||
{
|
||||
context.Branch(lblEnd);
|
||||
|
||||
@ -265,7 +265,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.Copy(GetVec(rt), value);
|
||||
|
||||
if (!context.Memory.Type.IsHostMappedOrTracked())
|
||||
if (!context.Memory.Type.IsHostMappedOrTracked)
|
||||
{
|
||||
context.Branch(lblEnd);
|
||||
|
||||
@ -312,7 +312,7 @@ namespace ARMeilleure.Instructions
|
||||
break;
|
||||
}
|
||||
|
||||
if (!context.Memory.Type.IsHostMappedOrTracked())
|
||||
if (!context.Memory.Type.IsHostMappedOrTracked)
|
||||
{
|
||||
context.Branch(lblEnd);
|
||||
|
||||
@ -385,7 +385,7 @@ namespace ARMeilleure.Instructions
|
||||
break;
|
||||
}
|
||||
|
||||
if (!context.Memory.Type.IsHostMappedOrTracked())
|
||||
if (!context.Memory.Type.IsHostMappedOrTracked)
|
||||
{
|
||||
context.Branch(lblEnd);
|
||||
|
||||
@ -399,11 +399,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static Operand EmitPtPointerLoad(ArmEmitterContext context, Operand address, Operand lblSlowPath, bool write, int size)
|
||||
{
|
||||
if (context.Memory.Type.IsHostMapped())
|
||||
if (context.Memory.Type.IsHostMapped)
|
||||
{
|
||||
return EmitHostMappedPointer(context, address);
|
||||
}
|
||||
else if (context.Memory.Type.IsHostTracked())
|
||||
else if (context.Memory.Type.IsHostTracked)
|
||||
{
|
||||
if (address.Type == OperandType.I32)
|
||||
{
|
||||
@ -717,7 +717,7 @@ namespace ARMeilleure.Instructions
|
||||
};
|
||||
}
|
||||
|
||||
private static Exception InvalidOpCodeType(OpCode opCode)
|
||||
private static InvalidOperationException InvalidOpCodeType(OpCode opCode)
|
||||
{
|
||||
return new InvalidOperationException($"Invalid OpCode type \"{opCode?.GetType().Name ?? "null"}\".");
|
||||
}
|
||||
@ -768,6 +768,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
m = InstEmitAluHelper.GetRrxC(context, m, setCarry);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ namespace ARMeilleure.Instructions
|
||||
public static void Umsubl(ArmEmitterContext context) => EmitMull(context, MullFlags.Subtract);
|
||||
|
||||
[Flags]
|
||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
||||
private enum MullFlags
|
||||
{
|
||||
Subtract = 0,
|
||||
|
@ -5266,7 +5266,7 @@ namespace ARMeilleure.Instructions
|
||||
private static Operand EmitSse2Sll_128(ArmEmitterContext context, Operand op, int shift)
|
||||
{
|
||||
// The upper part of op is assumed to be zero.
|
||||
Debug.Assert(shift >= 0 && shift < 64);
|
||||
Debug.Assert(shift is >= 0 and < 64);
|
||||
|
||||
if (shift == 0)
|
||||
{
|
||||
|
@ -231,10 +231,12 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
result |= (long)((i >= end || i < start) ? 0x80 : b++) << (i * 8);
|
||||
}
|
||||
|
||||
for (int i = 8; i < 16; i++)
|
||||
{
|
||||
result2 |= (long)((i >= end || i < start) ? 0x80 : b++) << ((i - 8) * 8);
|
||||
}
|
||||
|
||||
return (result2, result);
|
||||
}
|
||||
|
||||
@ -261,6 +263,7 @@ namespace ARMeilleure.Instructions
|
||||
nMaskHigh = nMaskLow + 0x0808080808080808L;
|
||||
mMaskHigh = mMaskLow + 0x0808080808080808L;
|
||||
}
|
||||
|
||||
nMask = X86GetElements(context, nMaskHigh, nMaskLow);
|
||||
mMask = X86GetElements(context, mMaskHigh, mMaskLow);
|
||||
Operand nPart = context.AddIntrinsic(Intrinsic.X86Pshufb, n, nMask);
|
||||
@ -285,6 +288,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
extract = EmitVectorExtractZx32(context, op.Qn, op.In + byteOff, op.Size);
|
||||
}
|
||||
|
||||
byteOff++;
|
||||
|
||||
res = EmitVectorInsert(context, res, extract, op.Id + index, op.Size);
|
||||
@ -1304,6 +1308,7 @@ namespace ARMeilleure.Instructions
|
||||
case 2:
|
||||
return context.AddIntrinsic(Intrinsic.X86Shufps, op1, op1, Const(1 | (0 << 2) | (3 << 4) | (2 << 6)));
|
||||
}
|
||||
|
||||
break;
|
||||
case 2:
|
||||
// Rev32
|
||||
@ -1316,6 +1321,7 @@ namespace ARMeilleure.Instructions
|
||||
mask = X86GetElements(context, 0x0d0c0f0e_09080b0aL, 0x05040706_01000302L);
|
||||
return context.AddIntrinsic(Intrinsic.X86Pshufb, op1, mask);
|
||||
}
|
||||
|
||||
break;
|
||||
case 1:
|
||||
// Rev16
|
||||
@ -1341,6 +1347,7 @@ namespace ARMeilleure.Instructions
|
||||
case 3:
|
||||
return context.ByteSwap(op1);
|
||||
}
|
||||
|
||||
break;
|
||||
case 1:
|
||||
switch (op.Size)
|
||||
@ -1355,6 +1362,7 @@ namespace ARMeilleure.Instructions
|
||||
context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op1, Const(0x0000ffff00000000ul)), Const(16)),
|
||||
context.ShiftLeft(context.BitwiseAnd(op1, Const(0x00000000ffff0000ul)), Const(16))));
|
||||
}
|
||||
|
||||
break;
|
||||
case 2:
|
||||
// Swap upper and lower halves.
|
||||
|
@ -1119,7 +1119,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, int size, bool signed)
|
||||
{
|
||||
Debug.Assert(value.Type == OperandType.I32 || value.Type == OperandType.I64);
|
||||
Debug.Assert(value.Type is OperandType.I32 or OperandType.I64);
|
||||
Debug.Assert((uint)size < 2);
|
||||
|
||||
OperandType type = size == 0 ? OperandType.FP32 : OperandType.FP64;
|
||||
@ -1136,7 +1136,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
private static Operand EmitScalarFcvts(ArmEmitterContext context, Operand value, int fBits)
|
||||
{
|
||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
|
||||
Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64);
|
||||
|
||||
value = EmitF2iFBitsMul(context, value, fBits);
|
||||
|
||||
@ -1160,7 +1160,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
private static Operand EmitScalarFcvtu(ArmEmitterContext context, Operand value, int fBits)
|
||||
{
|
||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
|
||||
Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64);
|
||||
|
||||
value = EmitF2iFBitsMul(context, value, fBits);
|
||||
|
||||
@ -1184,7 +1184,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
private static Operand EmitF2iFBitsMul(ArmEmitterContext context, Operand value, int fBits)
|
||||
{
|
||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
|
||||
Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64);
|
||||
|
||||
if (fBits == 0)
|
||||
{
|
||||
@ -1203,7 +1203,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
private static Operand EmitI2fFBitsMul(ArmEmitterContext context, Operand value, int fBits)
|
||||
{
|
||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.FP64);
|
||||
Debug.Assert(value.Type is OperandType.FP32 or OperandType.FP64);
|
||||
|
||||
if (fBits == 0)
|
||||
{
|
||||
|
@ -385,6 +385,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Cvtsd2ss, context.VectorZero(), res);
|
||||
}
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Vcvtps2ph, res, Const(X86GetRoundControl(FPRoundingMode.ToNearest)));
|
||||
res = context.VectorExtract16(res, 0);
|
||||
InsertScalar16(context, op.Vd, op.T, res);
|
||||
@ -397,6 +398,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Cvtss2sd, context.VectorZero(), res);
|
||||
}
|
||||
|
||||
res = context.VectorExtract(op.Size == 1 ? OperandType.I64 : OperandType.I32, res, 0);
|
||||
InsertScalar(context, op.Vd, res);
|
||||
}
|
||||
@ -635,7 +637,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, OperandType type, bool signed)
|
||||
{
|
||||
Debug.Assert(value.Type == OperandType.I32 || value.Type == OperandType.I64);
|
||||
Debug.Assert(value.Type is OperandType.I32 or OperandType.I64);
|
||||
|
||||
if (signed)
|
||||
{
|
||||
|
@ -363,7 +363,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static Operand EmitCountSetBits8(ArmEmitterContext context, Operand op) // "size" is 8 (SIMD&FP Inst.).
|
||||
{
|
||||
Debug.Assert(op.Type == OperandType.I32 || op.Type == OperandType.I64);
|
||||
Debug.Assert(op.Type is OperandType.I32 or OperandType.I64);
|
||||
|
||||
Operand op0 = context.Subtract(op, context.BitwiseAnd(context.ShiftRightUI(op, Const(1)), Const(op.Type, 0x55L)));
|
||||
|
||||
@ -489,7 +489,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static Operand EmitRoundByRMode(ArmEmitterContext context, Operand op)
|
||||
{
|
||||
Debug.Assert(op.Type == OperandType.FP32 || op.Type == OperandType.FP64);
|
||||
Debug.Assert(op.Type is OperandType.FP32 or OperandType.FP64);
|
||||
|
||||
Operand lbl1 = Label();
|
||||
Operand lbl2 = Label();
|
||||
@ -1676,7 +1676,7 @@ namespace ARMeilleure.Instructions
|
||||
int eSize = 8 << size;
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||
|
||||
Operand lbl1 = Label();
|
||||
Operand lblEnd = Label();
|
||||
@ -1709,7 +1709,7 @@ namespace ARMeilleure.Instructions
|
||||
int eSize = 8 << size;
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||
|
||||
Operand lblEnd = Label();
|
||||
|
||||
@ -1735,7 +1735,7 @@ namespace ARMeilleure.Instructions
|
||||
int eSizeDst = 8 << sizeDst;
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32);
|
||||
Debug.Assert(eSizeDst is 8 or 16 or 32);
|
||||
|
||||
Operand lbl1 = Label();
|
||||
Operand lblEnd = Label();
|
||||
@ -1768,7 +1768,7 @@ namespace ARMeilleure.Instructions
|
||||
int eSizeDst = 8 << sizeDst;
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32);
|
||||
Debug.Assert(eSizeDst is 8 or 16 or 32);
|
||||
|
||||
Operand lblEnd = Label();
|
||||
|
||||
|
@ -31,7 +31,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
Debug.Assert(type != OperandType.V128);
|
||||
|
||||
if (type == OperandType.FP64 || type == OperandType.I64)
|
||||
if (type is OperandType.FP64 or OperandType.I64)
|
||||
{
|
||||
// From dreg.
|
||||
return context.VectorExtract(type, GetVecA32(reg >> 1), reg & 1);
|
||||
@ -48,7 +48,7 @@ namespace ARMeilleure.Instructions
|
||||
Debug.Assert(value.Type != OperandType.V128);
|
||||
|
||||
Operand vec, insert;
|
||||
if (value.Type == OperandType.FP64 || value.Type == OperandType.I64)
|
||||
if (value.Type is OperandType.FP64 or OperandType.I64)
|
||||
{
|
||||
// From dreg.
|
||||
vec = GetVecA32(reg >> 1);
|
||||
@ -71,7 +71,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void InsertScalar16(ArmEmitterContext context, int reg, bool top, Operand value)
|
||||
{
|
||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.I32);
|
||||
Debug.Assert(value.Type is OperandType.FP32 or OperandType.I32);
|
||||
|
||||
Operand vec, insert;
|
||||
vec = GetVecA32(reg >> 2);
|
||||
@ -880,6 +880,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
res = EmitMoveDoubleWordToSide(context, res, side, op.Vd);
|
||||
}
|
||||
|
||||
res = EmitDoubleWordInsert(context, d, res, op.Vd);
|
||||
}
|
||||
|
||||
|
@ -146,6 +146,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
res = EmitMoveDoubleWordToSide(context, res, side, op.Vd);
|
||||
}
|
||||
|
||||
res = EmitDoubleWordInsert(context, d, res, op.Vd);
|
||||
}
|
||||
|
||||
|
@ -268,6 +268,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
m = context.BitwiseNot(m);
|
||||
}
|
||||
|
||||
return context.BitwiseExclusiveOr(
|
||||
context.BitwiseAnd(m,
|
||||
context.BitwiseExclusiveOr(d, n)), d);
|
||||
|
@ -110,6 +110,7 @@ namespace ARMeilleure.Instructions
|
||||
EmitStoreSimd(context, address, d >> 1, index, op.Size);
|
||||
}
|
||||
}
|
||||
|
||||
offset += eBytes;
|
||||
d += op.Increment;
|
||||
}
|
||||
|
@ -1634,7 +1634,7 @@ namespace ARMeilleure.Instructions
|
||||
int eSize = 8 << size;
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||
|
||||
Operand res = context.AllocateLocal(OperandType.I64);
|
||||
|
||||
@ -1657,7 +1657,7 @@ namespace ARMeilleure.Instructions
|
||||
int eSize = 8 << size;
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||
|
||||
Operand lblEnd = Label();
|
||||
|
||||
@ -1732,7 +1732,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(shiftLsB.Type == OperandType.I32);
|
||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||
|
||||
Operand lbl1 = Label();
|
||||
Operand lblEnd = Label();
|
||||
@ -1769,7 +1769,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
Debug.Assert(shiftLsB.Type == OperandType.I32);
|
||||
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||
Debug.Assert(eSize is 8 or 16 or 32 or 64);
|
||||
|
||||
Operand lbl1 = Label();
|
||||
Operand lbl2 = Label();
|
||||
@ -1813,6 +1813,7 @@ namespace ARMeilleure.Instructions
|
||||
? EmitSignedSrcSatQ(context, shl, size, signedDst: true)
|
||||
: EmitUnsignedSrcSatQ(context, shl, size, signedDst: false));
|
||||
}
|
||||
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
@ -1850,6 +1851,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
context.Copy(res, sar);
|
||||
}
|
||||
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
@ -1906,6 +1908,7 @@ namespace ARMeilleure.Instructions
|
||||
Operand right = context.BitwiseOr(shr, context.ShiftRightUI(oneShl63UL, context.Subtract(shift, one)));
|
||||
context.Copy(res, context.ConditionalSelect(isEqual, oneUL, right));
|
||||
}
|
||||
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
|
@ -69,13 +69,13 @@ namespace ARMeilleure.Instructions
|
||||
[UnmanagedCallersOnly]
|
||||
public static ulong GetCtrEl0()
|
||||
{
|
||||
return GetContext().CtrEl0;
|
||||
return ExecutionContext.CtrEl0;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static ulong GetDczidEl0()
|
||||
{
|
||||
return GetContext().DczidEl0;
|
||||
return ExecutionContext.DczidEl0;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
|
@ -1,692 +0,0 @@
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static class SoftFallback
|
||||
{
|
||||
#region "ShrImm64"
|
||||
[UnmanagedCallersOnly]
|
||||
public static long SignedShrImm64(long value, long roundConst, int shift)
|
||||
{
|
||||
if (roundConst == 0L)
|
||||
{
|
||||
if (shift <= 63)
|
||||
{
|
||||
return value >> shift;
|
||||
}
|
||||
else /* if (shift == 64) */
|
||||
{
|
||||
if (value < 0L)
|
||||
{
|
||||
return -1L;
|
||||
}
|
||||
else /* if (value >= 0L) */
|
||||
{
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* if (roundConst == 1L << (shift - 1)) */
|
||||
{
|
||||
if (shift <= 63)
|
||||
{
|
||||
long add = value + roundConst;
|
||||
|
||||
if ((~value & (value ^ add)) < 0L)
|
||||
{
|
||||
return (long)((ulong)add >> shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
return add >> shift;
|
||||
}
|
||||
}
|
||||
else /* if (shift == 64) */
|
||||
{
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift)
|
||||
{
|
||||
if (roundConst == 0L)
|
||||
{
|
||||
if (shift <= 63)
|
||||
{
|
||||
return value >> shift;
|
||||
}
|
||||
else /* if (shift == 64) */
|
||||
{
|
||||
return 0UL;
|
||||
}
|
||||
}
|
||||
else /* if (roundConst == 1L << (shift - 1)) */
|
||||
{
|
||||
ulong add = value + (ulong)roundConst;
|
||||
|
||||
if ((add < value) && (add < (ulong)roundConst))
|
||||
{
|
||||
if (shift <= 63)
|
||||
{
|
||||
return (add >> shift) | (0x8000000000000000UL >> (shift - 1));
|
||||
}
|
||||
else /* if (shift == 64) */
|
||||
{
|
||||
return 1UL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shift <= 63)
|
||||
{
|
||||
return add >> shift;
|
||||
}
|
||||
else /* if (shift == 64) */
|
||||
{
|
||||
return 0UL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region "Saturation"
|
||||
[UnmanagedCallersOnly]
|
||||
public static int SatF32ToS32(float value)
|
||||
{
|
||||
if (float.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= int.MaxValue ? int.MaxValue :
|
||||
value <= int.MinValue ? int.MinValue : (int)value;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static long SatF32ToS64(float value)
|
||||
{
|
||||
if (float.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= long.MaxValue ? long.MaxValue :
|
||||
value <= long.MinValue ? long.MinValue : (long)value;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint SatF32ToU32(float value)
|
||||
{
|
||||
if (float.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= uint.MaxValue ? uint.MaxValue :
|
||||
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static ulong SatF32ToU64(float value)
|
||||
{
|
||||
if (float.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= ulong.MaxValue ? ulong.MaxValue :
|
||||
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static int SatF64ToS32(double value)
|
||||
{
|
||||
if (double.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= int.MaxValue ? int.MaxValue :
|
||||
value <= int.MinValue ? int.MinValue : (int)value;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static long SatF64ToS64(double value)
|
||||
{
|
||||
if (double.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= long.MaxValue ? long.MaxValue :
|
||||
value <= long.MinValue ? long.MinValue : (long)value;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint SatF64ToU32(double value)
|
||||
{
|
||||
if (double.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= uint.MaxValue ? uint.MaxValue :
|
||||
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static ulong SatF64ToU64(double value)
|
||||
{
|
||||
if (double.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= ulong.MaxValue ? ulong.MaxValue :
|
||||
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region "Count"
|
||||
[UnmanagedCallersOnly]
|
||||
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
||||
{
|
||||
value ^= value >> 1;
|
||||
|
||||
int highBit = size - 2;
|
||||
|
||||
for (int bit = highBit; bit >= 0; bit--)
|
||||
{
|
||||
if (((int)(value >> bit) & 0b1) != 0)
|
||||
{
|
||||
return (ulong)(highBit - bit);
|
||||
}
|
||||
}
|
||||
|
||||
return (ulong)(size - 1);
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> ClzNibbleTbl => [4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
||||
{
|
||||
if (value == 0ul)
|
||||
{
|
||||
return (ulong)size;
|
||||
}
|
||||
|
||||
int nibbleIdx = size;
|
||||
int preCount, count = 0;
|
||||
|
||||
do
|
||||
{
|
||||
nibbleIdx -= 4;
|
||||
preCount = ClzNibbleTbl[(int)(value >> nibbleIdx) & 0b1111];
|
||||
count += preCount;
|
||||
}
|
||||
while (preCount == 4);
|
||||
|
||||
return (ulong)count;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region "Table"
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
|
||||
{
|
||||
return TblOrTbx(default, vector, bytes, tb0);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1)
|
||||
{
|
||||
return TblOrTbx(default, vector, bytes, tb0, tb1);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
|
||||
{
|
||||
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
|
||||
{
|
||||
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0)
|
||||
{
|
||||
return TblOrTbx(dest, vector, bytes, tb0);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1)
|
||||
{
|
||||
return TblOrTbx(dest, vector, bytes, tb0, tb1);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
|
||||
{
|
||||
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
|
||||
{
|
||||
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3);
|
||||
}
|
||||
|
||||
private static V128 TblOrTbx(V128 dest, V128 vector, int bytes, params ReadOnlySpan<V128> tb)
|
||||
{
|
||||
byte[] res = new byte[16];
|
||||
|
||||
if (dest != default)
|
||||
{
|
||||
Buffer.BlockCopy(dest.ToArray(), 0, res, 0, bytes);
|
||||
}
|
||||
|
||||
byte[] table = new byte[tb.Length * 16];
|
||||
|
||||
for (byte index = 0; index < tb.Length; index++)
|
||||
{
|
||||
Buffer.BlockCopy(tb[index].ToArray(), 0, table, index * 16, 16);
|
||||
}
|
||||
|
||||
byte[] v = vector.ToArray();
|
||||
|
||||
for (byte index = 0; index < bytes; index++)
|
||||
{
|
||||
byte tblIndex = v[index];
|
||||
|
||||
if (tblIndex < table.Length)
|
||||
{
|
||||
res[index] = table[tblIndex];
|
||||
}
|
||||
}
|
||||
|
||||
return new V128(res);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region "Crc32"
|
||||
private const uint Crc32RevPoly = 0xedb88320;
|
||||
private const uint Crc32cRevPoly = 0x82f63b78;
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
|
||||
|
||||
private static uint Crc32h(uint crc, uint poly, ushort val)
|
||||
{
|
||||
crc = Crc32(crc, poly, (byte)(val >> 0));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 8));
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
private static uint Crc32w(uint crc, uint poly, uint val)
|
||||
{
|
||||
crc = Crc32(crc, poly, (byte)(val >> 0));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 8));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 16));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 24));
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
private static uint Crc32x(uint crc, uint poly, ulong val)
|
||||
{
|
||||
crc = Crc32(crc, poly, (byte)(val >> 0));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 8));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 16));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 24));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 32));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 40));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 48));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 56));
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
private static uint Crc32(uint crc, uint poly, byte val)
|
||||
{
|
||||
crc ^= val;
|
||||
|
||||
for (int bit = 7; bit >= 0; bit--)
|
||||
{
|
||||
uint mask = (uint)(-(int)(crc & 1));
|
||||
|
||||
crc = (crc >> 1) ^ (poly & mask);
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region "Aes"
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Decrypt(V128 value, V128 roundKey)
|
||||
{
|
||||
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Encrypt(V128 value, V128 roundKey)
|
||||
{
|
||||
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 InverseMixColumns(V128 value)
|
||||
{
|
||||
return CryptoHelper.AesInvMixColumns(value);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 MixColumns(V128 value)
|
||||
{
|
||||
return CryptoHelper.AesMixColumns(value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region "Sha1"
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
|
||||
{
|
||||
for (int e = 0; e <= 3; e++)
|
||||
{
|
||||
uint t = ShaChoose(hash_abcd.Extract<uint>(1),
|
||||
hash_abcd.Extract<uint>(2),
|
||||
hash_abcd.Extract<uint>(3));
|
||||
|
||||
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
|
||||
|
||||
t = Rol(hash_abcd.Extract<uint>(1), 30);
|
||||
|
||||
hash_abcd.Insert(1, t);
|
||||
|
||||
Rol32_160(ref hash_e, ref hash_abcd);
|
||||
}
|
||||
|
||||
return hash_abcd;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint FixedRotate(uint hash_e)
|
||||
{
|
||||
return hash_e.Rol(30);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk)
|
||||
{
|
||||
for (int e = 0; e <= 3; e++)
|
||||
{
|
||||
uint t = ShaMajority(hash_abcd.Extract<uint>(1),
|
||||
hash_abcd.Extract<uint>(2),
|
||||
hash_abcd.Extract<uint>(3));
|
||||
|
||||
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
|
||||
|
||||
t = Rol(hash_abcd.Extract<uint>(1), 30);
|
||||
|
||||
hash_abcd.Insert(1, t);
|
||||
|
||||
Rol32_160(ref hash_e, ref hash_abcd);
|
||||
}
|
||||
|
||||
return hash_abcd;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk)
|
||||
{
|
||||
for (int e = 0; e <= 3; e++)
|
||||
{
|
||||
uint t = ShaParity(hash_abcd.Extract<uint>(1),
|
||||
hash_abcd.Extract<uint>(2),
|
||||
hash_abcd.Extract<uint>(3));
|
||||
|
||||
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
|
||||
|
||||
t = Rol(hash_abcd.Extract<uint>(1), 30);
|
||||
|
||||
hash_abcd.Insert(1, t);
|
||||
|
||||
Rol32_160(ref hash_e, ref hash_abcd);
|
||||
}
|
||||
|
||||
return hash_abcd;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11)
|
||||
{
|
||||
ulong t2 = w4_7.Extract<ulong>(0);
|
||||
ulong t1 = w0_3.Extract<ulong>(1);
|
||||
|
||||
V128 result = new(t1, t2);
|
||||
|
||||
return result ^ (w0_3 ^ w8_11);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15)
|
||||
{
|
||||
V128 t = tw0_3 ^ (w12_15 >> 32);
|
||||
|
||||
uint tE0 = t.Extract<uint>(0);
|
||||
uint tE1 = t.Extract<uint>(1);
|
||||
uint tE2 = t.Extract<uint>(2);
|
||||
uint tE3 = t.Extract<uint>(3);
|
||||
|
||||
return new V128(tE0.Rol(1), tE1.Rol(1), tE2.Rol(1), tE3.Rol(1) ^ tE0.Rol(2));
|
||||
}
|
||||
|
||||
private static void Rol32_160(ref uint y, ref V128 x)
|
||||
{
|
||||
uint xE3 = x.Extract<uint>(3);
|
||||
|
||||
x <<= 32;
|
||||
x.Insert(0, y);
|
||||
|
||||
y = xE3;
|
||||
}
|
||||
|
||||
private static uint ShaChoose(uint x, uint y, uint z)
|
||||
{
|
||||
return ((y ^ z) & x) ^ z;
|
||||
}
|
||||
|
||||
private static uint ShaMajority(uint x, uint y, uint z)
|
||||
{
|
||||
return (x & y) | ((x | y) & z);
|
||||
}
|
||||
|
||||
private static uint ShaParity(uint x, uint y, uint z)
|
||||
{
|
||||
return x ^ y ^ z;
|
||||
}
|
||||
|
||||
private static uint Rol(this uint value, int count)
|
||||
{
|
||||
return (value << count) | (value >> (32 - count));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region "Sha256"
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
||||
{
|
||||
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
||||
{
|
||||
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
|
||||
{
|
||||
V128 result = new();
|
||||
|
||||
for (int e = 0; e <= 3; e++)
|
||||
{
|
||||
uint elt = (e <= 2 ? w0_3 : w4_7).Extract<uint>(e <= 2 ? e + 1 : 0);
|
||||
|
||||
elt = elt.Ror(7) ^ elt.Ror(18) ^ elt.Lsr(3);
|
||||
|
||||
elt += w0_3.Extract<uint>(e);
|
||||
|
||||
result.Insert(e, elt);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
|
||||
{
|
||||
V128 result = new();
|
||||
|
||||
ulong t1 = w12_15.Extract<ulong>(1);
|
||||
|
||||
for (int e = 0; e <= 1; e++)
|
||||
{
|
||||
uint elt = t1.ULongPart(e);
|
||||
|
||||
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
|
||||
|
||||
elt += w0_3.Extract<uint>(e) + w8_11.Extract<uint>(e + 1);
|
||||
|
||||
result.Insert(e, elt);
|
||||
}
|
||||
|
||||
t1 = result.Extract<ulong>(0);
|
||||
|
||||
for (int e = 2; e <= 3; e++)
|
||||
{
|
||||
uint elt = t1.ULongPart(e - 2);
|
||||
|
||||
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
|
||||
|
||||
elt += w0_3.Extract<uint>(e) + (e == 2 ? w8_11 : w12_15).Extract<uint>(e == 2 ? 3 : 0);
|
||||
|
||||
result.Insert(e, elt);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static V128 Sha256Hash(V128 x, V128 y, V128 w, bool part1)
|
||||
{
|
||||
for (int e = 0; e <= 3; e++)
|
||||
{
|
||||
uint chs = ShaChoose(y.Extract<uint>(0),
|
||||
y.Extract<uint>(1),
|
||||
y.Extract<uint>(2));
|
||||
|
||||
uint maj = ShaMajority(x.Extract<uint>(0),
|
||||
x.Extract<uint>(1),
|
||||
x.Extract<uint>(2));
|
||||
|
||||
uint t1 = y.Extract<uint>(3) + ShaHashSigma1(y.Extract<uint>(0)) + chs + w.Extract<uint>(e);
|
||||
|
||||
uint t2 = t1 + x.Extract<uint>(3);
|
||||
|
||||
x.Insert(3, t2);
|
||||
|
||||
t2 = t1 + ShaHashSigma0(x.Extract<uint>(0)) + maj;
|
||||
|
||||
y.Insert(3, t2);
|
||||
|
||||
Rol32_256(ref y, ref x);
|
||||
}
|
||||
|
||||
return part1 ? x : y;
|
||||
}
|
||||
|
||||
private static void Rol32_256(ref V128 y, ref V128 x)
|
||||
{
|
||||
uint yE3 = y.Extract<uint>(3);
|
||||
uint xE3 = x.Extract<uint>(3);
|
||||
|
||||
y <<= 32;
|
||||
x <<= 32;
|
||||
|
||||
y.Insert(0, xE3);
|
||||
x.Insert(0, yE3);
|
||||
}
|
||||
|
||||
private static uint ShaHashSigma0(uint x)
|
||||
{
|
||||
return x.Ror(2) ^ x.Ror(13) ^ x.Ror(22);
|
||||
}
|
||||
|
||||
private static uint ShaHashSigma1(uint x)
|
||||
{
|
||||
return x.Ror(6) ^ x.Ror(11) ^ x.Ror(25);
|
||||
}
|
||||
|
||||
private static uint Ror(this uint value, int count)
|
||||
{
|
||||
return (value >> count) | (value << (32 - count));
|
||||
}
|
||||
|
||||
private static uint Lsr(this uint value, int count)
|
||||
{
|
||||
return value >> count;
|
||||
}
|
||||
|
||||
private static uint ULongPart(this ulong value, int part)
|
||||
{
|
||||
return part == 0
|
||||
? (uint)(value & 0xFFFFFFFFUL)
|
||||
: (uint)(value >> 32);
|
||||
}
|
||||
#endregion
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 PolynomialMult64_128(ulong op1, ulong op2)
|
||||
{
|
||||
V128 result = V128.Zero;
|
||||
|
||||
V128 op2_128 = new(op2, 0);
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
if (((op1 >> i) & 1) == 1)
|
||||
{
|
||||
result ^= op2_128 << i;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
using ARMeilleure.State;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static partial class SoftFallback
|
||||
{
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Decrypt(V128 value, V128 roundKey)
|
||||
{
|
||||
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Encrypt(V128 value, V128 roundKey)
|
||||
{
|
||||
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 InverseMixColumns(V128 value)
|
||||
{
|
||||
return CryptoHelper.AesInvMixColumns(value);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 MixColumns(V128 value)
|
||||
{
|
||||
return CryptoHelper.AesMixColumns(value);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static partial class SoftFallback
|
||||
{
|
||||
[UnmanagedCallersOnly]
|
||||
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
||||
{
|
||||
value ^= value >> 1;
|
||||
|
||||
int highBit = size - 2;
|
||||
|
||||
for (int bit = highBit; bit >= 0; bit--)
|
||||
{
|
||||
if (((int)(value >> bit) & 0b1) != 0)
|
||||
{
|
||||
return (ulong)(highBit - bit);
|
||||
}
|
||||
}
|
||||
|
||||
return (ulong)(size - 1);
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> ClzNibbleTbl => [4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
||||
{
|
||||
if (value == 0ul)
|
||||
{
|
||||
return (ulong)size;
|
||||
}
|
||||
|
||||
int nibbleIdx = size;
|
||||
int preCount, count = 0;
|
||||
|
||||
do
|
||||
{
|
||||
nibbleIdx -= 4;
|
||||
preCount = ClzNibbleTbl[(int)(value >> nibbleIdx) & 0b1111];
|
||||
count += preCount;
|
||||
}
|
||||
while (preCount == 4);
|
||||
|
||||
return (ulong)count;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static partial class SoftFallback
|
||||
{
|
||||
private const uint Crc32RevPoly = 0xedb88320;
|
||||
private const uint Crc32cRevPoly = 0x82f63b78;
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
|
||||
|
||||
private static uint Crc32h(uint crc, uint poly, ushort val)
|
||||
{
|
||||
crc = Crc32(crc, poly, (byte)(val >> 0));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 8));
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
private static uint Crc32w(uint crc, uint poly, uint val)
|
||||
{
|
||||
crc = Crc32(crc, poly, (byte)(val >> 0));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 8));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 16));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 24));
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
private static uint Crc32x(uint crc, uint poly, ulong val)
|
||||
{
|
||||
crc = Crc32(crc, poly, (byte)(val >> 0));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 8));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 16));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 24));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 32));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 40));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 48));
|
||||
crc = Crc32(crc, poly, (byte)(val >> 56));
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
private static uint Crc32(uint crc, uint poly, byte val)
|
||||
{
|
||||
crc ^= val;
|
||||
|
||||
for (int bit = 7; bit >= 0; bit--)
|
||||
{
|
||||
uint mask = (uint)(-(int)(crc & 1));
|
||||
|
||||
crc = (crc >> 1) ^ (poly & mask);
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static partial class SoftFallback
|
||||
{
|
||||
[UnmanagedCallersOnly]
|
||||
public static int SatF32ToS32(float value)
|
||||
{
|
||||
if (float.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= int.MaxValue ? int.MaxValue :
|
||||
value <= int.MinValue ? int.MinValue : (int)value;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static long SatF32ToS64(float value)
|
||||
{
|
||||
if (float.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= long.MaxValue ? long.MaxValue :
|
||||
value <= long.MinValue ? long.MinValue : (long)value;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint SatF32ToU32(float value)
|
||||
{
|
||||
if (float.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= uint.MaxValue ? uint.MaxValue :
|
||||
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static ulong SatF32ToU64(float value)
|
||||
{
|
||||
if (float.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= ulong.MaxValue ? ulong.MaxValue :
|
||||
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static int SatF64ToS32(double value)
|
||||
{
|
||||
if (double.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= int.MaxValue ? int.MaxValue :
|
||||
value <= int.MinValue ? int.MinValue : (int)value;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static long SatF64ToS64(double value)
|
||||
{
|
||||
if (double.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= long.MaxValue ? long.MaxValue :
|
||||
value <= long.MinValue ? long.MinValue : (long)value;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint SatF64ToU32(double value)
|
||||
{
|
||||
if (double.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= uint.MaxValue ? uint.MaxValue :
|
||||
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static ulong SatF64ToU64(double value)
|
||||
{
|
||||
if (double.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= ulong.MaxValue ? ulong.MaxValue :
|
||||
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
|
||||
}
|
||||
}
|
||||
}
|
131
src/ARMeilleure/Instructions/SoftFallback/SoftFallback.Sha1.cs
Normal file
131
src/ARMeilleure/Instructions/SoftFallback/SoftFallback.Sha1.cs
Normal file
@ -0,0 +1,131 @@
|
||||
using ARMeilleure.State;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static partial class SoftFallback
|
||||
{
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
|
||||
{
|
||||
for (int e = 0; e <= 3; e++)
|
||||
{
|
||||
uint t = ShaChoose(hash_abcd.Extract<uint>(1),
|
||||
hash_abcd.Extract<uint>(2),
|
||||
hash_abcd.Extract<uint>(3));
|
||||
|
||||
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
|
||||
|
||||
t = Rol(hash_abcd.Extract<uint>(1), 30);
|
||||
|
||||
hash_abcd.Insert(1, t);
|
||||
|
||||
Rol32_160(ref hash_e, ref hash_abcd);
|
||||
}
|
||||
|
||||
return hash_abcd;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static uint FixedRotate(uint hash_e)
|
||||
{
|
||||
return hash_e.Rol(30);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk)
|
||||
{
|
||||
for (int e = 0; e <= 3; e++)
|
||||
{
|
||||
uint t = ShaMajority(hash_abcd.Extract<uint>(1),
|
||||
hash_abcd.Extract<uint>(2),
|
||||
hash_abcd.Extract<uint>(3));
|
||||
|
||||
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
|
||||
|
||||
t = Rol(hash_abcd.Extract<uint>(1), 30);
|
||||
|
||||
hash_abcd.Insert(1, t);
|
||||
|
||||
Rol32_160(ref hash_e, ref hash_abcd);
|
||||
}
|
||||
|
||||
return hash_abcd;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk)
|
||||
{
|
||||
for (int e = 0; e <= 3; e++)
|
||||
{
|
||||
uint t = ShaParity(hash_abcd.Extract<uint>(1),
|
||||
hash_abcd.Extract<uint>(2),
|
||||
hash_abcd.Extract<uint>(3));
|
||||
|
||||
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
|
||||
|
||||
t = Rol(hash_abcd.Extract<uint>(1), 30);
|
||||
|
||||
hash_abcd.Insert(1, t);
|
||||
|
||||
Rol32_160(ref hash_e, ref hash_abcd);
|
||||
}
|
||||
|
||||
return hash_abcd;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11)
|
||||
{
|
||||
ulong t2 = w4_7.Extract<ulong>(0);
|
||||
ulong t1 = w0_3.Extract<ulong>(1);
|
||||
|
||||
V128 result = new(t1, t2);
|
||||
|
||||
return result ^ (w0_3 ^ w8_11);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15)
|
||||
{
|
||||
V128 t = tw0_3 ^ (w12_15 >> 32);
|
||||
|
||||
uint tE0 = t.Extract<uint>(0);
|
||||
uint tE1 = t.Extract<uint>(1);
|
||||
uint tE2 = t.Extract<uint>(2);
|
||||
uint tE3 = t.Extract<uint>(3);
|
||||
|
||||
return new V128(tE0.Rol(1), tE1.Rol(1), tE2.Rol(1), tE3.Rol(1) ^ tE0.Rol(2));
|
||||
}
|
||||
|
||||
private static void Rol32_160(ref uint y, ref V128 x)
|
||||
{
|
||||
uint xE3 = x.Extract<uint>(3);
|
||||
|
||||
x <<= 32;
|
||||
x.Insert(0, y);
|
||||
|
||||
y = xE3;
|
||||
}
|
||||
|
||||
private static uint ShaChoose(uint x, uint y, uint z)
|
||||
{
|
||||
return ((y ^ z) & x) ^ z;
|
||||
}
|
||||
|
||||
private static uint ShaMajority(uint x, uint y, uint z)
|
||||
{
|
||||
return (x & y) | ((x | y) & z);
|
||||
}
|
||||
|
||||
private static uint ShaParity(uint x, uint y, uint z)
|
||||
{
|
||||
return x ^ y ^ z;
|
||||
}
|
||||
|
||||
private static uint Rol(this uint value, int count)
|
||||
{
|
||||
return (value << count) | (value >> (32 - count));
|
||||
}
|
||||
}
|
||||
}
|
140
src/ARMeilleure/Instructions/SoftFallback/SoftFallback.Sha256.cs
Normal file
140
src/ARMeilleure/Instructions/SoftFallback/SoftFallback.Sha256.cs
Normal file
@ -0,0 +1,140 @@
|
||||
using ARMeilleure.State;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static partial class SoftFallback
|
||||
{
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
||||
{
|
||||
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
||||
{
|
||||
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
|
||||
{
|
||||
V128 result = new();
|
||||
|
||||
for (int e = 0; e <= 3; e++)
|
||||
{
|
||||
uint elt = (e <= 2 ? w0_3 : w4_7).Extract<uint>(e <= 2 ? e + 1 : 0);
|
||||
|
||||
elt = elt.Ror(7) ^ elt.Ror(18) ^ elt.Lsr(3);
|
||||
|
||||
elt += w0_3.Extract<uint>(e);
|
||||
|
||||
result.Insert(e, elt);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
|
||||
{
|
||||
V128 result = new();
|
||||
|
||||
ulong t1 = w12_15.Extract<ulong>(1);
|
||||
|
||||
for (int e = 0; e <= 1; e++)
|
||||
{
|
||||
uint elt = t1.ULongPart(e);
|
||||
|
||||
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
|
||||
|
||||
elt += w0_3.Extract<uint>(e) + w8_11.Extract<uint>(e + 1);
|
||||
|
||||
result.Insert(e, elt);
|
||||
}
|
||||
|
||||
t1 = result.Extract<ulong>(0);
|
||||
|
||||
for (int e = 2; e <= 3; e++)
|
||||
{
|
||||
uint elt = t1.ULongPart(e - 2);
|
||||
|
||||
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
|
||||
|
||||
elt += w0_3.Extract<uint>(e) + (e == 2 ? w8_11 : w12_15).Extract<uint>(e == 2 ? 3 : 0);
|
||||
|
||||
result.Insert(e, elt);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static V128 Sha256Hash(V128 x, V128 y, V128 w, bool part1)
|
||||
{
|
||||
for (int e = 0; e <= 3; e++)
|
||||
{
|
||||
uint chs = ShaChoose(y.Extract<uint>(0),
|
||||
y.Extract<uint>(1),
|
||||
y.Extract<uint>(2));
|
||||
|
||||
uint maj = ShaMajority(x.Extract<uint>(0),
|
||||
x.Extract<uint>(1),
|
||||
x.Extract<uint>(2));
|
||||
|
||||
uint t1 = y.Extract<uint>(3) + ShaHashSigma1(y.Extract<uint>(0)) + chs + w.Extract<uint>(e);
|
||||
|
||||
uint t2 = t1 + x.Extract<uint>(3);
|
||||
|
||||
x.Insert(3, t2);
|
||||
|
||||
t2 = t1 + ShaHashSigma0(x.Extract<uint>(0)) + maj;
|
||||
|
||||
y.Insert(3, t2);
|
||||
|
||||
Rol32_256(ref y, ref x);
|
||||
}
|
||||
|
||||
return part1 ? x : y;
|
||||
}
|
||||
|
||||
private static void Rol32_256(ref V128 y, ref V128 x)
|
||||
{
|
||||
uint yE3 = y.Extract<uint>(3);
|
||||
uint xE3 = x.Extract<uint>(3);
|
||||
|
||||
y <<= 32;
|
||||
x <<= 32;
|
||||
|
||||
y.Insert(0, xE3);
|
||||
x.Insert(0, yE3);
|
||||
}
|
||||
|
||||
private static uint ShaHashSigma0(uint x)
|
||||
{
|
||||
return x.Ror(2) ^ x.Ror(13) ^ x.Ror(22);
|
||||
}
|
||||
|
||||
private static uint ShaHashSigma1(uint x)
|
||||
{
|
||||
return x.Ror(6) ^ x.Ror(11) ^ x.Ror(25);
|
||||
}
|
||||
|
||||
private static uint Ror(this uint value, int count)
|
||||
{
|
||||
return (value >> count) | (value << (32 - count));
|
||||
}
|
||||
|
||||
private static uint Lsr(this uint value, int count)
|
||||
{
|
||||
return value >> count;
|
||||
}
|
||||
|
||||
private static uint ULongPart(this ulong value, int part)
|
||||
{
|
||||
return part == 0
|
||||
? (uint)(value & 0xFFFFFFFFUL)
|
||||
: (uint)(value >> 32);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static partial class SoftFallback
|
||||
{
|
||||
[UnmanagedCallersOnly]
|
||||
public static long SignedShrImm64(long value, long roundConst, int shift)
|
||||
{
|
||||
if (roundConst == 0L)
|
||||
{
|
||||
if (shift <= 63)
|
||||
{
|
||||
return value >> shift;
|
||||
}
|
||||
else /* if (shift == 64) */
|
||||
{
|
||||
if (value < 0L)
|
||||
{
|
||||
return -1L;
|
||||
}
|
||||
else /* if (value >= 0L) */
|
||||
{
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* if (roundConst == 1L << (shift - 1)) */
|
||||
{
|
||||
if (shift <= 63)
|
||||
{
|
||||
long add = value + roundConst;
|
||||
|
||||
if ((~value & (value ^ add)) < 0L)
|
||||
{
|
||||
return (long)((ulong)add >> shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
return add >> shift;
|
||||
}
|
||||
}
|
||||
else /* if (shift == 64) */
|
||||
{
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift)
|
||||
{
|
||||
if (roundConst == 0L)
|
||||
{
|
||||
if (shift <= 63)
|
||||
{
|
||||
return value >> shift;
|
||||
}
|
||||
else /* if (shift == 64) */
|
||||
{
|
||||
return 0UL;
|
||||
}
|
||||
}
|
||||
else /* if (roundConst == 1L << (shift - 1)) */
|
||||
{
|
||||
ulong add = value + (ulong)roundConst;
|
||||
|
||||
if ((add < value) && (add < (ulong)roundConst))
|
||||
{
|
||||
if (shift <= 63)
|
||||
{
|
||||
return (add >> shift) | (0x8000000000000000UL >> (shift - 1));
|
||||
}
|
||||
else /* if (shift == 64) */
|
||||
{
|
||||
return 1UL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shift <= 63)
|
||||
{
|
||||
return add >> shift;
|
||||
}
|
||||
else /* if (shift == 64) */
|
||||
{
|
||||
return 0UL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static partial class SoftFallback
|
||||
{
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
|
||||
{
|
||||
return TblOrTbx(default, vector, bytes, tb0);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1)
|
||||
{
|
||||
return TblOrTbx(default, vector, bytes, tb0, tb1);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
|
||||
{
|
||||
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
|
||||
{
|
||||
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0)
|
||||
{
|
||||
return TblOrTbx(dest, vector, bytes, tb0);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1)
|
||||
{
|
||||
return TblOrTbx(dest, vector, bytes, tb0, tb1);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
|
||||
{
|
||||
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
|
||||
{
|
||||
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3);
|
||||
}
|
||||
|
||||
private static V128 TblOrTbx(V128 dest, V128 vector, int bytes, params ReadOnlySpan<V128> tb)
|
||||
{
|
||||
byte[] res = new byte[16];
|
||||
|
||||
if (dest != default)
|
||||
{
|
||||
Buffer.BlockCopy(dest.ToArray(), 0, res, 0, bytes);
|
||||
}
|
||||
|
||||
byte[] table = new byte[tb.Length * 16];
|
||||
|
||||
for (byte index = 0; index < tb.Length; index++)
|
||||
{
|
||||
Buffer.BlockCopy(tb[index].ToArray(), 0, table, index * 16, 16);
|
||||
}
|
||||
|
||||
byte[] v = vector.ToArray();
|
||||
|
||||
for (byte index = 0; index < bytes; index++)
|
||||
{
|
||||
byte tblIndex = v[index];
|
||||
|
||||
if (tblIndex < table.Length)
|
||||
{
|
||||
res[index] = table[tblIndex];
|
||||
}
|
||||
}
|
||||
|
||||
return new V128(res);
|
||||
}
|
||||
}
|
||||
}
|
26
src/ARMeilleure/Instructions/SoftFallback/SoftFallback.cs
Normal file
26
src/ARMeilleure/Instructions/SoftFallback/SoftFallback.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using ARMeilleure.State;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static partial class SoftFallback
|
||||
{
|
||||
[UnmanagedCallersOnly]
|
||||
public static V128 PolynomialMult64_128(ulong op1, ulong op2)
|
||||
{
|
||||
V128 result = V128.Zero;
|
||||
|
||||
V128 op2_128 = new(op2, 0);
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
if (((op1 >> i) & 1) == 1)
|
||||
{
|
||||
result ^= op2_128 << i;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
111
src/ARMeilleure/Instructions/SoftFloat/SoftFloat.cs
Normal file
111
src/ARMeilleure/Instructions/SoftFloat/SoftFloat.cs
Normal file
@ -0,0 +1,111 @@
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static class SoftFloat
|
||||
{
|
||||
static SoftFloat()
|
||||
{
|
||||
RecipEstimateTable = BuildRecipEstimateTable();
|
||||
RecipSqrtEstimateTable = BuildRecipSqrtEstimateTable();
|
||||
}
|
||||
|
||||
public static readonly byte[] RecipEstimateTable;
|
||||
public static readonly byte[] RecipSqrtEstimateTable;
|
||||
|
||||
private static byte[] BuildRecipEstimateTable()
|
||||
{
|
||||
byte[] tbl = new byte[256];
|
||||
|
||||
for (int idx = 0; idx < 256; idx++)
|
||||
{
|
||||
uint src = (uint)idx + 256u;
|
||||
|
||||
Debug.Assert(src is >= 256u and < 512u);
|
||||
|
||||
src = (src << 1) + 1u;
|
||||
|
||||
uint aux = (1u << 19) / src;
|
||||
|
||||
uint dst = (aux + 1u) >> 1;
|
||||
|
||||
Debug.Assert(dst is >= 256u and < 512u);
|
||||
|
||||
tbl[idx] = (byte)(dst - 256u);
|
||||
}
|
||||
|
||||
return tbl;
|
||||
}
|
||||
|
||||
private static byte[] BuildRecipSqrtEstimateTable()
|
||||
{
|
||||
byte[] tbl = new byte[384];
|
||||
|
||||
for (int idx = 0; idx < 384; idx++)
|
||||
{
|
||||
uint src = (uint)idx + 128u;
|
||||
|
||||
Debug.Assert(src is >= 128u and < 512u);
|
||||
|
||||
if (src < 256u)
|
||||
{
|
||||
src = (src << 1) + 1u;
|
||||
}
|
||||
else
|
||||
{
|
||||
src = (src >> 1) << 1;
|
||||
src = (src + 1u) << 1;
|
||||
}
|
||||
|
||||
uint aux = 512u;
|
||||
|
||||
while (src * (aux + 1u) * (aux + 1u) < (1u << 28))
|
||||
{
|
||||
aux++;
|
||||
}
|
||||
|
||||
uint dst = (aux + 1u) >> 1;
|
||||
|
||||
Debug.Assert(dst is >= 256u and < 512u);
|
||||
|
||||
tbl[idx] = (byte)(dst - 256u);
|
||||
}
|
||||
|
||||
return tbl;
|
||||
}
|
||||
|
||||
public static void FPProcessException(FPException exc, ExecutionContext context)
|
||||
{
|
||||
FPProcessException(exc, context, context.Fpcr);
|
||||
}
|
||||
|
||||
public static void FPProcessException(FPException exc, ExecutionContext context, FPCR fpcr)
|
||||
{
|
||||
int enable = (int)exc + 8;
|
||||
|
||||
if ((fpcr & (FPCR)(1 << enable)) != 0)
|
||||
{
|
||||
throw new NotImplementedException("Floating-point trap handling.");
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Fpsr |= (FPSR)(1 << (int)exc);
|
||||
}
|
||||
}
|
||||
|
||||
extension(FPCR fpcr)
|
||||
{
|
||||
public FPRoundingMode RoundingMode
|
||||
{
|
||||
get
|
||||
{
|
||||
const int RModeShift = 22;
|
||||
|
||||
return (FPRoundingMode)(((uint)fpcr >> RModeShift) & 3u);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
212
src/ARMeilleure/Instructions/SoftFloat/SoftFloat16.cs
Normal file
212
src/ARMeilleure/Instructions/SoftFloat/SoftFloat16.cs
Normal file
@ -0,0 +1,212 @@
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static class SoftFloat16
|
||||
{
|
||||
public static ushort FPDefaultNaN()
|
||||
{
|
||||
return (ushort)0x7E00u;
|
||||
}
|
||||
|
||||
public static ushort FPInfinity(bool sign)
|
||||
{
|
||||
return sign ? (ushort)0xFC00u : (ushort)0x7C00u;
|
||||
}
|
||||
|
||||
public static ushort FPZero(bool sign)
|
||||
{
|
||||
return sign ? (ushort)0x8000u : (ushort)0x0000u;
|
||||
}
|
||||
|
||||
public static ushort FPMaxNormal(bool sign)
|
||||
{
|
||||
return sign ? (ushort)0xFBFFu : (ushort)0x7BFFu;
|
||||
}
|
||||
|
||||
public static double FPUnpackCv(
|
||||
this ushort valueBits,
|
||||
out FPType type,
|
||||
out bool sign,
|
||||
ExecutionContext context)
|
||||
{
|
||||
sign = (~(uint)valueBits & 0x8000u) == 0u;
|
||||
|
||||
uint exp16 = ((uint)valueBits & 0x7C00u) >> 10;
|
||||
uint frac16 = (uint)valueBits & 0x03FFu;
|
||||
|
||||
double real;
|
||||
|
||||
if (exp16 == 0u)
|
||||
{
|
||||
if (frac16 == 0u)
|
||||
{
|
||||
type = FPType.Zero;
|
||||
real = 0d;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = FPType.Nonzero; // Subnormal.
|
||||
real = Math.Pow(2d, -14) * ((double)frac16 * Math.Pow(2d, -10));
|
||||
}
|
||||
}
|
||||
else if (exp16 == 0x1Fu && (context.Fpcr & FPCR.Ahp) == 0)
|
||||
{
|
||||
if (frac16 == 0u)
|
||||
{
|
||||
type = FPType.Infinity;
|
||||
real = Math.Pow(2d, 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = (~frac16 & 0x0200u) == 0u ? FPType.QNaN : FPType.SNaN;
|
||||
real = 0d;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
type = FPType.Nonzero; // Normal.
|
||||
real = Math.Pow(2d, (int)exp16 - 15) * (1d + (double)frac16 * Math.Pow(2d, -10));
|
||||
}
|
||||
|
||||
return sign ? -real : real;
|
||||
}
|
||||
|
||||
public static ushort FPRoundCv(double real, ExecutionContext context)
|
||||
{
|
||||
const int MinimumExp = -14;
|
||||
|
||||
const int E = 5;
|
||||
const int F = 10;
|
||||
|
||||
bool sign;
|
||||
double mantissa;
|
||||
|
||||
if (real < 0d)
|
||||
{
|
||||
sign = true;
|
||||
mantissa = -real;
|
||||
}
|
||||
else
|
||||
{
|
||||
sign = false;
|
||||
mantissa = real;
|
||||
}
|
||||
|
||||
int exponent = 0;
|
||||
|
||||
while (mantissa < 1d)
|
||||
{
|
||||
mantissa *= 2d;
|
||||
exponent--;
|
||||
}
|
||||
|
||||
while (mantissa >= 2d)
|
||||
{
|
||||
mantissa /= 2d;
|
||||
exponent++;
|
||||
}
|
||||
|
||||
uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
|
||||
|
||||
if (biasedExp == 0u)
|
||||
{
|
||||
mantissa /= Math.Pow(2d, MinimumExp - exponent);
|
||||
}
|
||||
|
||||
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, F));
|
||||
double error = mantissa * Math.Pow(2d, F) - (double)intMant;
|
||||
|
||||
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
|
||||
{
|
||||
SoftFloat.FPProcessException(FPException.Underflow, context);
|
||||
}
|
||||
|
||||
bool overflowToInf;
|
||||
bool roundUp;
|
||||
|
||||
switch (context.Fpcr.RoundingMode)
|
||||
{
|
||||
case FPRoundingMode.ToNearest:
|
||||
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
|
||||
overflowToInf = true;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsPlusInfinity:
|
||||
roundUp = (error != 0d && !sign);
|
||||
overflowToInf = !sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsMinusInfinity:
|
||||
roundUp = (error != 0d && sign);
|
||||
overflowToInf = sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsZero:
|
||||
roundUp = false;
|
||||
overflowToInf = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Invalid rounding mode \"{context.Fpcr.RoundingMode}\".");
|
||||
}
|
||||
|
||||
if (roundUp)
|
||||
{
|
||||
intMant++;
|
||||
|
||||
if (intMant == 1u << F)
|
||||
{
|
||||
biasedExp = 1u;
|
||||
}
|
||||
|
||||
if (intMant == 1u << (F + 1))
|
||||
{
|
||||
biasedExp++;
|
||||
intMant >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
ushort resultBits;
|
||||
|
||||
if ((context.Fpcr & FPCR.Ahp) == 0)
|
||||
{
|
||||
if (biasedExp >= (1u << E) - 1u)
|
||||
{
|
||||
resultBits = overflowToInf ? FPInfinity(sign) : FPMaxNormal(sign);
|
||||
|
||||
SoftFloat.FPProcessException(FPException.Overflow, context);
|
||||
|
||||
error = 1d;
|
||||
}
|
||||
else
|
||||
{
|
||||
resultBits = (ushort)((sign ? 1u : 0u) << 15 | (biasedExp & 0x1Fu) << 10 | (intMant & 0x03FFu));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (biasedExp >= 1u << E)
|
||||
{
|
||||
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
|
||||
|
||||
SoftFloat.FPProcessException(FPException.InvalidOp, context);
|
||||
|
||||
error = 0d;
|
||||
}
|
||||
else
|
||||
{
|
||||
resultBits = (ushort)((sign ? 1u : 0u) << 15 | (biasedExp & 0x1Fu) << 10 | (intMant & 0x03FFu));
|
||||
}
|
||||
}
|
||||
|
||||
if (error != 0d)
|
||||
{
|
||||
SoftFloat.FPProcessException(FPException.Inexact, context);
|
||||
}
|
||||
|
||||
return resultBits;
|
||||
}
|
||||
}
|
||||
}
|
182
src/ARMeilleure/Instructions/SoftFloat/SoftFloat16_32.cs
Normal file
182
src/ARMeilleure/Instructions/SoftFloat/SoftFloat16_32.cs
Normal file
@ -0,0 +1,182 @@
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static class SoftFloat16_32
|
||||
{
|
||||
[UnmanagedCallersOnly]
|
||||
public static float FPConvert(ushort valueBits)
|
||||
{
|
||||
ExecutionContext context = NativeInterface.GetContext();
|
||||
|
||||
double real = valueBits.FPUnpackCv(out FPType type, out bool sign, context);
|
||||
|
||||
float result;
|
||||
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
if ((context.Fpcr & FPCR.Dn) != 0)
|
||||
{
|
||||
result = SoftFloat32.FPDefaultNaN();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = FPConvertNaN(valueBits);
|
||||
}
|
||||
|
||||
if (type == FPType.SNaN)
|
||||
{
|
||||
SoftFloat.FPProcessException(FPException.InvalidOp, context);
|
||||
}
|
||||
}
|
||||
else if (type == FPType.Infinity)
|
||||
{
|
||||
result = SoftFloat32.FPInfinity(sign);
|
||||
}
|
||||
else if (type == FPType.Zero)
|
||||
{
|
||||
result = SoftFloat32.FPZero(sign);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = FPRoundCv(real, context);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static float FPRoundCv(double real, ExecutionContext context)
|
||||
{
|
||||
const int MinimumExp = -126;
|
||||
|
||||
const int E = 8;
|
||||
const int F = 23;
|
||||
|
||||
bool sign;
|
||||
double mantissa;
|
||||
|
||||
if (real < 0d)
|
||||
{
|
||||
sign = true;
|
||||
mantissa = -real;
|
||||
}
|
||||
else
|
||||
{
|
||||
sign = false;
|
||||
mantissa = real;
|
||||
}
|
||||
|
||||
int exponent = 0;
|
||||
|
||||
while (mantissa < 1d)
|
||||
{
|
||||
mantissa *= 2d;
|
||||
exponent--;
|
||||
}
|
||||
|
||||
while (mantissa >= 2d)
|
||||
{
|
||||
mantissa /= 2d;
|
||||
exponent++;
|
||||
}
|
||||
|
||||
if ((context.Fpcr & FPCR.Fz) != 0 && exponent < MinimumExp)
|
||||
{
|
||||
context.Fpsr |= FPSR.Ufc;
|
||||
|
||||
return SoftFloat32.FPZero(sign);
|
||||
}
|
||||
|
||||
uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
|
||||
|
||||
if (biasedExp == 0u)
|
||||
{
|
||||
mantissa /= Math.Pow(2d, MinimumExp - exponent);
|
||||
}
|
||||
|
||||
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, F));
|
||||
double error = mantissa * Math.Pow(2d, F) - (double)intMant;
|
||||
|
||||
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
|
||||
{
|
||||
SoftFloat.FPProcessException(FPException.Underflow, context);
|
||||
}
|
||||
|
||||
bool overflowToInf;
|
||||
bool roundUp;
|
||||
|
||||
switch (context.Fpcr.RoundingMode)
|
||||
{
|
||||
case FPRoundingMode.ToNearest:
|
||||
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
|
||||
overflowToInf = true;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsPlusInfinity:
|
||||
roundUp = (error != 0d && !sign);
|
||||
overflowToInf = !sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsMinusInfinity:
|
||||
roundUp = (error != 0d && sign);
|
||||
overflowToInf = sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsZero:
|
||||
roundUp = false;
|
||||
overflowToInf = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Invalid rounding mode \"{context.Fpcr.RoundingMode}\".");
|
||||
}
|
||||
|
||||
if (roundUp)
|
||||
{
|
||||
intMant++;
|
||||
|
||||
if (intMant == 1u << F)
|
||||
{
|
||||
biasedExp = 1u;
|
||||
}
|
||||
|
||||
if (intMant == 1u << (F + 1))
|
||||
{
|
||||
biasedExp++;
|
||||
intMant >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
float result;
|
||||
|
||||
if (biasedExp >= (1u << E) - 1u)
|
||||
{
|
||||
result = overflowToInf ? SoftFloat32.FPInfinity(sign) : SoftFloat32.FPMaxNormal(sign);
|
||||
|
||||
SoftFloat.FPProcessException(FPException.Overflow, context);
|
||||
|
||||
error = 1d;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = BitConverter.Int32BitsToSingle(
|
||||
(int)((sign ? 1u : 0u) << 31 | (biasedExp & 0xFFu) << 23 | (intMant & 0x007FFFFFu)));
|
||||
}
|
||||
|
||||
if (error != 0d)
|
||||
{
|
||||
SoftFloat.FPProcessException(FPException.Inexact, context);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static float FPConvertNaN(ushort valueBits)
|
||||
{
|
||||
return BitConverter.Int32BitsToSingle(
|
||||
(int)(((uint)valueBits & 0x8000u) << 16 | 0x7FC00000u | ((uint)valueBits & 0x01FFu) << 13));
|
||||
}
|
||||
}
|
||||
}
|
182
src/ARMeilleure/Instructions/SoftFloat/SoftFloat16_64.cs
Normal file
182
src/ARMeilleure/Instructions/SoftFloat/SoftFloat16_64.cs
Normal file
@ -0,0 +1,182 @@
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static class SoftFloat16_64
|
||||
{
|
||||
[UnmanagedCallersOnly]
|
||||
public static double FPConvert(ushort valueBits)
|
||||
{
|
||||
ExecutionContext context = NativeInterface.GetContext();
|
||||
|
||||
double real = valueBits.FPUnpackCv(out FPType type, out bool sign, context);
|
||||
|
||||
double result;
|
||||
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
if ((context.Fpcr & FPCR.Dn) != 0)
|
||||
{
|
||||
result = SoftFloat64.FPDefaultNaN();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = FPConvertNaN(valueBits);
|
||||
}
|
||||
|
||||
if (type == FPType.SNaN)
|
||||
{
|
||||
SoftFloat.FPProcessException(FPException.InvalidOp, context);
|
||||
}
|
||||
}
|
||||
else if (type == FPType.Infinity)
|
||||
{
|
||||
result = SoftFloat64.FPInfinity(sign);
|
||||
}
|
||||
else if (type == FPType.Zero)
|
||||
{
|
||||
result = SoftFloat64.FPZero(sign);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = FPRoundCv(real, context);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static double FPRoundCv(double real, ExecutionContext context)
|
||||
{
|
||||
const int MinimumExp = -1022;
|
||||
|
||||
const int E = 11;
|
||||
const int F = 52;
|
||||
|
||||
bool sign;
|
||||
double mantissa;
|
||||
|
||||
if (real < 0d)
|
||||
{
|
||||
sign = true;
|
||||
mantissa = -real;
|
||||
}
|
||||
else
|
||||
{
|
||||
sign = false;
|
||||
mantissa = real;
|
||||
}
|
||||
|
||||
int exponent = 0;
|
||||
|
||||
while (mantissa < 1d)
|
||||
{
|
||||
mantissa *= 2d;
|
||||
exponent--;
|
||||
}
|
||||
|
||||
while (mantissa >= 2d)
|
||||
{
|
||||
mantissa /= 2d;
|
||||
exponent++;
|
||||
}
|
||||
|
||||
if ((context.Fpcr & FPCR.Fz) != 0 && exponent < MinimumExp)
|
||||
{
|
||||
context.Fpsr |= FPSR.Ufc;
|
||||
|
||||
return SoftFloat64.FPZero(sign);
|
||||
}
|
||||
|
||||
uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
|
||||
|
||||
if (biasedExp == 0u)
|
||||
{
|
||||
mantissa /= Math.Pow(2d, MinimumExp - exponent);
|
||||
}
|
||||
|
||||
ulong intMant = (ulong)Math.Floor(mantissa * Math.Pow(2d, F));
|
||||
double error = mantissa * Math.Pow(2d, F) - (double)intMant;
|
||||
|
||||
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
|
||||
{
|
||||
SoftFloat.FPProcessException(FPException.Underflow, context);
|
||||
}
|
||||
|
||||
bool overflowToInf;
|
||||
bool roundUp;
|
||||
|
||||
switch (context.Fpcr.RoundingMode)
|
||||
{
|
||||
case FPRoundingMode.ToNearest:
|
||||
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
|
||||
overflowToInf = true;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsPlusInfinity:
|
||||
roundUp = (error != 0d && !sign);
|
||||
overflowToInf = !sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsMinusInfinity:
|
||||
roundUp = (error != 0d && sign);
|
||||
overflowToInf = sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsZero:
|
||||
roundUp = false;
|
||||
overflowToInf = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Invalid rounding mode \"{context.Fpcr.RoundingMode}\".");
|
||||
}
|
||||
|
||||
if (roundUp)
|
||||
{
|
||||
intMant++;
|
||||
|
||||
if (intMant == 1ul << F)
|
||||
{
|
||||
biasedExp = 1u;
|
||||
}
|
||||
|
||||
if (intMant == 1ul << (F + 1))
|
||||
{
|
||||
biasedExp++;
|
||||
intMant >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
double result;
|
||||
|
||||
if (biasedExp >= (1u << E) - 1u)
|
||||
{
|
||||
result = overflowToInf ? SoftFloat64.FPInfinity(sign) : SoftFloat64.FPMaxNormal(sign);
|
||||
|
||||
SoftFloat.FPProcessException(FPException.Overflow, context);
|
||||
|
||||
error = 1d;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = BitConverter.Int64BitsToDouble(
|
||||
(long)((sign ? 1ul : 0ul) << 63 | (biasedExp & 0x7FFul) << 52 | (intMant & 0x000FFFFFFFFFFFFFul)));
|
||||
}
|
||||
|
||||
if (error != 0d)
|
||||
{
|
||||
SoftFloat.FPProcessException(FPException.Inexact, context);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static double FPConvertNaN(ushort valueBits)
|
||||
{
|
||||
return BitConverter.Int64BitsToDouble(
|
||||
(long)(((ulong)valueBits & 0x8000ul) << 48 | 0x7FF8000000000000ul | ((ulong)valueBits & 0x01FFul) << 42));
|
||||
}
|
||||
}
|
||||
}
|
1421
src/ARMeilleure/Instructions/SoftFloat/SoftFloat32.cs
Normal file
1421
src/ARMeilleure/Instructions/SoftFloat/SoftFloat32.cs
Normal file
File diff suppressed because it is too large
Load Diff
126
src/ARMeilleure/Instructions/SoftFloat/SoftFloat32_16.cs
Normal file
126
src/ARMeilleure/Instructions/SoftFloat/SoftFloat32_16.cs
Normal file
@ -0,0 +1,126 @@
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static class SoftFloat32_16
|
||||
{
|
||||
[UnmanagedCallersOnly]
|
||||
public static ushort FPConvert(float value)
|
||||
{
|
||||
ExecutionContext context = NativeInterface.GetContext();
|
||||
|
||||
double real = value.FPUnpackCv(out FPType type, out bool sign, out uint valueBits, context);
|
||||
|
||||
bool altHp = (context.Fpcr & FPCR.Ahp) != 0;
|
||||
|
||||
ushort resultBits;
|
||||
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
if (altHp)
|
||||
{
|
||||
resultBits = SoftFloat16.FPZero(sign);
|
||||
}
|
||||
else if ((context.Fpcr & FPCR.Dn) != 0)
|
||||
{
|
||||
resultBits = SoftFloat16.FPDefaultNaN();
|
||||
}
|
||||
else
|
||||
{
|
||||
resultBits = FPConvertNaN(valueBits);
|
||||
}
|
||||
|
||||
if (type == FPType.SNaN || altHp)
|
||||
{
|
||||
SoftFloat.FPProcessException(FPException.InvalidOp, context);
|
||||
}
|
||||
}
|
||||
else if (type == FPType.Infinity)
|
||||
{
|
||||
if (altHp)
|
||||
{
|
||||
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
|
||||
|
||||
SoftFloat.FPProcessException(FPException.InvalidOp, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
resultBits = SoftFloat16.FPInfinity(sign);
|
||||
}
|
||||
}
|
||||
else if (type == FPType.Zero)
|
||||
{
|
||||
resultBits = SoftFloat16.FPZero(sign);
|
||||
}
|
||||
else
|
||||
{
|
||||
resultBits = SoftFloat16.FPRoundCv(real, context);
|
||||
}
|
||||
|
||||
return resultBits;
|
||||
}
|
||||
|
||||
private static double FPUnpackCv(
|
||||
this float value,
|
||||
out FPType type,
|
||||
out bool sign,
|
||||
out uint valueBits,
|
||||
ExecutionContext context)
|
||||
{
|
||||
valueBits = (uint)BitConverter.SingleToInt32Bits(value);
|
||||
|
||||
sign = (~valueBits & 0x80000000u) == 0u;
|
||||
|
||||
uint exp32 = (valueBits & 0x7F800000u) >> 23;
|
||||
uint frac32 = valueBits & 0x007FFFFFu;
|
||||
|
||||
double real;
|
||||
|
||||
if (exp32 == 0u)
|
||||
{
|
||||
if (frac32 == 0u || (context.Fpcr & FPCR.Fz) != 0)
|
||||
{
|
||||
type = FPType.Zero;
|
||||
real = 0d;
|
||||
|
||||
if (frac32 != 0u)
|
||||
{
|
||||
SoftFloat.FPProcessException(FPException.InputDenorm, context);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
type = FPType.Nonzero; // Subnormal.
|
||||
real = Math.Pow(2d, -126) * ((double)frac32 * Math.Pow(2d, -23));
|
||||
}
|
||||
}
|
||||
else if (exp32 == 0xFFu)
|
||||
{
|
||||
if (frac32 == 0u)
|
||||
{
|
||||
type = FPType.Infinity;
|
||||
real = Math.Pow(2d, 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = (~frac32 & 0x00400000u) == 0u ? FPType.QNaN : FPType.SNaN;
|
||||
real = 0d;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
type = FPType.Nonzero; // Normal.
|
||||
real = Math.Pow(2d, (int)exp32 - 127) * (1d + (double)frac32 * Math.Pow(2d, -23));
|
||||
}
|
||||
|
||||
return sign ? -real : real;
|
||||
}
|
||||
|
||||
private static ushort FPConvertNaN(uint valueBits)
|
||||
{
|
||||
return (ushort)((valueBits & 0x80000000u) >> 16 | 0x7E00u | (valueBits & 0x003FE000u) >> 13);
|
||||
}
|
||||
}
|
||||
}
|
1421
src/ARMeilleure/Instructions/SoftFloat/SoftFloat64.cs
Normal file
1421
src/ARMeilleure/Instructions/SoftFloat/SoftFloat64.cs
Normal file
File diff suppressed because it is too large
Load Diff
127
src/ARMeilleure/Instructions/SoftFloat/SoftFloat64_16.cs
Normal file
127
src/ARMeilleure/Instructions/SoftFloat/SoftFloat64_16.cs
Normal file
@ -0,0 +1,127 @@
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static class SoftFloat64_16
|
||||
{
|
||||
[UnmanagedCallersOnly]
|
||||
public static ushort FPConvert(double value)
|
||||
{
|
||||
ExecutionContext context = NativeInterface.GetContext();
|
||||
|
||||
double real = value.FPUnpackCv(out FPType type, out bool sign, out ulong valueBits, context);
|
||||
|
||||
bool altHp = (context.Fpcr & FPCR.Ahp) != 0;
|
||||
|
||||
ushort resultBits;
|
||||
|
||||
if (type is FPType.SNaN or FPType.QNaN)
|
||||
{
|
||||
if (altHp)
|
||||
{
|
||||
resultBits = SoftFloat16.FPZero(sign);
|
||||
}
|
||||
else if ((context.Fpcr & FPCR.Dn) != 0)
|
||||
{
|
||||
resultBits = SoftFloat16.FPDefaultNaN();
|
||||
}
|
||||
else
|
||||
{
|
||||
resultBits = FPConvertNaN(valueBits);
|
||||
}
|
||||
|
||||
if (type == FPType.SNaN || altHp)
|
||||
{
|
||||
SoftFloat.FPProcessException(FPException.InvalidOp, context);
|
||||
}
|
||||
}
|
||||
else if (type == FPType.Infinity)
|
||||
{
|
||||
if (altHp)
|
||||
{
|
||||
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
|
||||
|
||||
SoftFloat.FPProcessException(FPException.InvalidOp, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
resultBits = SoftFloat16.FPInfinity(sign);
|
||||
}
|
||||
}
|
||||
else if (type == FPType.Zero)
|
||||
{
|
||||
resultBits = SoftFloat16.FPZero(sign);
|
||||
}
|
||||
else
|
||||
{
|
||||
resultBits = SoftFloat16.FPRoundCv(real, context);
|
||||
}
|
||||
|
||||
return resultBits;
|
||||
}
|
||||
|
||||
private static double FPUnpackCv(
|
||||
this double value,
|
||||
out FPType type,
|
||||
out bool sign,
|
||||
out ulong valueBits,
|
||||
ExecutionContext context)
|
||||
{
|
||||
valueBits = (ulong)BitConverter.DoubleToInt64Bits(value);
|
||||
|
||||
sign = (~valueBits & 0x8000000000000000ul) == 0u;
|
||||
|
||||
ulong exp64 = (valueBits & 0x7FF0000000000000ul) >> 52;
|
||||
ulong frac64 = valueBits & 0x000FFFFFFFFFFFFFul;
|
||||
|
||||
double real;
|
||||
|
||||
if (exp64 == 0u)
|
||||
{
|
||||
if (frac64 == 0u || (context.Fpcr & FPCR.Fz) != 0)
|
||||
{
|
||||
type = FPType.Zero;
|
||||
real = 0d;
|
||||
|
||||
if (frac64 != 0u)
|
||||
{
|
||||
SoftFloat.FPProcessException(FPException.InputDenorm, context);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
type = FPType.Nonzero; // Subnormal.
|
||||
real = Math.Pow(2d, -1022) * ((double)frac64 * Math.Pow(2d, -52));
|
||||
}
|
||||
}
|
||||
else if (exp64 == 0x7FFul)
|
||||
{
|
||||
if (frac64 == 0u)
|
||||
{
|
||||
type = FPType.Infinity;
|
||||
real = Math.Pow(2d, 1000000);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = (~frac64 & 0x0008000000000000ul) == 0u ? FPType.QNaN : FPType.SNaN;
|
||||
real = 0d;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
type = FPType.Nonzero; // Normal.
|
||||
real = Math.Pow(2d, (int)exp64 - 1023) * (1d + (double)frac64 * Math.Pow(2d, -52));
|
||||
}
|
||||
|
||||
return sign ? -real : real;
|
||||
}
|
||||
|
||||
private static ushort FPConvertNaN(ulong valueBits)
|
||||
{
|
||||
return (ushort)((valueBits & 0x8000000000000000ul) >> 48 | 0x7E00u |
|
||||
(valueBits & 0x0007FC0000000000ul) >> 42);
|
||||
}
|
||||
}
|
||||
}
|
@ -16,9 +16,9 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
|
||||
static class ComparisonExtensions
|
||||
{
|
||||
public static Comparison Invert(this Comparison comp)
|
||||
extension(Comparison comparison)
|
||||
{
|
||||
return (Comparison)((int)comp ^ 1);
|
||||
public Comparison Inverse => (Comparison)((int)comparison ^ 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis;
|
||||
namespace ARMeilleure.IntermediateRepresentation
|
||||
{
|
||||
[Flags]
|
||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
||||
enum Intrinsic : ushort
|
||||
{
|
||||
// X86 (SSE and AVX)
|
||||
|
@ -446,7 +446,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
Data* data = null;
|
||||
|
||||
// If constant or register, then try to look up in the intern table before allocating.
|
||||
if (kind == OperandKind.Constant || kind == OperandKind.Register)
|
||||
if (kind is OperandKind.Constant or OperandKind.Register)
|
||||
{
|
||||
uint hash = (uint)HashCode.Combine(kind, type, value);
|
||||
|
||||
|
@ -14,48 +14,38 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
|
||||
static class OperandTypeExtensions
|
||||
{
|
||||
public static bool IsInteger(this OperandType type)
|
||||
extension(OperandType type)
|
||||
{
|
||||
return type == OperandType.I32 ||
|
||||
type == OperandType.I64;
|
||||
}
|
||||
|
||||
public static RegisterType ToRegisterType(this OperandType type)
|
||||
{
|
||||
return type switch
|
||||
public bool IsInteger => type is OperandType.I32 or OperandType.I64;
|
||||
|
||||
public RegisterType Register => type switch
|
||||
{
|
||||
OperandType.FP32 => RegisterType.Vector,
|
||||
OperandType.FP64 => RegisterType.Vector,
|
||||
OperandType.I32 => RegisterType.Integer,
|
||||
OperandType.I64 => RegisterType.Integer,
|
||||
OperandType.V128 => RegisterType.Vector,
|
||||
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\"."),
|
||||
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\".")
|
||||
};
|
||||
}
|
||||
|
||||
public static int GetSizeInBytes(this OperandType type)
|
||||
{
|
||||
return type switch
|
||||
|
||||
public int ByteSize => type switch
|
||||
{
|
||||
OperandType.FP32 => 4,
|
||||
OperandType.FP64 => 8,
|
||||
OperandType.I32 => 4,
|
||||
OperandType.I64 => 8,
|
||||
OperandType.V128 => 16,
|
||||
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\"."),
|
||||
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\".")
|
||||
};
|
||||
}
|
||||
|
||||
public static int GetSizeInBytesLog2(this OperandType type)
|
||||
{
|
||||
return type switch
|
||||
|
||||
public int ByteSizeLog2 => type switch
|
||||
{
|
||||
OperandType.FP32 => 2,
|
||||
OperandType.FP64 => 3,
|
||||
OperandType.I32 => 2,
|
||||
OperandType.I64 => 3,
|
||||
OperandType.V128 => 4,
|
||||
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\"."),
|
||||
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\".")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -45,19 +45,12 @@ namespace ARMeilleure.Memory
|
||||
|
||||
public static class MemoryManagerTypeExtensions
|
||||
{
|
||||
public static bool IsHostMapped(this MemoryManagerType type)
|
||||
extension(MemoryManagerType type)
|
||||
{
|
||||
return type == MemoryManagerType.HostMapped || type == MemoryManagerType.HostMappedUnsafe;
|
||||
}
|
||||
|
||||
public static bool IsHostTracked(this MemoryManagerType type)
|
||||
{
|
||||
return type == MemoryManagerType.HostTracked || type == MemoryManagerType.HostTrackedUnsafe;
|
||||
}
|
||||
|
||||
public static bool IsHostMappedOrTracked(this MemoryManagerType type)
|
||||
{
|
||||
return type.IsHostMapped() || type.IsHostTracked();
|
||||
public bool IsHostMapped => type is MemoryManagerType.HostMapped or MemoryManagerType.HostMappedUnsafe;
|
||||
public bool IsHostTracked => type is MemoryManagerType.HostTracked or MemoryManagerType.HostTrackedUnsafe;
|
||||
|
||||
public bool IsHostMappedOrTracked => type.IsHostMapped || type.IsHostTracked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,10 +16,8 @@ namespace ARMeilleure.State
|
||||
|
||||
public ulong Pc => _nativeContext.GetPc();
|
||||
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public uint CtrEl0 => 0x8444c004;
|
||||
public uint DczidEl0 => 0x00000004;
|
||||
#pragma warning restore CA1822
|
||||
public static uint CtrEl0 => 0x8444c004;
|
||||
public static uint DczidEl0 => 0x00000004;
|
||||
|
||||
public ulong CntfrqEl0 => _counter.Frequency;
|
||||
public ulong CntpctEl0 => _counter.Counter;
|
||||
|
@ -111,6 +111,7 @@ namespace ARMeilleure.State
|
||||
{
|
||||
value |= GetStorage().Flags[flag] != 0 ? 1u << flag : 0u;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -155,6 +156,7 @@ namespace ARMeilleure.State
|
||||
value |= GetStorage().FpFlags[flag] != 0 ? bit : 0u;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
|
||||
private static JitCacheInvalidation _jitCacheInvalidator;
|
||||
|
||||
private static List<CacheMemoryAllocator> _cacheAllocators = [];
|
||||
private static readonly List<CacheMemoryAllocator> _cacheAllocators = [];
|
||||
|
||||
private static readonly List<CacheEntry> _cacheEntries = [];
|
||||
|
||||
@ -205,7 +205,6 @@ namespace ARMeilleure.Translation.Cache
|
||||
return allocOffsetNew;
|
||||
}
|
||||
|
||||
|
||||
private static int AlignCodeSize(int codeSize)
|
||||
{
|
||||
return checked(codeSize + (CodeAlignment - 1)) & ~(CodeAlignment - 1);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user