mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-02-20 07:41:07 +00:00
Compare commits
67 Commits
Canary-1.3
...
setup-wiza
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7dd718d6f | ||
|
|
6ee7957574 | ||
|
|
bf62531802 | ||
|
|
17be50ea80 | ||
|
|
ec50a1ec3e | ||
|
|
5a20047e5e | ||
|
|
f9fed4cf4d | ||
|
|
2970dcd3c7 | ||
|
|
4be6cb2fa1 | ||
|
|
c90d2af9cd | ||
|
|
13ff9cb162 | ||
|
|
b35ba58831 | ||
|
|
e12a77d4a3 | ||
|
|
804a4e0bcb | ||
|
|
94870eafaa | ||
|
|
7e6cc31866 | ||
|
|
3b25c43abf | ||
|
|
1804dd031b | ||
|
|
211498e060 | ||
|
|
4bdee89288 | ||
|
|
d8a6364cca | ||
|
|
2f794794c6 | ||
|
|
1d6c2426df | ||
|
|
6cd03f15fa | ||
|
|
3fe7600382 | ||
|
|
dc2aa837b3 | ||
|
|
133ac41425 | ||
|
|
fd2ecee479 | ||
|
|
8f529d17a8 | ||
|
|
884d0f526c | ||
|
|
c5b325bde2 | ||
|
|
8ab851ead8 | ||
|
|
5a060cf451 | ||
|
|
9b0fa3bf6d | ||
|
|
325e13a490 | ||
|
|
e202cccc6e | ||
|
|
e0ed8f56ea | ||
|
|
46b2fb92d7 | ||
|
|
8563e7d4dc | ||
|
|
ee10cbf735 | ||
|
|
b033adbde7 | ||
|
|
66f339d265 | ||
|
|
6cdbdfd329 | ||
|
|
9f817d60d5 | ||
|
|
5cffc95be6 | ||
|
|
2c0977f6b3 | ||
|
|
3a593b6084 | ||
|
|
c3155fcadb | ||
|
|
fd7554425a | ||
|
|
52700f71dc | ||
|
|
b018a44ff0 | ||
|
|
d522bfef62 | ||
|
|
39f55b2af3 | ||
|
|
6126e3dc1e | ||
|
|
e1c829f91d | ||
|
|
6c7dc7646b | ||
|
|
862a686c5e | ||
|
|
e8751e1c40 | ||
|
|
09748b140a | ||
|
|
456db46065 | ||
|
|
7b39ff36c0 | ||
|
|
10476771d3 | ||
|
|
c5082ac85a | ||
|
|
5e86ad83cc | ||
|
|
1baaa1c365 | ||
|
|
e8225ce7aa | ||
|
|
6b814fb973 |
101
.github/workflows/canary.yml
vendored
101
.github/workflows/canary.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Canary release job
|
||||
name: Canary CI
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -19,7 +19,6 @@ concurrency: release
|
||||
env:
|
||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
RYUJINX_BASE_VERSION: "1.3"
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_NAME: "canary"
|
||||
RELEASE: 1
|
||||
|
||||
@@ -30,8 +29,8 @@ jobs:
|
||||
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: win-x64, os: ubuntu-latest, zip_os_name: win_x64 }
|
||||
#- { name: win-arm64, os: ubuntu-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:
|
||||
@@ -44,12 +43,27 @@ jobs:
|
||||
- name: Overwrite csc problem matcher
|
||||
run: echo "::add-matcher::.github/csc.json"
|
||||
|
||||
- name: Install 7zip
|
||||
run: |
|
||||
sudo apt install -y 7zip
|
||||
|
||||
- name: Install gli
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'gli-linux-x64'
|
||||
chmod +x gli
|
||||
mv gli $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 }}" >> $GITHUB_OUTPUT
|
||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
||||
echo "build_version=$(gli get-next-version -c Canary -R)" >> $GITHUB_OUTPUT
|
||||
echo "prev_build_version=$(gli get-current-version -c Canary -R)" >> $GITHUB_OUTPUT
|
||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
echo "commit_message=$(git log -1 --pretty=%B)" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Configure for release
|
||||
@@ -69,33 +83,20 @@ jobs:
|
||||
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'
|
||||
if: contains(matrix.platform.name, 'win')
|
||||
run: |
|
||||
pushd publish
|
||||
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"
|
||||
|
||||
gli upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/canary -n Ryubing-Canary -v ${{ steps.version_info.outputs.build_version }} -p 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'
|
||||
if: contains(matrix.platform.name, 'linux')
|
||||
run: |
|
||||
pushd publish
|
||||
rm libarmeilleure-jitsupport.dylib
|
||||
@@ -103,11 +104,11 @@ jobs:
|
||||
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"
|
||||
gli upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/canary -n Ryubing-Canary -v ${{ steps.version_info.outputs.build_version }} -p release_output/ryujinx-canary-${{ 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'
|
||||
if: contains(matrix.platform.name, 'linux')
|
||||
run: |
|
||||
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
|
||||
PLATFORM_NAME="${{ matrix.platform.name }}"
|
||||
@@ -139,8 +140,8 @@ jobs:
|
||||
pushd publish_appimage
|
||||
mv Ryujinx.AppImage ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage
|
||||
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 upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/canary -n Ryubing-Canary -v ${{ steps.version_info.outputs.build_version }} -p release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage
|
||||
shell: bash
|
||||
|
||||
macos_release:
|
||||
@@ -159,10 +160,10 @@ jobs:
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 17
|
||||
|
||||
- name: Install GitLabCli
|
||||
- name: Install gli
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
||||
gh release download -R GreemDev/GLI -O gli -p 'gli-linux-x64'
|
||||
chmod +x gli
|
||||
mv gli $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
@@ -183,9 +184,10 @@ jobs:
|
||||
- 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 "build_version=$(gli get-next-version -c Canary -R)" >> $GITHUB_OUTPUT
|
||||
echo "prev_build_version=$(gli get-current-version -c Canary -R)" >> $GITHUB_OUTPUT
|
||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Configure for release
|
||||
run: |
|
||||
@@ -200,7 +202,7 @@ jobs:
|
||||
- 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"
|
||||
gli upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/canary -n Ryubing-Canary -v ${{ steps.version_info.outputs.build_version }} -p publish_ava/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz
|
||||
|
||||
create_gitlab_release:
|
||||
name: Create GitLab Release
|
||||
@@ -210,37 +212,42 @@ jobs:
|
||||
- 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
|
||||
|
||||
- name: Install gli
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
||||
gh release download -R GreemDev/GLI -O gli -p 'gli-linux-x64'
|
||||
chmod +x gli
|
||||
mv gli $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get version info
|
||||
id: version_info
|
||||
run: |
|
||||
echo "build_version=$(gli get-next-version -c Canary -R)" >> $GITHUB_OUTPUT
|
||||
echo "prev_build_version=$(gli get-current-version -c Canary -R)" >> $GITHUB_OUTPUT
|
||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
echo "commit_message=$(git log -1 --pretty=%B)" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- 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 }}"
|
||||
gli create-tag -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/ryujinx -n Canary-${{ steps.version_info.outputs.build_version }} -r ${{ steps.version_info.outputs.git_short_hash }} -c "${{ steps.version_info.outputs.commit_message }}"
|
||||
|
||||
- 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 }})"
|
||||
gli create-release-from-generic-package-files -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/canary -n Ryubing-Canary -v ${{ steps.version_info.outputs.build_version }} -r main -t "Canary ${{ steps.version_info.outputs.build_version }}" -b "**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"
|
||||
gli send-update-message -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/canary -t ${{ steps.version_info.outputs.build_version }} -c FF4500 -w ${{ secrets.CANARY_DISCORD_WEBHOOK }} -i https://avatars.githubusercontent.com/u/192939710?s=200&v=4
|
||||
|
||||
- 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 }}'
|
||||
gli refresh-version-cache -T ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }} -c Canary
|
||||
|
||||
- name: Advance to the next version
|
||||
run: |
|
||||
gli increment-version -T ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }} -c Canary
|
||||
|
||||
224
.github/workflows/debug_release.yml
vendored
224
.github/workflows/debug_release.yml
vendored
@@ -1,224 +0,0 @@
|
||||
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"
|
||||
123
.github/workflows/release.yml
vendored
123
.github/workflows/release.yml
vendored
@@ -1,15 +1,18 @@
|
||||
name: Release job
|
||||
name: Stable CI
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs: {}
|
||||
inputs:
|
||||
is_bugfix_release:
|
||||
description: "Bug fix release: If checked, this will increment the third number for only Stable, and leave the Major version alone for both Stable and Canary."
|
||||
required: true
|
||||
type: boolean
|
||||
|
||||
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
|
||||
|
||||
@@ -20,8 +23,8 @@ jobs:
|
||||
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: win-x64, os: ubuntu-latest, zip_os_name: win_x64 }
|
||||
#- { name: win-arm64, os: ubuntu-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:
|
||||
@@ -33,12 +36,30 @@ jobs:
|
||||
|
||||
- name: Overwrite csc problem matcher
|
||||
run: echo "::add-matcher::.github/csc.json"
|
||||
|
||||
- name: Install 7zip
|
||||
run: |
|
||||
sudo apt install -y 7zip
|
||||
|
||||
- name: Install gli
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'gli-linux-x64'
|
||||
chmod +x gli
|
||||
mv gli $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 }}" >> $GITHUB_OUTPUT
|
||||
echo "prev_build_version=${{ env.RYUJINX_BASE_VERSION }}.$((${{ github.run_number }} - 1))" >> $GITHUB_OUTPUT
|
||||
if [ '${{ inputs.is_bugfix_release }}' == 'false' ]; then
|
||||
echo "build_version=$(gli get-next-version -m -c Stable -R)" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "build_version=$(gli get-next-version -c Stable -R)" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
echo "prev_build_version=$(gli get-current-version -c Stable -R)" >> $GITHUB_OUTPUT
|
||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
@@ -58,47 +79,34 @@ jobs:
|
||||
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'
|
||||
if: contains(matrix.platform.name, 'win')
|
||||
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"
|
||||
|
||||
gli upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/ryujinx -n Ryubing -v ${{ steps.version_info.outputs.build_version }} -p 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'
|
||||
if: contains(matrix.platform.name, 'linux')
|
||||
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"
|
||||
|
||||
gli upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/ryujinx -n Ryubing -v ${{ steps.version_info.outputs.build_version }} -p 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'
|
||||
if: contains(matrix.platform.name, 'linux')
|
||||
run: |
|
||||
BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
|
||||
PLATFORM_NAME="${{ matrix.platform.name }}"
|
||||
@@ -131,7 +139,7 @@ jobs:
|
||||
mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage
|
||||
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 upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/ryujinx -n Ryubing -v ${{ steps.version_info.outputs.build_version }} -p release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage
|
||||
shell: bash
|
||||
|
||||
macos_release:
|
||||
@@ -150,10 +158,10 @@ jobs:
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 17
|
||||
|
||||
- name: Install GitLabCli
|
||||
- name: Install gli
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
||||
gh release download -R GreemDev/GLI -O gli -p 'gli-linux-x64'
|
||||
chmod +x gli
|
||||
mv gli $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
@@ -174,9 +182,14 @@ jobs:
|
||||
- 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
|
||||
if [ '${{ inputs.is_bugfix_release }}' == 'false' ]; then
|
||||
echo "build_version=$(gli get-next-version -m -c Stable -R)" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "build_version=$(gli get-next-version -c Stable -R)" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
echo "prev_build_version=$(gli get-current-version -c Stable -R)" >> $GITHUB_OUTPUT
|
||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- name: Configure for release
|
||||
run: |
|
||||
@@ -189,7 +202,8 @@ jobs:
|
||||
- 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"
|
||||
|
||||
gli upload-generic-package -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/ryujinx -n Ryubing -v ${{ steps.version_info.outputs.build_version }} -p publish/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz
|
||||
|
||||
create_gitlab_release:
|
||||
name: Create GitLab Release
|
||||
@@ -200,32 +214,45 @@ jobs:
|
||||
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
|
||||
- name: Install gli
|
||||
run: |
|
||||
mkdir -p $HOME/.bin
|
||||
gh release download -R GreemDev/GLI -O gli -p 'GitLabCli-linux_x64'
|
||||
gh release download -R GreemDev/GLI -O gli -p 'gli-linux-x64'
|
||||
chmod +x gli
|
||||
mv gli $HOME/.bin/
|
||||
echo "$HOME/.bin" >> $GITHUB_PATH
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get version info
|
||||
id: version_info
|
||||
run: |
|
||||
if [ '${{ inputs.is_bugfix_release }}' == 'false' ]; then
|
||||
echo "build_version=$(gli get-next-version -m -c Stable -R)" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "build_version=$(gli get-next-version -c Stable -R)" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
echo "prev_build_version=$(gli get-current-version -c Stable -R)" >> $GITHUB_OUTPUT
|
||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
echo "commit_message=$(git log -1 --pretty=%B)" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- 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 }}"
|
||||
|
||||
gli create-release-from-generic-package-files -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/ryujinx -n Ryubing -v ${{ steps.version_info.outputs.build_version }} -r ${{ steps.version_info.outputs.git_short_hash }} -t "${{ steps.version_info.outputs.build_version }}" -b "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"
|
||||
|
||||
gli send-update-message -T ${{ secrets.GITLAB_TOKEN }} -P ryubing/ryujinx -t ${{ steps.version_info.outputs.build_version }} -c 32cd32 -w ${{ secrets.STABLE_DISCORD_WEBHOOK }} -i https://avatars.githubusercontent.com/u/192939710?s=200&v=4
|
||||
|
||||
- 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 }}'
|
||||
gli refresh-version-cache -T ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }} -c Stable
|
||||
|
||||
- name: Advance to the next version
|
||||
run: |
|
||||
if [ '${{ inputs.is_bugfix_release }}' == 'false' ]; then
|
||||
gli advance-version -T ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }}
|
||||
else
|
||||
gli increment-version -T ${{ secrets.UPDATE_SERVER_ADMIN_TOKEN }} -c Stable
|
||||
fi
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -18,6 +18,8 @@ build/
|
||||
[Oo]bj/
|
||||
AppDir/
|
||||
publish_appimage/
|
||||
publish_ava/
|
||||
publish_tmp_ava/
|
||||
|
||||
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
|
||||
!packages/*/build/
|
||||
@@ -98,6 +100,7 @@ DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
RyubingMaintainerTools/
|
||||
|
||||
# Publish Web Output
|
||||
*.Publish.xml
|
||||
|
||||
@@ -5,7 +5,7 @@ If you wish to build the emulator yourself, follow these steps:
|
||||
|
||||
### Step 1
|
||||
|
||||
Install the [.NET 9.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/9.0).
|
||||
Install the [.NET 10.0 (or higher) SDK](https://dotnet.microsoft.com/en-us/download/dotnet/10.0).
|
||||
Make sure your SDK version is higher or equal to the required version specified in [global.json](global.json).
|
||||
|
||||
### Step 2
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<LangVersion>preview</LangVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.126" />
|
||||
<PackageVersion Include="Ryujinx.UpdateClient" Version="1.0.44" />
|
||||
<PackageVersion Include="Ryujinx.Systems.Update.Common" Version="1.0.44" />
|
||||
<PackageVersion Include="Gommon" Version="2.8.0.1" />
|
||||
<PackageVersion Include="Gommon" Version="2.8.0.2" />
|
||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageVersion Include="Sep" Version="0.11.1" />
|
||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||
@@ -59,4 +59,4 @@
|
||||
<PackageVersion Include="System.Management" Version="9.0.2" />
|
||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -85,6 +85,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
.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
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
"el_GR": "Χωρίς Ελέγχους (γρηγορότερο, μη ασφαλές)",
|
||||
"en_US": "Host Unchecked (Fastest, Unsafe)",
|
||||
"es_ES": "Host Sin Verificación (Más rápido, Inseguro)",
|
||||
"fr_FR": "Hôte Non Vérifié (plus rapide, non sécurisé)",
|
||||
"fr_FR": "Hôte Non Vérifié (Plus Rapide, Non Sécurisé)",
|
||||
"he_IL": "מארח לא מבוקר (המהיר ביותר, לא בטוח)",
|
||||
"it_IT": "Host senza verifica (più veloce, non sicura)",
|
||||
"ja_JP": "ホスト, チェックなし (最高速, 安全でない)",
|
||||
@@ -3350,7 +3350,7 @@
|
||||
"el_GR": "Ερώτημα",
|
||||
"en_US": "Prompt",
|
||||
"es_ES": "Al Inicio",
|
||||
"fr_FR": "Demande",
|
||||
"fr_FR": "Demander",
|
||||
"he_IL": "הודעה",
|
||||
"it_IT": "Domanda",
|
||||
"ja_JP": "プロンプト",
|
||||
@@ -4800,7 +4800,7 @@
|
||||
"el_GR": "Backend Ήχου:",
|
||||
"en_US": "Audio Backend:",
|
||||
"es_ES": "Motor de Audio:",
|
||||
"fr_FR": "Bibliothèque Audio :",
|
||||
"fr_FR": "Moteur Audio :",
|
||||
"he_IL": "אחראי שמע:",
|
||||
"it_IT": "Backend audio:",
|
||||
"ja_JP": "音声バックエンド:",
|
||||
@@ -5700,7 +5700,7 @@
|
||||
"el_GR": "Έκταση σε όλο το παράθυρο",
|
||||
"en_US": "Stretch to Fit Window",
|
||||
"es_ES": "Estirar a la Ventana",
|
||||
"fr_FR": "Ajuster à la Taille de la Fenêtre",
|
||||
"fr_FR": "Adapter à la Taille de la Fenêtre",
|
||||
"he_IL": "מתח לגודל חלון",
|
||||
"it_IT": "Adatta alla finestra",
|
||||
"ja_JP": "ウインドウサイズに合わせる",
|
||||
@@ -5750,7 +5750,7 @@
|
||||
"el_GR": "Τοποθεσία Shaders Γραφικών:",
|
||||
"en_US": "Graphics Shader Dump Path:",
|
||||
"es_ES": "Directorio de Volcado de Sombreadores:",
|
||||
"fr_FR": "Chemin du Dossier de Copie des Shaders :",
|
||||
"fr_FR": "Chemin du dump des shaders graphiques :",
|
||||
"he_IL": "",
|
||||
"it_IT": "Percorso di dump degli shader:",
|
||||
"ja_JP": "グラフィックス シェーダー ダンプパス:",
|
||||
@@ -15000,7 +15000,7 @@
|
||||
"el_GR": "Πολυνηματική Επεξεργασία Γραφικών:",
|
||||
"en_US": "Graphics Backend Multithreading:",
|
||||
"es_ES": "Multihilado del Motor Gráfico:",
|
||||
"fr_FR": "Interface graphique multithread :",
|
||||
"fr_FR": "Interface Graphique Multithread :",
|
||||
"he_IL": "אחראי גרפיקה רב-תהליכי:",
|
||||
"it_IT": "Multithreading del backend grafico:",
|
||||
"ja_JP": "グラフィックスバックエンドのマルチスレッド実行:",
|
||||
@@ -16598,9 +16598,9 @@
|
||||
"ar_SA": "",
|
||||
"de_DE": "Diese Option überspringt den Dialog 'Benutzerprofile verwalten' während des Spiels und verwendet ein voreingestelltes Profil.\n\nDie Profilumschaltung finden Sie unter 'Einstellungen' - 'Benutzerprofile verwalten'. Wählen Sie das gewünschte Profil aus, bevor Sie das Spiel laden.",
|
||||
"el_GR": "Αυτή η επιλογή παρακάμπτει το παράθυρο διαλόγου 'Διαχειριστής Προφίλ Χρήστη' κατά τη διάρκεια του παιχνιδιού, χρησιμοποιώντας ένα προεπιλεγμένο προφίλ.\n\nΗ εναλλαγή προφίλ βρίσκεται στις 'Ρυθμίσεις' - 'Διαχειριστής Προφίλ Χρήστη'. Επιλέξτε το επιθυμητό προφίλ πριν φορτώσετε το παιχνίδι.",
|
||||
"en_US": "This option skips the 'Manage User Profiles' dialog during gameplay, using a pre-selected profile.\n\nProfile switching is found in 'Settings' - 'Manager User Profiles'. Select the desired profile before loading the game.",
|
||||
"es_ES": "Esta opción omite el diálogo de 'Gestionar perfiles de usuario' durante el juego, utilizando un perfil preseleccionado.\n\nEl cambio de perfil se encuentra en 'Configuración' - 'Gestionar perfiles de usuario'. Seleccione el perfil deseado antes de cargar el juego.",
|
||||
"fr_FR": "Cette option permet d'éviter le dialogue du 'Gérer les profils d'utilisateurs' pendant le jeu, en utilisant un profil pré-sélectionné.\n\nLa sélection du profil se trouve dans 'Paramètres' - 'Gérer les profils d'utilisateurs'. Sélectionnez le profil souhaité avant de lancer le jeu.",
|
||||
"en_US": "This option skips the 'Manage User Profiles' dialog during gameplay, using a pre-selected profile.\n\nProfile switching is found in 'Options' - 'User Profiles'. Select the desired profile before loading the game.",
|
||||
"es_ES": "Esta opción omite el diálogo de 'Gestionar perfiles de usuario' durante el juego, utilizando un perfil preseleccionado.\n\nEl cambio de perfil se encuentra en 'Opciones' - 'Perfiles de Usuario'. Seleccione el perfil deseado antes de cargar el juego.",
|
||||
"fr_FR": "Cette option permet de passer le dialogue 'Gérer les profils d'utilisateurs' pendant le jeu, en utilisant un profil pré-sélectionné.\n\nLa sélection du profil se trouve dans 'Options' - 'Profils d'Utilisateurs'. Sélectionnez le profil souhaité avant de lancer le jeu.",
|
||||
"he_IL": "",
|
||||
"it_IT": "Questa opzione salta la finestra di dialogo 'Gestisci i profili utente' durante il gioco, utilizzando un profilo pre-selezionato.\n\nIl cambio del profilo si trova in 'Impostazioni' - 'Gestisci i profili utente'. Seleziona il profilo desiderato prima di caricare il gioco.",
|
||||
"ja_JP": "このオプションは、ゲームプレイ中に「ユーザプロファイルを管理」ダイアログをスキップし、事前に選択されたプロファイルを使用します。\n\nプロファイルの切り替えは、「設定」-「ユーザプロファイルを管理」で見つけることができます。ゲームのロード前に目的のプロファイルをを選択してください。",
|
||||
@@ -22520,26 +22520,26 @@
|
||||
{
|
||||
"ID": "MultiplayerModeTooltip",
|
||||
"Translations": {
|
||||
"ar_SA": "تغيير وضع LDN متعدد اللاعبين.\n\nسوف يقوم LdnMitm بتعديل وظيفة اللعب المحلية/اللاسلكية المحلية في الألعاب لتعمل كما لو كانت شبكة LAN، مما يسمح باتصالات الشبكة المحلية نفسها مع محاكيات ريوجينكس الأخرى وأجهزة نينتندو سويتش المخترقة التي تم تثبيت وحدة ldn_mitm عليها.\n\nيتطلب وضع اللاعبين المتعددين أن يكون جميع اللاعبين على نفس إصدار اللعبة (على سبيل المثال، يتعذر على الإصدار 13.0.1 من سوبر سماش برذرز ألتميت الاتصال بالإصدار 13.0.0).\n\nاتركه معطلا إذا لم تكن متأكدا.",
|
||||
"de_DE": "Ändert den LDN-Mehrspielermodus.\n\nLdnMitm ändert die lokale drahtlose/lokale Spielfunktionalität in Spielen so, dass sie wie ein LAN funktioniert und lokale, netzwerkgleiche Verbindungen mit anderen Ryujinx-Instanzen und gehackten Nintendo Switch-Konsolen ermöglicht, auf denen das ldn_mitm-Modul installiert ist.\n\nMultiplayer erfordert, dass alle Spieler die gleiche Spielversion verwenden (d.h. Super Smash Bros. Ultimate v13.0.1 kann sich nicht mit v13.0.0 verbinden).\n\nIm Zweifelsfall auf DISABLED lassen.",
|
||||
"ar_SA": "تغيير وضع LDN متعدد اللاعبين.\n\nسوف يقوم ldn_mitm بتعديل وظيفة اللعب المحلية/اللاسلكية المحلية في الألعاب لتعمل كما لو كانت شبكة LAN، مما يسمح باتصالات الشبكة المحلية نفسها مع محاكيات ريوجينكس الأخرى وأجهزة نينتندو سويتش المخترقة التي تم تثبيت وحدة ldn_mitm عليها.\n\nيتطلب وضع اللاعبين المتعددين أن يكون جميع اللاعبين على نفس إصدار اللعبة (على سبيل المثال، يتعذر على الإصدار 13.0.1 من سوبر سماش برذرز ألتميت الاتصال بالإصدار 13.0.0).\n\nاتركه معطلا إذا لم تكن متأكدا.",
|
||||
"de_DE": "Ändert den LDN-Mehrspielermodus.\n\nldn_mitm ändert die lokale drahtlose/lokale Spielfunktionalität in Spielen so, dass sie wie ein LAN funktioniert und lokale, netzwerkgleiche Verbindungen mit anderen Ryujinx-Instanzen und gehackten Nintendo Switch-Konsolen ermöglicht, auf denen das ldn_mitm-Modul installiert ist.\n\nMultiplayer erfordert, dass alle Spieler die gleiche Spielversion verwenden (d.h. Super Smash Bros. Ultimate v13.0.1 kann sich nicht mit v13.0.0 verbinden).\n\nIm Zweifelsfall auf DISABLED lassen.",
|
||||
"el_GR": "",
|
||||
"en_US": "Change LDN multiplayer mode.\n\nLdnMitm will modify local wireless/local play functionality in games to function as if it were LAN, allowing for local, same-network connections with other Ryujinx instances and hacked Nintendo Switch consoles that have the ldn_mitm module installed.\n\nMultiplayer requires all players to be on the same game version (i.e. Super Smash Bros. Ultimate v13.0.1 can't connect to v13.0.0).\n\nLeave DISABLED if unsure.",
|
||||
"es_ES": "Cambiar modo LDN multijugador.\n\nLdnMitm modificará la funcionalidad local de juego inalámbrico para funcionar como si fuera LAN, permitiendo locales conexiones de la misma red con otras instancias de Ryujinx y consolas hackeadas de Nintendo Switch que tienen instalado el módulo ldn_mitm.\n\nMultijugador requiere que todos los jugadores estén en la misma versión del juego (por ejemplo, Super Smash Bros. Ultimate v13.0.1 no se puede conectar a v13.0.0).\n\nDejar DESACTIVADO si no está seguro.",
|
||||
"fr_FR": "Change le mode multijoueur LDN.\n\nLdnMitm modifiera la fonctionnalité de jeu sans fil local/jeu local dans les jeux pour fonctionner comme s'il s'agissait d'un LAN, permettant des connexions locales sur le même réseau avec d'autres instances de Ryujinx et des consoles Nintendo Switch piratées ayant le module ldn_mitm installé.\n\nLe multijoueur nécessite que tous les joueurs soient sur la même version du jeu (par exemple, Super Smash Bros. Ultimate v13.0.1 ne peut pas se connecter à v13.0.0).\n\nLaissez DÉSACTIVÉ si vous n'êtes pas sûr.",
|
||||
"en_US": "Change LDN multiplayer mode.\n\nldn_mitm will modify local wireless/local play functionality in games to function as if it were LAN, allowing for local, same-network connections with other Ryujinx instances and hacked Nintendo Switch consoles that have the ldn_mitm module installed.\n\nMultiplayer requires all players to be on the same game version (i.e. Super Smash Bros. Ultimate v13.0.1 can't connect to v13.0.0).\n\nLeave DISABLED if unsure.",
|
||||
"es_ES": "Cambiar modo LDN multijugador.\n\nldn_mitm modificará la funcionalidad local de juego inalámbrico para funcionar como si fuera LAN, permitiendo locales conexiones de la misma red con otras instancias de Ryujinx y consolas hackeadas de Nintendo Switch que tienen instalado el módulo ldn_mitm.\n\nMultijugador requiere que todos los jugadores estén en la misma versión del juego (por ejemplo, Super Smash Bros. Ultimate v13.0.1 no se puede conectar a v13.0.0).\n\nDejar DESACTIVADO si no está seguro.",
|
||||
"fr_FR": "Change le mode multijoueur LDN.\n\nldn_mitm modifiera la fonctionnalité de jeu sans fil local/jeu local dans les jeux pour fonctionner comme s'il s'agissait d'un LAN, permettant des connexions locales sur le même réseau avec d'autres instances de Ryujinx et des consoles Nintendo Switch piratées ayant le module ldn_mitm installé.\n\nLe multijoueur nécessite que tous les joueurs soient sur la même version du jeu (par exemple, Super Smash Bros. Ultimate v13.0.1 ne peut pas se connecter à v13.0.0).\n\nLaissez DÉSACTIVÉ si vous n'êtes pas sûr.",
|
||||
"he_IL": "",
|
||||
"it_IT": "Cambia la modalità multigiocatore LDN.\n\nLdnMitm modificherà la funzionalità locale wireless/local play nei giochi per funzionare come se fosse in modalità LAN, consentendo connessioni locali sulla stessa rete con altre istanze di Ryujinx e console Nintendo Switch modificate che hanno il modulo ldn_mitm installato.\n\nLa modalità multigiocatore richiede che tutti i giocatori usino la stessa versione del gioco (es. Super Smash Bros. Ultimate v13.0.1 non può connettersi con la v13.0.0).\n\nNel dubbio, lascia l'opzione su Disabilitato.",
|
||||
"it_IT": "Cambia la modalità multigiocatore LDN.\n\nldn_mitm modificherà la funzionalità locale wireless/local play nei giochi per funzionare come se fosse in modalità LAN, consentendo connessioni locali sulla stessa rete con altre istanze di Ryujinx e console Nintendo Switch modificate che hanno il modulo ldn_mitm installato.\n\nLa modalità multigiocatore richiede che tutti i giocatori usino la stessa versione del gioco (es. Super Smash Bros. Ultimate v13.0.1 non può connettersi con la v13.0.0).\n\nNel dubbio, lascia l'opzione su Disabilitato.",
|
||||
"ja_JP": "LDNマルチプレイヤーモードを変更します.\n\nldn_mitmモジュールがインストールされた, 他のRyujinxインスタンスや,ハックされたNintendo Switchコンソールとのローカル/同一ネットワーク接続を可能にします.\n\nマルチプレイでは, すべてのプレイヤーが同じゲームバージョンである必要があります(例:Super Smash Bros. Ultimate v13.0.1はv13.0.0に接続できません).\n\n不明な場合は「無効」のままにしてください.",
|
||||
"ko_KR": "LDN 멀티플레이어 모드를 변경합니다.\n\nLdnMitm은 게임의 로컬 무선/로컬 플레이 기능을 LAN처럼 작동하도록 수정하여 다른 Ryujinx 인스턴스나 ldn_mitm 모듈이 설치된 해킹된 Nintendo Switch 콘솔과 로컬, 동일 네트워크 연결이 가능합니다.\n\n멀티플레이어는 모든 플레이어가 동일한 게임 버전을 사용해야 합니다(예 : 슈퍼 스매시브라더스 얼티밋 v13.0.1은 v13.0.0에 연결할 수 없음).\n\n모르면 비활성화 상태로 두세요.",
|
||||
"no_NO": "Endre LDN flerspillermodus.\n\nLdnMitm vil endre lokal trådløst/lokal spillfunksjonalitet i spill som skal fungere som om den var LAN, noe som tillater lokal, samme nettverk forbindelser med andre Ryujinx instanser og hacket Nintendo Switch konsoller som har installert ldn_mitm-modulen.\n\nFlerspiller krever at alle spillerne er på samme versjon (dvs. Super Smash Bros. Ultimat v13.0.1 kan ikke koble til v13.0.0).\n\nForlat DEAKTIVERT hvis usikker.",
|
||||
"ko_KR": "LDN 멀티플레이어 모드를 변경합니다.\n\nldn_mitm은 게임의 로컬 무선/로컬 플레이 기능을 LAN처럼 작동하도록 수정하여 다른 Ryujinx 인스턴스나 ldn_mitm 모듈이 설치된 해킹된 Nintendo Switch 콘솔과 로컬, 동일 네트워크 연결이 가능합니다.\n\n멀티플레이어는 모든 플레이어가 동일한 게임 버전을 사용해야 합니다(예 : 슈퍼 스매시브라더스 얼티밋 v13.0.1은 v13.0.0에 연결할 수 없음).\n\n모르면 비활성화 상태로 두세요.",
|
||||
"no_NO": "Endre LDN flerspillermodus.\n\nldn_mitm vil endre lokal trådløst/lokal spillfunksjonalitet i spill som skal fungere som om den var LAN, noe som tillater lokal, samme nettverk forbindelser med andre Ryujinx instanser og hacket Nintendo Switch konsoller som har installert ldn_mitm-modulen.\n\nFlerspiller krever at alle spillerne er på samme versjon (dvs. Super Smash Bros. Ultimat v13.0.1 kan ikke koble til v13.0.0).\n\nForlat DEAKTIVERT hvis usikker.",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "Alterar o modo multiplayer LDN.\n\nLdnMitm modificará a funcionalidade de jogo sem fio/local nos jogos para funcionar como se fosse LAN, permitindo conexões locais, na mesma rede, com outras instâncias do Ryujinx e consoles Nintendo Switch hackeados que possuem o módulo ldn_mitm instalado.\n\nO multiplayer exige que todos os jogadores estejam na mesma versão do jogo (ex.: Super Smash Bros. Ultimate v13.0.1 não consegue se conectar à v13.0.0).\n\nDeixe DESATIVADO se estiver em dúvida.",
|
||||
"ru_RU": "Меняет многопользовательский режим LDN.\n\nLdnMitm модифицирует функциональность локальной беспроводной игры на одном устройстве в играх, позволяя играть с другими пользователями Ryujinx или взломанными консолями Nintendo Switch с установленным модулем ldn_mitm, находящимися в одной локальной сети друг с другом.\n\nМногопользовательская игра требует наличия у всех игроков одной и той же версии игры (т.е. Super Smash Bros. Ultimate v13.0.1 не может подключиться к v13.0.0).\n\nРекомендуется оставить выключенным.",
|
||||
"sv_SE": "Ändra LDN-flerspelarläge\n\nLdnMitm kommer att ändra lokal funktionalitet för trådlös/lokalt spel att fungera som om det vore ett LAN, vilket ger stöd för anslutningar med local och same-network med andra Ryujinx-instanser och hackade Nintendo Switch-konsoller som har modulen ldn_mitm installerad.\n\nFlerspelare kräver att alla spelare har samma spelversion (t.ex. Super Smash Bros. Ultimate v13.0.1 kan inte ansluta till v13.0.0).\n\nLämna INAKTIVERAD om du är osäker.",
|
||||
"th_TH": "เปลี่ยนโหมดผู้เล่นหลายคนของ LDN\n\nLdnMitm จะปรับเปลี่ยนฟังก์ชันการเล่นแบบไร้สาย/ภายใน จะให้เกมทำงานเหมือนกับว่าเป็น LAN ช่วยให้สามารถเชื่อมต่อภายในเครือข่ายเดียวกันกับอินสแตนซ์ Ryujinx อื่น ๆ และคอนโซล Nintendo Switch ที่ถูกแฮ็กซึ่งมีโมดูล ldn_mitm ติดตั้งอยู่\n\nผู้เล่นหลายคนต้องการให้ผู้เล่นทุกคนอยู่ในเกมเวอร์ชันเดียวกัน (เช่น Super Smash Bros. Ultimate v13.0.1 ไม่สามารถเชื่อมต่อกับ v13.0.0)\n\nปล่อยให้ปิดการใช้งานหากไม่แน่ใจ",
|
||||
"pt_BR": "Alterar o modo multiplayer LDN.\n\nldn_mitm modificará a funcionalidade de jogo sem fio/local nos jogos para funcionar como se fosse LAN, permitindo conexões locais, na mesma rede, com outras instâncias do Ryujinx e consoles Nintendo Switch hackeados que possuem o módulo ldn_mitm instalado.\n\nO multiplayer exige que todos os jogadores estejam na mesma versão do jogo (ex.: Super Smash Bros. Ultimate v13.0.1 não consegue se conectar à v13.0.0).\n\nDeixe DESATIVADO se estiver em dúvida.",
|
||||
"ru_RU": "Меняет многопользовательский режим LDN.\n\nldn_mitm модифицирует функциональность локальной беспроводной игры на одном устройстве в играх, позволяя играть с другими пользователями Ryujinx или взломанными консолями Nintendo Switch с установленным модулем ldn_mitm, находящимися в одной локальной сети друг с другом.\n\nМногопользовательская игра требует наличия у всех игроков одной и той же версии игры (т.е. Super Smash Bros. Ultimate v13.0.1 не может подключиться к v13.0.0).\n\nРекомендуется оставить выключенным.",
|
||||
"sv_SE": "Ändra LDN-flerspelarläge\n\nldn_mitm kommer att ändra lokal funktionalitet för trådlös/lokalt spel att fungera som om det vore ett LAN, vilket ger stöd för anslutningar med local och same-network med andra Ryujinx-instanser och hackade Nintendo Switch-konsoller som har modulen ldn_mitm installerad.\n\nFlerspelare kräver att alla spelare har samma spelversion (t.ex. Super Smash Bros. Ultimate v13.0.1 kan inte ansluta till v13.0.0).\n\nLämna INAKTIVERAD om du är osäker.",
|
||||
"th_TH": "เปลี่ยนโหมดผู้เล่นหลายคนของ LDN\n\nldn_mitm จะปรับเปลี่ยนฟังก์ชันการเล่นแบบไร้สาย/ภายใน จะให้เกมทำงานเหมือนกับว่าเป็น LAN ช่วยให้สามารถเชื่อมต่อภายในเครือข่ายเดียวกันกับอินสแตนซ์ Ryujinx อื่น ๆ และคอนโซล Nintendo Switch ที่ถูกแฮ็กซึ่งมีโมดูล ldn_mitm ติดตั้งอยู่\n\nผู้เล่นหลายคนต้องการให้ผู้เล่นทุกคนอยู่ในเกมเวอร์ชันเดียวกัน (เช่น Super Smash Bros. Ultimate v13.0.1 ไม่สามารถเชื่อมต่อกับ v13.0.0)\n\nปล่อยให้ปิดการใช้งานหากไม่แน่ใจ",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "Змінити LDN мультиплеєру.\n\nLdnMitm змінить функціонал бездротової/локальної гри в іграх, щоб вони працювали так, ніби це LAN, що дозволяє локальні підключення в тій самій мережі з іншими екземплярами Ryujinx та хакнутими консолями Nintendo Switch, які мають встановлений модуль ldn_mitm.\n\nМультиплеєр вимагає, щоб усі гравці були на одній і тій же версії гри (наприклад Super Smash Bros. Ultimate v13.0.1 не зможе під'єднатися до v13.0.0).\n\nЗалиште на \"Вимкнено\", якщо не впевнені.",
|
||||
"uk_UA": "Змінити LDN мультиплеєру.\n\nldn_mitm змінить функціонал бездротової/локальної гри в іграх, щоб вони працювали так, ніби це LAN, що дозволяє локальні підключення в тій самій мережі з іншими екземплярами Ryujinx та хакнутими консолями Nintendo Switch, які мають встановлений модуль ldn_mitm.\n\nМультиплеєр вимагає, щоб усі гравці були на одній і тій же версії гри (наприклад Super Smash Bros. Ultimate v13.0.1 не зможе під'єднатися до v13.0.0).\n\nЗалиште на \"Вимкнено\", якщо не впевнені.",
|
||||
"zh_CN": "修改 LDN 多人联机游玩模式。\n\nldn_mitm 联机插件将修改游戏中的本地无线和本地游玩功能,使其表现得像局域网一样,允许和其他安装了 ldn_mitm 插件的 Ryujinx 模拟器和破解的任天堂 Switch 主机在同一网络下进行本地连接,实现多人联机游玩。\n\n多人联机游玩要求所有玩家必须运行相同的游戏版本(例如,游戏版本 v13.0.1 无法与 v13.0.0 联机)。\n\n如果不确定,请保持为“禁用”。",
|
||||
"zh_TW": "變更 LDN 多人遊戲模式。\n\nLdnMitm 將修改遊戲中的本機無線/本機遊戲功能,使其如同區域網路一樣執行,允許與其他安裝了 ldn_mitm 模組的 Ryujinx 實例和已破解的 Nintendo Switch 遊戲機進行本機同網路連線。\n\n多人遊戲要求所有玩家使用相同的遊戲版本 (例如,Super Smash Bros. Ultimate v13.0.1 無法連接 v13.0.0)。\n\n如果不確定,請保持 Disabled (停用) 狀態。"
|
||||
"zh_TW": "變更 LDN 多人遊戲模式。\n\nldn_mitm 將修改遊戲中的本機無線/本機遊戲功能,使其如同區域網路一樣執行,允許與其他安裝了 ldn_mitm 模組的 Ryujinx 實例和已破解的 Nintendo Switch 遊戲機進行本機同網路連線。\n\n多人遊戲要求所有玩家使用相同的遊戲版本 (例如,Super Smash Bros. Ultimate v13.0.1 無法連接 v13.0.0)。\n\n如果不確定,請保持 Disabled (停用) 狀態。"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -22800,7 +22800,7 @@
|
||||
"el_GR": "",
|
||||
"en_US": "Generates a new passphrase, which can be shared with other players.",
|
||||
"es_ES": "Genera una nueva frase de contraseña, que puede ser compartida con otros jugadores.",
|
||||
"fr_FR": "Génére un nouveau mot de passe, qui peut être partagé avec les autres.",
|
||||
"fr_FR": "Génère un nouveau mot de passe, qui peut être partagé avec les autres.",
|
||||
"he_IL": "",
|
||||
"it_IT": "Genera una nuova passphrase, che può essere condivisa con altri giocatori.",
|
||||
"ja_JP": "",
|
||||
@@ -24841,6 +24841,781 @@
|
||||
"zh_CN": "如果您在设置中有某些 LDN 口令则可加入此游戏。",
|
||||
"zh_TW": "你只能加入與 LDN 網路密碼片語 (passphrase) 設定相同的遊戲。"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardOpen",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Setup Wizard",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardActionBack",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Back",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardActionNext",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Next",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFirstPageTitle",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Welcome to Ryubing!",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFirstPageContent",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Ryubing is a fork of the discontinued Nintendo Switch emulator, Ryujinx.\n\nThis setup wizard will guide you through the necessary steps needed for Ryubing to play your Switch games on PC.",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFirstPageAction",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Start Setup",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardKeysPageTitle",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Key Files",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardKeysPageDescription",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Please select the folder containing your prod/title .keys files:",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardKeysPageFolderPopupTitle",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Please select the folder containing your prod/title .keys files",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardKeysPageHelpText",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Not sure how to get your keys?",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardKeysPageSkipText",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Skipped setting up keys as you already have a valid key installation and did not choose a folder to install from.\nClick '{0}' if you wish to reinstall your keys.",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFirmwarePageTitle",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Switch Firmware",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFirmwarePageDescription",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Please select the folder or .zip/.xci containing your dumped Nintendo Switch firmware:",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFirmwarePageFolderPopupTitle",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Please select the folder containing your dumped & extracted Switch firmware.",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFirmwarePageFilePopupTitle",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Please select the file containing your dumped Switch firmware.",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFirmwarePageFileBrowse",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Select .zip or .xci",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFirmwarePageFolderBrowse",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Select Extracted Folder",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFirmwarePageInstallSuccessNotificationTitle",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Firmware installed",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFirmwarePageInstallSuccessNotificationText",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Installed firmware version {0}.",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFirmwarePageInstallFailNotificationTitle",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Firmware not installed",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFirmwarePageInstallFailNotificationText",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "It seems some error occurred when trying to install the firmware at path '{0}'.\nDid that folder contain a firmware dump?",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFirmwarePageHelpText",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Not sure how to get your firmware off of your Switch?",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFirmwarePageSkipText",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Skipped setting up firmware as you already have a valid firmware installation and did not choose a folder or file to install from.\nClick '{0}' if you wish to overwrite your firmware.",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardGameDirsPageTitle",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Game, Update, and DLC Paths",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardGameDirsPageDescription",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "{0} can be pointed at any number of folders to look for your games, updates, and DLC content.\nAt least one folder must be specified in game directories before continuing.",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardGameDirsPageNoFoldersSelectedError",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "At least one folder for games must be selected; otherwise the UI will be empty.",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardGameDirsPageHelpText",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Not sure how to get your games, updates, and/or DLC onto your PC?",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFinalPageTitle",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Setup Complete",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFinalPageDescription",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Your installation of Ryubing (aka Ryujinx) has been completed.\n\nIf you require assistance, feel free to join our Discord server and ask for help,\nafter verifying your possession of a modded Nintendo Switch.",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFinalPageAction",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Finish",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardHelpLinkButton",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Click here to view a guide.",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
BIN
distribution/macos/Assets.car
Normal file
BIN
distribution/macos/Assets.car
Normal file
Binary file not shown.
@@ -10,6 +10,8 @@
|
||||
<string>Ryujinx</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>Ryujinx.icns</string>
|
||||
<key>CFBundleIconName</key>
|
||||
<string>Ryujinx</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
@@ -40,7 +42,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.2</string>
|
||||
<string>1.3</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
||||
@@ -25,6 +25,7 @@ cp "$PUBLISH_DIRECTORY"/*.dylib "$APP_BUNDLE_DIRECTORY/Contents/Frameworks"
|
||||
cp Info.plist "$APP_BUNDLE_DIRECTORY/Contents"
|
||||
cp Ryujinx.icns "$APP_BUNDLE_DIRECTORY/Contents/Resources/Ryujinx.icns"
|
||||
cp updater.sh "$APP_BUNDLE_DIRECTORY/Contents/Resources/updater.sh"
|
||||
cp Assets.car "$APP_BUNDLE_DIRECTORY/Contents/Resources/Assets.car"
|
||||
cp -r "$PUBLISH_DIRECTORY/THIRDPARTY.md" "$APP_BUNDLE_DIRECTORY/Contents/Resources"
|
||||
|
||||
echo -n "APPL????" > "$APP_BUNDLE_DIRECTORY/Contents/PkgInfo"
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$#" -lt 8 ]; then
|
||||
echo "usage <BASE_DIR> <TEMP_DIRECTORY> <OUTPUT_DIRECTORY> <ENTITLEMENTS_FILE_PATH> <VERSION> <SOURCE_REVISION_ID> <CONFIGURATION> <CANARY>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$1"
|
||||
mkdir -p "$2"
|
||||
mkdir -p "$3"
|
||||
|
||||
BASE_DIR=$(readlink -f "$1")
|
||||
TEMP_DIRECTORY=$(readlink -f "$2")
|
||||
OUTPUT_DIRECTORY=$(readlink -f "$3")
|
||||
ENTITLEMENTS_FILE_PATH=$(readlink -f "$4")
|
||||
VERSION=$5
|
||||
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
|
||||
RELEASE_TAR_FILE_NAME=nogui-ryujinx-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.tar
|
||||
else
|
||||
RELEASE_TAR_FILE_NAME=nogui-ryujinx-$VERSION-macos_universal.tar
|
||||
fi
|
||||
|
||||
ARM64_OUTPUT="$TEMP_DIRECTORY/publish_arm64"
|
||||
X64_OUTPUT="$TEMP_DIRECTORY/publish_x64"
|
||||
UNIVERSAL_OUTPUT="$OUTPUT_DIRECTORY/publish"
|
||||
EXECUTABLE_SUB_PATH=Ryujinx.Headless.SDL3
|
||||
|
||||
rm -rf "$TEMP_DIRECTORY"
|
||||
mkdir -p "$TEMP_DIRECTORY"
|
||||
|
||||
DOTNET_COMMON_ARGS=(-p:DebugType=embedded -p:Version="$VERSION" -p:SourceRevisionId="$SOURCE_REVISION_ID" --self-contained true $EXTRA_ARGS)
|
||||
|
||||
dotnet restore
|
||||
dotnet build -c "$CONFIGURATION" src/Ryujinx.Headless.SDL3
|
||||
dotnet publish -c "$CONFIGURATION" -r osx-arm64 -o "$TEMP_DIRECTORY/publish_arm64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx.Headless.SDL3
|
||||
dotnet publish -c "$CONFIGURATION" -r osx-x64 -o "$TEMP_DIRECTORY/publish_x64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx.Headless.SDL3
|
||||
|
||||
# Get rid of the support library for ARMeilleure for x64 (that's only for arm64)
|
||||
rm -rf "$TEMP_DIRECTORY/publish_x64/libarmeilleure-jitsupport.dylib"
|
||||
|
||||
# Get rid of libsoundio from arm64 builds as we don't have a arm64 variant
|
||||
# TODO: remove this once done
|
||||
rm -rf "$TEMP_DIRECTORY/publish_arm64/libsoundio.dylib"
|
||||
|
||||
rm -rf "$OUTPUT_DIRECTORY"
|
||||
mkdir -p "$OUTPUT_DIRECTORY"
|
||||
|
||||
# Let's copy one of the two different outputs and remove the executable
|
||||
cp -R "$ARM64_OUTPUT/" "$UNIVERSAL_OUTPUT"
|
||||
rm "$UNIVERSAL_OUTPUT/$EXECUTABLE_SUB_PATH"
|
||||
|
||||
# Make its libraries universal
|
||||
python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_OUTPUT" "$X64_OUTPUT" "$UNIVERSAL_OUTPUT" "**/*.dylib"
|
||||
|
||||
if ! [ -x "$(command -v lipo)" ];
|
||||
then
|
||||
if ! [ -x "$(command -v llvm-lipo-17)" ];
|
||||
then
|
||||
LIPO=llvm-lipo
|
||||
else
|
||||
LIPO=llvm-lipo-17
|
||||
fi
|
||||
else
|
||||
LIPO=lipo
|
||||
fi
|
||||
|
||||
# Make the executable universal
|
||||
$LIPO "$ARM64_OUTPUT/$EXECUTABLE_SUB_PATH" "$X64_OUTPUT/$EXECUTABLE_SUB_PATH" -output "$UNIVERSAL_OUTPUT/$EXECUTABLE_SUB_PATH" -create
|
||||
|
||||
# Now sign it
|
||||
if ! [ -x "$(command -v codesign)" ];
|
||||
then
|
||||
if ! [ -x "$(command -v rcodesign)" ];
|
||||
then
|
||||
echo "Cannot find rcodesign on your system, please install rcodesign."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# NOTE: Currently require https://github.com/indygreg/apple-platform-rs/pull/44 to work on other OSes.
|
||||
# cargo install --git "https://github.com/marysaka/apple-platform-rs" --branch "fix/adhoc-app-bundle" apple-codesign --bin "rcodesign"
|
||||
echo "Using rcodesign for ad-hoc signing"
|
||||
for FILE in "$UNIVERSAL_OUTPUT"/*; do
|
||||
if [[ $(file "$FILE") == *"Mach-O"* ]]; then
|
||||
rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$FILE"
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo "Using codesign for ad-hoc signing"
|
||||
for FILE in "$UNIVERSAL_OUTPUT"/*; do
|
||||
if [[ $(file "$FILE") == *"Mach-O"* ]]; then
|
||||
codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f -s - "$FILE"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo "Creating archive"
|
||||
pushd "$OUTPUT_DIRECTORY"
|
||||
tar --exclude "publish/Ryujinx.Headless.SDL3" -cvf "$RELEASE_TAR_FILE_NAME" publish 1> /dev/null
|
||||
python3 "$BASE_DIR/distribution/misc/add_tar_exec.py" "$RELEASE_TAR_FILE_NAME" "publish/Ryujinx.Headless.SDL3" "publish/Ryujinx.Headless.SDL3"
|
||||
gzip -9 < "$RELEASE_TAR_FILE_NAME" > "$RELEASE_TAR_FILE_NAME.gz"
|
||||
rm "$RELEASE_TAR_FILE_NAME"
|
||||
popd
|
||||
|
||||
echo "Done"
|
||||
@@ -2275,12 +2275,12 @@
|
||||
010018E011D92000,"Pokémon™ Shining Pearl",gpu;ldn-works,ingame,2024-08-28 13:26:35
|
||||
010015F008C54000,"Pokémon™ HOME",Needs Update;crash;services,menus,2020-12-06 06:01:51
|
||||
01001F5010DFA000,"Pokémon™ Legends: Arceus",gpu;Needs Update;ldn-works,ingame,2024-09-19 10:02:02
|
||||
0100F43008C44000,"Pokémon™ Legends: Z-A",gpu;crash;ldn-works,ingame,2025-11-16 00:30:00
|
||||
01005D100807A000,"Pokémon™ Quest",,playable,2022-02-22 16:12:32
|
||||
0100A3D008C5C000,"Pokémon™ Scarlet",gpu;nvdec;ldn-works;amd-vendor-bug,ingame,2023-12-14 13:18:29
|
||||
01008F6008C5E000,"Pokémon™ Violet",gpu;nvdec;ldn-works;amd-vendor-bug;mac-bug,ingame,2024-07-30 02:51:48
|
||||
0100187003A36000,"Pokémon™: Let’s Go, Eevee!",crash;nvdec;online-broken;ldn-broken,ingame,2024-06-01 15:03:04
|
||||
010003F003A34000,"Pokémon™: Let’s Go, Pikachu!",crash;nvdec;online-broken;ldn-broken,ingame,2024-03-15 07:55:41
|
||||
0100F43008C44000,"Pokémon Legends: Z-A",gpu;crash;ldn-broken,ingame,2025-10-16 19:13:00
|
||||
0100B3F000BE2000,"Pokkén Tournament™ DX",nvdec;ldn-works;opengl-backend-bug;LAN;amd-vendor-bug;intel-vendor-bug,playable,2024-07-18 23:11:08
|
||||
010030D005AE6000,"Pokkén Tournament™ DX Demo",demo;opengl-backend-bug,playable,2022-08-10 12:03:19
|
||||
0100A3500B4EC000,"Polandball: Can Into Space",,playable,2020-06-25 15:13:26
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "9.0.100",
|
||||
"version": "10.0.100",
|
||||
"rollForward": "latestFeature"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -973,7 +973,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
uint instruction;
|
||||
int scale;
|
||||
|
||||
if (type.IsInteger())
|
||||
if (type.IsInteger)
|
||||
{
|
||||
instruction = intInst;
|
||||
|
||||
@@ -1009,7 +1009,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
uint instruction;
|
||||
|
||||
if (type.IsInteger())
|
||||
if (type.IsInteger)
|
||||
{
|
||||
instruction = intInst;
|
||||
|
||||
|
||||
@@ -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));
|
||||
@@ -468,7 +468,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
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);
|
||||
}
|
||||
@@ -485,7 +485,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1549,7 +1549,7 @@ 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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
}
|
||||
else if (otherCompType == Comparison.Equal)
|
||||
{
|
||||
propCompType = compType.Invert();
|
||||
propCompType = compType.Inverse;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
@@ -792,9 +792,9 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
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,12 +1713,12 @@ 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;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
break;
|
||||
|
||||
case Instruction.Negate:
|
||||
if (!node.GetSource(0).Type.IsInteger())
|
||||
if (!node.GetSource(0).Type.IsInteger)
|
||||
{
|
||||
GenerateNegate(block.Operations, node);
|
||||
}
|
||||
@@ -159,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:
|
||||
@@ -208,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);
|
||||
|
||||
@@ -298,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);
|
||||
|
||||
@@ -466,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;
|
||||
|
||||
@@ -654,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:
|
||||
@@ -672,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:
|
||||
|
||||
@@ -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))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.LoadFromContext();
|
||||
|
||||
context.Return(Const(op.Address));
|
||||
InstEmitFlowHelper.EmitReturn(context, Const(op.Address));
|
||||
}
|
||||
|
||||
public static void Svc(ArmEmitterContext context)
|
||||
@@ -49,7 +49,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.LoadFromContext();
|
||||
|
||||
context.Return(Const(op.Address));
|
||||
InstEmitFlowHelper.EmitReturn(context, Const(op.Address));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.LoadFromContext();
|
||||
|
||||
context.Return(Const(context.CurrOp.Address));
|
||||
InstEmitFlowHelper.EmitReturn(context, Const(context.CurrOp.Address));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCodeBReg op = (OpCodeBReg)context.CurrOp;
|
||||
|
||||
context.Return(GetIntOrZR(context, op.Rn));
|
||||
EmitReturn(context, GetIntOrZR(context, op.Rn));
|
||||
}
|
||||
|
||||
public static void Tbnz(ArmEmitterContext context) => EmitTb(context, onNotZero: true);
|
||||
|
||||
@@ -13,6 +13,10 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
static class InstEmitFlowHelper
|
||||
{
|
||||
// How many calls we can have in our call stack before we give up and return to the dispatcher.
|
||||
// This prevents stack overflows caused by deep recursive calls.
|
||||
private const int MaxCallDepth = 200;
|
||||
|
||||
public static void EmitCondBranch(ArmEmitterContext context, Operand target, Condition cond)
|
||||
{
|
||||
if (cond != Condition.Al)
|
||||
@@ -182,12 +186,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
if (isReturn || context.IsSingleStep)
|
||||
{
|
||||
if (target.Type == OperandType.I32)
|
||||
{
|
||||
target = context.ZeroExtend32(OperandType.I64, target);
|
||||
}
|
||||
|
||||
context.Return(target);
|
||||
EmitReturn(context, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -195,6 +194,19 @@ namespace ARMeilleure.Instructions
|
||||
}
|
||||
}
|
||||
|
||||
public static void EmitReturn(ArmEmitterContext context, Operand target)
|
||||
{
|
||||
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
||||
DecreaseCallDepth(context, nativeContext);
|
||||
|
||||
if (target.Type == OperandType.I32)
|
||||
{
|
||||
target = context.ZeroExtend32(OperandType.I64, target);
|
||||
}
|
||||
|
||||
context.Return(target);
|
||||
}
|
||||
|
||||
private static void EmitTableBranch(ArmEmitterContext context, Operand guestAddress, bool isJump)
|
||||
{
|
||||
context.StoreToContext();
|
||||
@@ -257,6 +269,8 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
if (isJump)
|
||||
{
|
||||
DecreaseCallDepth(context, nativeContext);
|
||||
|
||||
context.Tailcall(hostAddress, nativeContext);
|
||||
}
|
||||
else
|
||||
@@ -278,8 +292,42 @@ namespace ARMeilleure.Instructions
|
||||
Operand lblContinue = context.GetLabel(nextAddr.Value);
|
||||
context.BranchIf(lblContinue, returnAddress, nextAddr, Comparison.Equal, BasicBlockFrequency.Cold);
|
||||
|
||||
DecreaseCallDepth(context, nativeContext);
|
||||
|
||||
context.Return(returnAddress);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EmitCallDepthCheckAndIncrement(EmitterContext context, Operand guestAddress)
|
||||
{
|
||||
if (!Optimizations.EnableDeepCallRecursionProtection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
||||
Operand callDepthAddr = context.Add(nativeContext, Const((ulong)NativeContext.GetCallDepthOffset()));
|
||||
Operand currentCallDepth = context.Load(OperandType.I32, callDepthAddr);
|
||||
Operand lblDoCall = Label();
|
||||
|
||||
context.BranchIf(lblDoCall, currentCallDepth, Const(MaxCallDepth), Comparison.LessUI);
|
||||
context.Store(callDepthAddr, context.Subtract(currentCallDepth, Const(1)));
|
||||
context.Return(guestAddress);
|
||||
|
||||
context.MarkLabel(lblDoCall);
|
||||
context.Store(callDepthAddr, context.Add(currentCallDepth, Const(1)));
|
||||
}
|
||||
|
||||
private static void DecreaseCallDepth(EmitterContext context, Operand nativeContext)
|
||||
{
|
||||
if (!Optimizations.EnableDeepCallRecursionProtection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Operand callDepthAddr = context.Add(nativeContext, Const((ulong)NativeContext.GetCallDepthOffset()));
|
||||
Operand currentCallDepth = context.Load(OperandType.I32, callDepthAddr);
|
||||
context.Store(callDepthAddr, context.Subtract(currentCallDepth, Const(1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ 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(crc.Type.IsInteger && value.Type.IsInteger);
|
||||
Debug.Assert(size is >= 0 and < 4);
|
||||
Debug.Assert((size < 3) || (value.Type == OperandType.I64));
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,48 +14,38 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
|
||||
static class OperandTypeExtensions
|
||||
{
|
||||
public static bool IsInteger(this OperandType type)
|
||||
extension(OperandType type)
|
||||
{
|
||||
return type is OperandType.I32 or
|
||||
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 is MemoryManagerType.HostMapped or MemoryManagerType.HostMappedUnsafe;
|
||||
}
|
||||
|
||||
public static bool IsHostTracked(this MemoryManagerType type)
|
||||
{
|
||||
return type is MemoryManagerType.HostTracked or 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace ARMeilleure
|
||||
public static bool AllowLcqInFunctionTable { get; set; } = true;
|
||||
public static bool UseUnmanagedDispatchLoop { get; set; } = true;
|
||||
public static bool EnableDebugging { get; set; } = false;
|
||||
public static bool EnableDeepCallRecursionProtection { get; set; } = true;
|
||||
|
||||
public static bool UseAdvSimdIfAvailable { get; set; } = true;
|
||||
public static bool UseArm64AesIfAvailable { get; set; } = true;
|
||||
|
||||
@@ -134,6 +134,11 @@ namespace ARMeilleure.State
|
||||
public bool GetFPstateFlag(FPState flag) => _nativeContext.GetFPStateFlag(flag);
|
||||
public void SetFPstateFlag(FPState flag, bool value) => _nativeContext.SetFPStateFlag(flag, value);
|
||||
|
||||
internal void ResetCallDepth()
|
||||
{
|
||||
_nativeContext.ResetCallDepth();
|
||||
}
|
||||
|
||||
internal void CheckInterrupt()
|
||||
{
|
||||
if (Interrupted)
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace ARMeilleure.State
|
||||
public ulong ExclusiveValueHigh;
|
||||
public int Running;
|
||||
public long Tpidr2El0;
|
||||
public int CallDepth;
|
||||
|
||||
/// <summary>
|
||||
/// Precise PC value used for debugging.
|
||||
@@ -199,6 +200,8 @@ namespace ARMeilleure.State
|
||||
public bool GetRunning() => GetStorage().Running != 0;
|
||||
public void SetRunning(bool value) => GetStorage().Running = value ? 1 : 0;
|
||||
|
||||
public void ResetCallDepth() => GetStorage().CallDepth = 0;
|
||||
|
||||
public unsafe static int GetRegisterOffset(Register reg)
|
||||
{
|
||||
if (reg.Type == RegisterType.Integer)
|
||||
@@ -284,6 +287,11 @@ namespace ARMeilleure.State
|
||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.DebugPrecisePc);
|
||||
}
|
||||
|
||||
public static int GetCallDepthOffset()
|
||||
{
|
||||
return StorageOffset(ref _dummyStorage, ref _dummyStorage.CallDepth);
|
||||
}
|
||||
|
||||
private static int StorageOffset<T>(ref NativeCtxStorage storage, ref T target)
|
||||
{
|
||||
return (int)Unsafe.ByteOffset(ref Unsafe.As<NativeCtxStorage, T>(ref storage), ref target);
|
||||
|
||||
@@ -361,10 +361,7 @@ namespace ARMeilleure.Translation
|
||||
|
||||
IntervalTreeNode<TK, TV> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
|
||||
|
||||
if (tmp != null)
|
||||
{
|
||||
tmp.Parent = ParentOf(replacementNode);
|
||||
}
|
||||
tmp?.Parent = ParentOf(replacementNode);
|
||||
|
||||
if (ParentOf(replacementNode) == null)
|
||||
{
|
||||
@@ -582,10 +579,7 @@ namespace ARMeilleure.Translation
|
||||
{
|
||||
IntervalTreeNode<TK, TV> right = RightOf(node);
|
||||
node.Right = LeftOf(right);
|
||||
if (node.Right != null)
|
||||
{
|
||||
node.Right.Parent = node;
|
||||
}
|
||||
node.Right?.Parent = node;
|
||||
|
||||
IntervalTreeNode<TK, TV> nodeParent = ParentOf(node);
|
||||
right.Parent = nodeParent;
|
||||
@@ -615,10 +609,7 @@ namespace ARMeilleure.Translation
|
||||
{
|
||||
IntervalTreeNode<TK, TV> left = LeftOf(node);
|
||||
node.Left = RightOf(left);
|
||||
if (node.Left != null)
|
||||
{
|
||||
node.Left.Parent = node;
|
||||
}
|
||||
node.Left?.Parent = node;
|
||||
|
||||
IntervalTreeNode<TK, TV> nodeParent = ParentOf(node);
|
||||
left.Parent = nodeParent;
|
||||
@@ -667,10 +658,7 @@ namespace ARMeilleure.Translation
|
||||
/// <param name="color">Color (Boolean)</param>
|
||||
private static void SetColor(IntervalTreeNode<TK, TV> node, bool color)
|
||||
{
|
||||
if (node != null)
|
||||
{
|
||||
node.Color = color;
|
||||
}
|
||||
node?.Color = color;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||
|
||||
private const uint InternalVersion = 7009; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
private const uint InternalVersion = 7010; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
|
||||
private const string ActualDir = "0";
|
||||
private const string BackupDir = "1";
|
||||
|
||||
@@ -186,6 +186,7 @@ namespace ARMeilleure.Translation
|
||||
|
||||
Statistics.StartTimer();
|
||||
|
||||
context.ResetCallDepth();
|
||||
ulong nextAddr = func.Execute(Stubs.ContextWrapper, context);
|
||||
|
||||
Statistics.StopTimer(address);
|
||||
@@ -260,6 +261,7 @@ namespace ARMeilleure.Translation
|
||||
|
||||
Logger.StartPass(PassName.Translation);
|
||||
|
||||
InstEmitFlowHelper.EmitCallDepthCheckAndIncrement(context, Const(address));
|
||||
EmitSynchronization(context);
|
||||
|
||||
if (blocks[0].Address != address)
|
||||
@@ -412,7 +414,7 @@ namespace ARMeilleure.Translation
|
||||
{
|
||||
context.SyncQcFlag();
|
||||
|
||||
if (block.Branch != null && !block.Branch.Exit && block.Branch.Address <= block.Address)
|
||||
if (block.Branch is { Exit: false } && block.Branch.Address <= block.Address)
|
||||
{
|
||||
EmitSynchronization(context);
|
||||
}
|
||||
@@ -429,14 +431,14 @@ namespace ARMeilleure.Translation
|
||||
{
|
||||
lblPredicateSkip = Label();
|
||||
|
||||
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, context.CurrentIfThenBlockCond.Invert());
|
||||
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, context.CurrentIfThenBlockCond.Inverse);
|
||||
}
|
||||
|
||||
if (opCode is OpCode32 op && op.Cond < Condition.Al)
|
||||
if (opCode is OpCode32 { Cond: < Condition.Al } op)
|
||||
{
|
||||
lblPredicateSkip = Label();
|
||||
|
||||
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, op.Cond.Invert());
|
||||
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, op.Cond.Inverse);
|
||||
}
|
||||
|
||||
if (opCode.Instruction.Emitter != null)
|
||||
|
||||
@@ -262,10 +262,18 @@ namespace ARMeilleure.Translation
|
||||
|
||||
Operand runningAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetRunningOffset()));
|
||||
Operand dispatchAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset()));
|
||||
Operand callDepthAddress = context.Add(nativeContext, Const((ulong)NativeContext.GetCallDepthOffset()));
|
||||
|
||||
EmitSyncFpContext(context, nativeContext, true);
|
||||
|
||||
context.MarkLabel(beginLbl);
|
||||
|
||||
if (Optimizations.EnableDeepCallRecursionProtection)
|
||||
{
|
||||
// Reset the call depth counter, since this is our first guest function call.
|
||||
context.Store(callDepthAddress, Const(0));
|
||||
}
|
||||
|
||||
context.Store(dispatchAddress, guestAddress);
|
||||
context.Copy(guestAddress, context.Call(Const((ulong)DispatchStub), OperandType.I64, nativeContext));
|
||||
context.BranchIfFalse(endLbl, guestAddress);
|
||||
|
||||
@@ -58,16 +58,16 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||
switch (realSampleFormat)
|
||||
{
|
||||
case SampleFormat.PcmInt8:
|
||||
PcmHelper.ConvertSampleToPcm8(MemoryMarshal.Cast<byte, sbyte>(convertedSamples), samples);
|
||||
PcmHelper.ConvertSampleToPcm8(MemoryMarshal.Cast<byte, sbyte>(new Span<byte>(convertedSamples)), samples);
|
||||
break;
|
||||
case SampleFormat.PcmInt24:
|
||||
PcmHelper.ConvertSampleToPcm24(convertedSamples, samples);
|
||||
break;
|
||||
case SampleFormat.PcmInt32:
|
||||
PcmHelper.ConvertSampleToPcm32(MemoryMarshal.Cast<byte, int>(convertedSamples), samples);
|
||||
PcmHelper.ConvertSampleToPcm32(MemoryMarshal.Cast<byte, int>(new Span<byte>(convertedSamples)), samples);
|
||||
break;
|
||||
case SampleFormat.PcmFloat:
|
||||
PcmHelper.ConvertSampleToPcmFloat(MemoryMarshal.Cast<byte, float>(convertedSamples), samples);
|
||||
PcmHelper.ConvertSampleToPcmFloat(MemoryMarshal.Cast<byte, float>(new Span<byte>(convertedSamples)), samples);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException($"Sample format conversion from {_userSampleFormat} to {realSampleFormat} not implemented.");
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Ryujinx.Audio.Integration
|
||||
|
||||
public void AppendBuffer(ReadOnlySpan<short> data, uint channelCount)
|
||||
{
|
||||
data.CopyTo(MemoryMarshal.Cast<byte, short>(_buffer));
|
||||
data.CopyTo(MemoryMarshal.Cast<byte, short>(new Span<byte>(_buffer)));
|
||||
|
||||
_session.QueueBuffer(new AudioBuffer
|
||||
{
|
||||
|
||||
@@ -92,6 +92,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
}
|
||||
|
||||
short[] outputBuffer = ArrayPool<short>.Shared.Rent((int)inputCount * SampleCount);
|
||||
Array.Fill(outputBuffer, (short)0, 0, (int)inputCount * SampleCount);
|
||||
|
||||
for (int i = 0; i < bufferCount; i++)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,11 @@ namespace Ryujinx.Audio.Renderer.Parameter.Effect
|
||||
/// The output channel indices that will be used by the <see cref="Dsp.AudioProcessor"/>.
|
||||
/// </summary>
|
||||
public Array6<byte> Output;
|
||||
|
||||
/// <summary>
|
||||
/// Reserved/unused.
|
||||
/// </summary>
|
||||
private readonly uint _padding;
|
||||
|
||||
/// <summary>
|
||||
/// Biquad filter numerator (b0, b1, b2).
|
||||
|
||||
@@ -91,7 +91,11 @@ namespace Ryujinx.Common
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_queue.CompleteAdding();
|
||||
try
|
||||
{
|
||||
_queue.CompleteAdding();
|
||||
} catch (ObjectDisposedException) {}
|
||||
|
||||
_cts.Cancel();
|
||||
_workerThread.Join();
|
||||
|
||||
|
||||
@@ -386,10 +386,7 @@ namespace Ryujinx.Common.Collections
|
||||
|
||||
IntervalTreeNode<TKey, TValue> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
|
||||
|
||||
if (tmp != null)
|
||||
{
|
||||
tmp.Parent = ParentOf(replacementNode);
|
||||
}
|
||||
tmp?.Parent = ParentOf(replacementNode);
|
||||
|
||||
if (ParentOf(replacementNode) == null)
|
||||
{
|
||||
|
||||
@@ -235,10 +235,7 @@ namespace Ryujinx.Common.Collections
|
||||
parent = ParentOf(element);
|
||||
color = ColorOf(element);
|
||||
|
||||
if (child != null)
|
||||
{
|
||||
child.Parent = parent;
|
||||
}
|
||||
child?.Parent = parent;
|
||||
|
||||
if (parent == null)
|
||||
{
|
||||
@@ -258,8 +255,7 @@ namespace Ryujinx.Common.Collections
|
||||
element.Right = old.Right;
|
||||
element.Parent = old.Parent;
|
||||
element.Predecessor = old.Predecessor;
|
||||
if (element.Predecessor != null)
|
||||
element.Predecessor.Successor = element;
|
||||
element.Predecessor?.Successor = element;
|
||||
|
||||
if (ParentOf(old) == null)
|
||||
{
|
||||
@@ -292,10 +288,7 @@ namespace Ryujinx.Common.Collections
|
||||
parent = ParentOf(nodeToDelete);
|
||||
color = ColorOf(nodeToDelete);
|
||||
|
||||
if (child != null)
|
||||
{
|
||||
child.Parent = parent;
|
||||
}
|
||||
child?.Parent = parent;
|
||||
|
||||
if (parent == null)
|
||||
{
|
||||
@@ -314,11 +307,9 @@ namespace Ryujinx.Common.Collections
|
||||
{
|
||||
RestoreBalanceAfterRemoval(child);
|
||||
}
|
||||
|
||||
if (old.Successor != null)
|
||||
old.Successor.Predecessor = old.Predecessor;
|
||||
if (old.Predecessor != null)
|
||||
old.Predecessor.Successor = old.Successor;
|
||||
|
||||
old.Successor?.Predecessor = old.Predecessor;
|
||||
old.Predecessor?.Successor = old.Successor;
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
@@ -250,10 +250,7 @@ namespace Ryujinx.Common.Collections
|
||||
{
|
||||
T right = RightOf(node);
|
||||
node.Right = LeftOf(right);
|
||||
if (node.Right != null)
|
||||
{
|
||||
node.Right.Parent = node;
|
||||
}
|
||||
node.Right?.Parent = node;
|
||||
|
||||
T nodeParent = ParentOf(node);
|
||||
right.Parent = nodeParent;
|
||||
@@ -281,10 +278,7 @@ namespace Ryujinx.Common.Collections
|
||||
{
|
||||
T left = LeftOf(node);
|
||||
node.Left = RightOf(left);
|
||||
if (node.Left != null)
|
||||
{
|
||||
node.Left.Parent = node;
|
||||
}
|
||||
node.Left?.Parent = node;
|
||||
|
||||
T nodeParent = ParentOf(node);
|
||||
left.Parent = nodeParent;
|
||||
@@ -329,10 +323,7 @@ namespace Ryujinx.Common.Collections
|
||||
/// <param name="color">Color (Boolean)</param>
|
||||
protected static void SetColor(T node, bool color)
|
||||
{
|
||||
if (node != null)
|
||||
{
|
||||
node.Color = color;
|
||||
}
|
||||
node?.Color = color;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -328,10 +328,7 @@ namespace Ryujinx.Common.Collections
|
||||
|
||||
Node<TKey, TValue> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
|
||||
|
||||
if (tmp != null)
|
||||
{
|
||||
tmp.Parent = ParentOf(replacementNode);
|
||||
}
|
||||
tmp?.Parent = ParentOf(replacementNode);
|
||||
|
||||
if (ParentOf(replacementNode) == null)
|
||||
{
|
||||
|
||||
@@ -31,6 +31,11 @@ namespace Ryujinx.Common.Configuration
|
||||
public static string KeysDirPath { get; private set; }
|
||||
public static string KeysDirPathUser { get; }
|
||||
|
||||
public static string GetKeysDir() =>
|
||||
Mode is LaunchMode.UserProfile && Directory.Exists(KeysDirPathUser)
|
||||
? KeysDirPathUser
|
||||
: KeysDirPath;
|
||||
|
||||
public static string LogsDirPath { get; private set; }
|
||||
|
||||
public const string DefaultNandDir = "bis";
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace Ryujinx.Common.Logging
|
||||
ServiceBsd,
|
||||
ServiceBtm,
|
||||
ServiceCaps,
|
||||
ServiceEctx,
|
||||
ServiceFatal,
|
||||
ServiceFriend,
|
||||
ServiceFs,
|
||||
|
||||
@@ -7,6 +7,9 @@ namespace Ryujinx.Common.Memory
|
||||
{
|
||||
private static readonly RecyclableMemoryStreamManager _shared = new();
|
||||
|
||||
private static readonly ObjectPool<RecyclableMemoryStream> _streamPool =
|
||||
new(() => new RecyclableMemoryStream(_shared, Guid.NewGuid(), null, 0));
|
||||
|
||||
/// <summary>
|
||||
/// We don't expose the <c>RecyclableMemoryStreamManager</c> directly because version 2.x
|
||||
/// returns them as <c>MemoryStream</c>. This Shared class is here to a) offer only the GetStream() versions we use
|
||||
@@ -19,7 +22,12 @@ namespace Ryujinx.Common.Memory
|
||||
/// </summary>
|
||||
/// <returns>A <c>RecyclableMemoryStream</c></returns>
|
||||
public static RecyclableMemoryStream GetStream()
|
||||
=> new(_shared);
|
||||
{
|
||||
RecyclableMemoryStream stream = _streamPool.Allocate();
|
||||
stream.SetLength(0);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a new <c>MemoryStream</c> object with the contents copied from the provided
|
||||
@@ -55,7 +63,8 @@ namespace Ryujinx.Common.Memory
|
||||
RecyclableMemoryStream stream = null;
|
||||
try
|
||||
{
|
||||
stream = new RecyclableMemoryStream(_shared, id, tag, buffer.Length);
|
||||
stream = _streamPool.Allocate();
|
||||
stream.SetLength(0);
|
||||
stream.Write(buffer);
|
||||
stream.Position = 0;
|
||||
return stream;
|
||||
@@ -83,7 +92,8 @@ namespace Ryujinx.Common.Memory
|
||||
RecyclableMemoryStream stream = null;
|
||||
try
|
||||
{
|
||||
stream = new RecyclableMemoryStream(_shared, id, tag, count);
|
||||
stream = _streamPool.Allocate();
|
||||
stream.SetLength(0);
|
||||
stream.Write(buffer, offset, count);
|
||||
stream.Position = 0;
|
||||
return stream;
|
||||
@@ -94,6 +104,11 @@ namespace Ryujinx.Common.Memory
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReleaseStream(RecyclableMemoryStream stream)
|
||||
{
|
||||
_streamPool.Release(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,15 @@ namespace Ryujinx.Common
|
||||
public const string SetupGuideWikiUrl =
|
||||
"https://git.ryujinx.app/ryubing/ryujinx/-/wikis/Setup-&-Configuration-Guide";
|
||||
|
||||
public const string DumpKeysWikiUrl =
|
||||
"https://git.ryujinx.app/ryubing/ryujinx/-/wikis/Dumping/Keys";
|
||||
|
||||
public const string DumpFirmwareWikiUrl =
|
||||
"https://git.ryujinx.app/ryubing/ryujinx/-/wikis/Dumping/Firmware";
|
||||
|
||||
public const string DumpContentWikiUrl =
|
||||
"https://git.ryujinx.app/ryubing/ryujinx/-/wikis/Dumping/Games,-Updates-&-DLC";
|
||||
|
||||
public const string MultiplayerWikiUrl =
|
||||
"https://git.ryujinx.app/ryubing/ryujinx/-/wikis/Multiplayer-(LDN-Local-Wireless)-Guide";
|
||||
}
|
||||
|
||||
@@ -20,5 +20,21 @@ namespace Ryujinx.Common.Utilities
|
||||
Debug.Assert(res != -1);
|
||||
}
|
||||
}
|
||||
|
||||
// "dumpable" attribute of the calling process
|
||||
private const int PR_SET_DUMPABLE = 4;
|
||||
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
private static extern int prctl(int option, int arg2);
|
||||
|
||||
public static void SetCoreDumpable(bool dumpable)
|
||||
{
|
||||
if (OperatingSystem.IsLinux())
|
||||
{
|
||||
int dumpableInt = dumpable ? 1 : 0;
|
||||
int result = prctl(PR_SET_DUMPABLE, dumpableInt);
|
||||
Debug.Assert(result == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Ryujinx.Cpu.Jit
|
||||
_functionTable = AddressTable<ulong>.CreateForArm(for64Bit, memory.Type);
|
||||
_translator = new Translator(new JitMemoryAllocator(forJit: true), memory, _functionTable);
|
||||
|
||||
if (memory.Type.IsHostMappedOrTracked())
|
||||
if (memory.Type.IsHostMappedOrTracked)
|
||||
{
|
||||
NativeSignalHandler.InitializeSignalHandler();
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
|
||||
return;
|
||||
}
|
||||
|
||||
if (_operand.Type.IsInteger())
|
||||
if (_operand.Type.IsInteger)
|
||||
{
|
||||
_registerAllocator.FreeTempGprRegister(_operand.AsInt32());
|
||||
}
|
||||
|
||||
@@ -381,7 +381,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
||||
if (currentCond != ArmCondition.Al)
|
||||
{
|
||||
instructionPointer = context.CodeWriter.InstructionPointer;
|
||||
context.Arm64Assembler.B(currentCond.Invert(), 0);
|
||||
context.Arm64Assembler.B(currentCond.Inverse, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
||||
|
||||
if (invert)
|
||||
{
|
||||
conditions[i++] = ((ArmCondition)firstCond).Invert();
|
||||
conditions[i++] = ((ArmCondition)firstCond).Inverse;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1129,7 +1129,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
||||
// We don't need to mask the address for the safe mode, since it is already naturally limited to 32-bit
|
||||
// and can never reach out of the guest address space.
|
||||
|
||||
if (mmType.IsHostTracked())
|
||||
if (mmType.IsHostTracked)
|
||||
{
|
||||
int tempRegister = regAlloc.AllocateTempGprRegister();
|
||||
|
||||
@@ -1141,7 +1141,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
||||
|
||||
regAlloc.FreeTempGprRegister(tempRegister);
|
||||
}
|
||||
else if (mmType.IsHostMapped())
|
||||
else if (mmType.IsHostMapped)
|
||||
{
|
||||
asm.Add(destination64, basePointer, guestAddress);
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64
|
||||
|
||||
InstName lastInstructionName = Instructions[^1].Name;
|
||||
|
||||
return lastInstructionName.IsCall() || lastInstructionName.IsException();
|
||||
return lastInstructionName.IsCall || lastInstructionName.IsException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1042,126 +1042,39 @@ namespace Ryujinx.Cpu.LightningJit.Arm64
|
||||
|
||||
static class InstNameExtensions
|
||||
{
|
||||
public static bool IsCall(this InstName name)
|
||||
extension(InstName name)
|
||||
{
|
||||
return name is InstName.Bl or InstName.Blr;
|
||||
}
|
||||
public bool IsCall => name is InstName.Bl or InstName.Blr;
|
||||
|
||||
public static bool IsControlFlowOrException(this InstName name)
|
||||
{
|
||||
switch (name)
|
||||
public bool IsControlFlowOrException => name is
|
||||
InstName.BUncond or InstName.BCond or InstName.Bl or InstName.Blr or InstName.Br or InstName.Brk
|
||||
or InstName.Cbnz or InstName.Cbz or InstName.Ret or InstName.Tbnz or InstName.Tbz or InstName.Svc
|
||||
or InstName.UdfPermUndef;
|
||||
|
||||
public bool IsException => name is InstName.Brk or InstName.Svc or InstName.UdfPermUndef;
|
||||
|
||||
public bool IsSystem => name switch
|
||||
{
|
||||
case InstName.BUncond:
|
||||
case InstName.BCond:
|
||||
case InstName.Bl:
|
||||
case InstName.Blr:
|
||||
case InstName.Br:
|
||||
case InstName.Brk:
|
||||
case InstName.Cbnz:
|
||||
case InstName.Cbz:
|
||||
case InstName.Ret:
|
||||
case InstName.Tbnz:
|
||||
case InstName.Tbz:
|
||||
case InstName.Svc:
|
||||
case InstName.UdfPermUndef:
|
||||
return true;
|
||||
}
|
||||
InstName.Mrs or InstName.MsrImm or InstName.MsrReg => true,
|
||||
_ => name.IsException
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
||||
public bool IsSystemOrCall => name.IsCall || name is
|
||||
InstName.Svc or InstName.Mrs or InstName.MsrImm or InstName.MsrReg
|
||||
or InstName.Sysl;
|
||||
|
||||
public static bool IsException(this InstName name)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case InstName.Brk:
|
||||
case InstName.Svc:
|
||||
case InstName.UdfPermUndef:
|
||||
return true;
|
||||
}
|
||||
public bool IsPrivileged => name is
|
||||
InstName.Dcps1 or InstName.Dcps2 or InstName.Dcps3 or InstName.Drps or InstName.Eret or InstName.Ereta
|
||||
or InstName.Hvc or InstName.MsrImm or InstName.Smc;
|
||||
|
||||
return false;
|
||||
}
|
||||
public bool IsPartialRegisterUpdateMemory => name is
|
||||
InstName.Ld1AdvsimdSnglAsNoPostIndex or InstName.Ld1AdvsimdSnglAsPostIndex
|
||||
or InstName.Ld2AdvsimdSnglAsNoPostIndex or InstName.Ld2AdvsimdSnglAsPostIndex
|
||||
or InstName.Ld3AdvsimdSnglAsNoPostIndex or InstName.Ld3AdvsimdSnglAsPostIndex
|
||||
or InstName.Ld4AdvsimdSnglAsNoPostIndex or InstName.Ld4AdvsimdSnglAsPostIndex;
|
||||
|
||||
public static bool IsSystem(this InstName name)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case InstName.Mrs:
|
||||
case InstName.MsrImm:
|
||||
case InstName.MsrReg:
|
||||
return true;
|
||||
}
|
||||
|
||||
return name.IsException();
|
||||
}
|
||||
|
||||
public static bool IsSystemOrCall(this InstName name)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case InstName.Bl:
|
||||
case InstName.Blr:
|
||||
case InstName.Svc:
|
||||
case InstName.Mrs:
|
||||
case InstName.MsrImm:
|
||||
case InstName.MsrReg:
|
||||
case InstName.Sysl:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsPrivileged(this InstName name)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case InstName.Dcps1:
|
||||
case InstName.Dcps2:
|
||||
case InstName.Dcps3:
|
||||
case InstName.Drps:
|
||||
case InstName.Eret:
|
||||
case InstName.Ereta:
|
||||
case InstName.Hvc:
|
||||
case InstName.MsrImm:
|
||||
case InstName.Smc:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsPartialRegisterUpdateMemory(this InstName name)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case InstName.Ld1AdvsimdSnglAsNoPostIndex:
|
||||
case InstName.Ld1AdvsimdSnglAsPostIndex:
|
||||
case InstName.Ld2AdvsimdSnglAsNoPostIndex:
|
||||
case InstName.Ld2AdvsimdSnglAsPostIndex:
|
||||
case InstName.Ld3AdvsimdSnglAsNoPostIndex:
|
||||
case InstName.Ld3AdvsimdSnglAsPostIndex:
|
||||
case InstName.Ld4AdvsimdSnglAsNoPostIndex:
|
||||
case InstName.Ld4AdvsimdSnglAsPostIndex:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsPrefetchMemory(this InstName name)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case InstName.PrfmImm:
|
||||
case InstName.PrfmLit:
|
||||
case InstName.PrfmReg:
|
||||
case InstName.Prfum:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
public bool IsPrefetchMemory => name is
|
||||
InstName.PrfmImm or InstName.PrfmLit or InstName.PrfmReg or InstName.Prfum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64
|
||||
|
||||
public static int CalculateMaxTemps(MemoryManagerType mmType)
|
||||
{
|
||||
return mmType.IsHostMapped() ? 1 : 2;
|
||||
return mmType.IsHostMapped ? 1 : 2;
|
||||
}
|
||||
|
||||
public static int CalculateMaxTempsInclFixed(MemoryManagerType mmType)
|
||||
|
||||
@@ -247,7 +247,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64
|
||||
}
|
||||
}
|
||||
|
||||
if (!flags.HasFlag(InstFlags.ReadRt) || name.IsPartialRegisterUpdateMemory())
|
||||
if (!flags.HasFlag(InstFlags.ReadRt) || name.IsPartialRegisterUpdateMemory)
|
||||
{
|
||||
if (flags.HasFlag(InstFlags.Rt))
|
||||
{
|
||||
@@ -281,7 +281,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64
|
||||
gprMask |= MaskFromIndex(ExtractRd(flags, encoding));
|
||||
}
|
||||
|
||||
if (!flags.HasFlag(InstFlags.ReadRt) || name.IsPartialRegisterUpdateMemory())
|
||||
if (!flags.HasFlag(InstFlags.ReadRt) || name.IsPartialRegisterUpdateMemory)
|
||||
{
|
||||
if (flags.HasFlag(InstFlags.Rt))
|
||||
{
|
||||
|
||||
@@ -364,7 +364,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
|
||||
{
|
||||
InstEmitMemory.RewriteSysInstruction(memoryManager.AddressSpaceBits, memoryManager.Type, writer, regAlloc, encoding);
|
||||
}
|
||||
else if (instInfo.Name.IsSystem())
|
||||
else if (instInfo.Name.IsSystem)
|
||||
{
|
||||
bool needsContextStoreLoad = InstEmitSystem.NeedsContextStoreLoad(instInfo.Name);
|
||||
|
||||
@@ -405,7 +405,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
|
||||
|
||||
lastInstructionEncoding = RegisterUtils.RemapRegisters(regAlloc, lastInstructionFlags, lastInstructionEncoding);
|
||||
|
||||
if (lastInstructionName.IsCall())
|
||||
if (lastInstructionName.IsCall)
|
||||
{
|
||||
context.StoreToContextBeforeCall(blockIndex, pc + 4UL);
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
|
||||
|
||||
(name, flags, AddressForm addressForm) = InstTable.GetInstNameAndFlags(encoding, cpuPreset.Version, cpuPreset.Features);
|
||||
|
||||
if (name.IsPrivileged() || (name == InstName.Sys && IsPrivilegedSys(encoding)))
|
||||
if (name.IsPrivileged || (name == InstName.Sys && IsPrivilegedSys(encoding)))
|
||||
{
|
||||
name = InstName.UdfPermUndef;
|
||||
flags = InstFlags.None;
|
||||
@@ -267,7 +267,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
|
||||
(uint instGprReadMask, uint instFpSimdReadMask) = RegisterUtils.PopulateReadMasks(name, flags, encoding);
|
||||
(uint instGprWriteMask, uint instFpSimdWriteMask) = RegisterUtils.PopulateWriteMasks(name, flags, encoding);
|
||||
|
||||
if (name.IsCall())
|
||||
if (name.IsCall)
|
||||
{
|
||||
instGprWriteMask |= 1u << RegisterUtils.LrIndex;
|
||||
}
|
||||
@@ -310,12 +310,12 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
|
||||
fpSimdUseMask |= instFpSimdReadMask | instFpSimdWriteMask;
|
||||
pStateUseMask |= instPStateReadMask | instPStateWriteMask;
|
||||
|
||||
if (name.IsSystemOrCall() && !hasHostCall)
|
||||
if (name.IsSystemOrCall && !hasHostCall)
|
||||
{
|
||||
hasHostCall = name.IsCall() || InstEmitSystem.NeedsCall(encoding);
|
||||
hasHostCall = name.IsCall || InstEmitSystem.NeedsCall(encoding);
|
||||
}
|
||||
|
||||
isControlFlow = name.IsControlFlowOrException();
|
||||
isControlFlow = name.IsControlFlowOrException;
|
||||
|
||||
RegisterUse registerUse = new(
|
||||
instGprReadMask,
|
||||
@@ -339,7 +339,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
|
||||
|
||||
useMask = new(gprUseMask, fpSimdUseMask, pStateUseMask);
|
||||
|
||||
return new(startAddress, address, insts, !isTruncated && !name.IsException(), isTruncated, isLoopEnd);
|
||||
return new(startAddress, address, insts, !isTruncated && !name.IsException, isTruncated, isLoopEnd);
|
||||
}
|
||||
|
||||
private static bool IsPrivilegedSys(uint encoding)
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
|
||||
ulong pc,
|
||||
uint encoding)
|
||||
{
|
||||
if (name.IsPrefetchMemory() && mmType == MemoryManagerType.HostTrackedUnsafe)
|
||||
if (name.IsPrefetchMemory && mmType == MemoryManagerType.HostTrackedUnsafe)
|
||||
{
|
||||
// Prefetch to invalid addresses do not cause faults, so for memory manager
|
||||
// types where we need to access the page table before doing the prefetch,
|
||||
@@ -544,7 +544,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
|
||||
{
|
||||
Operand basePointer = new(regAlloc.FixedPageTableRegister, RegisterType.Integer, OperandType.I64);
|
||||
|
||||
if (mmType.IsHostTracked())
|
||||
if (mmType.IsHostTracked)
|
||||
{
|
||||
int tempRegister = regAlloc.AllocateTempGprRegister();
|
||||
|
||||
@@ -562,7 +562,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
|
||||
|
||||
regAlloc.FreeTempGprRegister(tempRegister);
|
||||
}
|
||||
else if (mmType.IsHostMapped())
|
||||
else if (mmType.IsHostMapped)
|
||||
{
|
||||
if (mmType == MemoryManagerType.HostMapped)
|
||||
{
|
||||
|
||||
@@ -22,9 +22,9 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
||||
|
||||
static class ArmConditionExtensions
|
||||
{
|
||||
public static ArmCondition Invert(this ArmCondition condition)
|
||||
extension(ArmCondition condition)
|
||||
{
|
||||
return (ArmCondition)((int)condition ^ 1);
|
||||
public ArmCondition Inverse => (ArmCondition)((int)condition ^ 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -673,7 +673,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
||||
|
||||
public readonly void Mov(Operand rd, Operand rn)
|
||||
{
|
||||
Debug.Assert(rd.Type.IsInteger());
|
||||
Debug.Assert(rd.Type.IsInteger);
|
||||
Orr(rd, new Operand(ZrRegister, RegisterType.Integer, rd.Type), rn);
|
||||
}
|
||||
|
||||
@@ -4544,7 +4544,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
||||
uint instruction;
|
||||
int scale;
|
||||
|
||||
if (type.IsInteger())
|
||||
if (type.IsInteger)
|
||||
{
|
||||
instruction = intInst;
|
||||
|
||||
@@ -4580,7 +4580,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
||||
{
|
||||
uint instruction;
|
||||
|
||||
if (type.IsInteger())
|
||||
if (type.IsInteger)
|
||||
{
|
||||
instruction = intInst;
|
||||
|
||||
@@ -4610,7 +4610,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
||||
{
|
||||
uint instruction;
|
||||
|
||||
if (type.IsInteger())
|
||||
if (type.IsInteger)
|
||||
{
|
||||
instruction = intInst;
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
||||
int gprCalleeSavedRegsCount = BitOperations.PopCount(_gprMask);
|
||||
int fpSimdCalleeSavedRegsCount = BitOperations.PopCount(_fpSimdMask);
|
||||
|
||||
return (_hasCall ? 16 : 0) + Align16(gprCalleeSavedRegsCount * 8 + fpSimdCalleeSavedRegsCount * _fpSimdType.GetSizeInBytes());
|
||||
return (_hasCall ? 16 : 0) + Align16(gprCalleeSavedRegsCount * 8 + fpSimdCalleeSavedRegsCount * _fpSimdType.ByteSize);
|
||||
}
|
||||
|
||||
public void WritePrologue(ref Assembler asm)
|
||||
@@ -46,7 +46,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
||||
int fpSimdCalleeSavedRegsCount = BitOperations.PopCount(fpSimdMask);
|
||||
|
||||
int reservedStackSize = Align16(_reservedStackSize);
|
||||
int calleeSaveRegionSize = Align16(gprCalleeSavedRegsCount * 8 + fpSimdCalleeSavedRegsCount * _fpSimdType.GetSizeInBytes()) + reservedStackSize;
|
||||
int calleeSaveRegionSize = Align16(gprCalleeSavedRegsCount * 8 + fpSimdCalleeSavedRegsCount * _fpSimdType.ByteSize) + reservedStackSize;
|
||||
int offset = 0;
|
||||
|
||||
WritePrologueCalleeSavesPreIndexed(ref asm, ref gprMask, ref offset, calleeSaveRegionSize, OperandType.I64);
|
||||
@@ -103,7 +103,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
||||
asm.StrRiUn(Register(reg, type), Register(Assembler.SpRegister), 0);
|
||||
}
|
||||
|
||||
offset += type.GetSizeInBytes();
|
||||
offset += type.ByteSize;
|
||||
}
|
||||
|
||||
while (mask != 0)
|
||||
@@ -130,7 +130,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
||||
asm.StpRiUn(Register(reg, type), Register(reg2, type), Register(Assembler.SpRegister), 0);
|
||||
}
|
||||
|
||||
offset += type.GetSizeInBytes() * 2;
|
||||
offset += type.ByteSize * 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
||||
|
||||
bool misalignedVector = _fpSimdType == OperandType.V128 && (gprCalleeSavedRegsCount & 1) != 0;
|
||||
|
||||
int offset = gprCalleeSavedRegsCount * 8 + fpSimdCalleeSavedRegsCount * _fpSimdType.GetSizeInBytes();
|
||||
int offset = gprCalleeSavedRegsCount * 8 + fpSimdCalleeSavedRegsCount * _fpSimdType.ByteSize;
|
||||
|
||||
if (misalignedVector)
|
||||
{
|
||||
@@ -197,7 +197,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
||||
|
||||
mask &= ~(1u << reg2);
|
||||
|
||||
offset -= type.GetSizeInBytes() * 2;
|
||||
offset -= type.ByteSize * 2;
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
@@ -215,7 +215,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
|
||||
}
|
||||
else
|
||||
{
|
||||
offset -= type.GetSizeInBytes();
|
||||
offset -= type.ByteSize;
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
|
||||
@@ -14,14 +14,11 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen
|
||||
|
||||
static class OperandTypeExtensions
|
||||
{
|
||||
public static bool IsInteger(this OperandType type)
|
||||
extension(OperandType type)
|
||||
{
|
||||
return type is OperandType.I32 or OperandType.I64;
|
||||
}
|
||||
public bool IsInteger => type is OperandType.I32 or OperandType.I64;
|
||||
|
||||
public static int GetSizeInBytes(this OperandType type)
|
||||
{
|
||||
return type switch
|
||||
public int ByteSize => type switch
|
||||
{
|
||||
OperandType.FP32 => 4,
|
||||
OperandType.FP64 => 8,
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace Ryujinx.Cpu.LightningJit
|
||||
|
||||
FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub;
|
||||
|
||||
if (memory.Type.IsHostMappedOrTracked())
|
||||
if (memory.Type.IsHostMappedOrTracked)
|
||||
{
|
||||
NativeSignalHandler.InitializeSignalHandler();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user