mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-02-19 23:31:07 +00:00
Compare commits
77 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 | ||
|
|
49c70efdd5 | ||
|
|
4677b749b1 | ||
|
|
ed32cd6999 | ||
|
|
d7e2d4534a | ||
|
|
3c3e14c819 | ||
|
|
dd9ba05e36 | ||
|
|
a49822470c | ||
|
|
58be57bf73 | ||
|
|
17d5d6e65a | ||
|
|
1dac06e394 |
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -2,3 +2,4 @@
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto eol=lf
|
||||
*.json text eol=lf
|
||||
|
||||
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>
|
||||
|
||||
20
Ryujinx.sln
20
Ryujinx.sln
@@ -45,12 +45,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vic", "src
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Video", "src\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj", "{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL3", "src\Ryujinx.Audio.Backends.SDL3\Ryujinx.Audio.Backends.SDL3.csproj", "{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.OpenAL", "src\Ryujinx.Audio.Backends.OpenAL\Ryujinx.Audio.Backends.OpenAL.csproj", "{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SoundIo", "src\Ryujinx.Audio.Backends.SoundIo\Ryujinx.Audio.Backends.SoundIo.csproj", "{716364DE-B988-41A6-BAB4-327964266ECC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Input", "src\Ryujinx.Input\Ryujinx.Input.csproj", "{C16F112F-38C3-40BC-9F5F-4791112063D6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Input.SDL3", "src\Ryujinx.Input.SDL3\Ryujinx.Input.SDL3.csproj", "{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmpeg", "src\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj", "{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
|
||||
@@ -73,24 +77,19 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "s
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.SDL3.Common", "src\Ryujinx.SDL3.Common\Ryujinx.SDL3.Common.csproj", "{F6F9826A-BC58-4D78-A700-F358A66B2B06}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
.github\workflows\build.yml = .github\workflows\build.yml
|
||||
.github\workflows\canary.yml = .github\workflows\canary.yml
|
||||
Directory.Packages.props = Directory.Packages.props
|
||||
Directory.Build.props = Directory.Build.props
|
||||
.github\workflows\release.yml = .github\workflows\release.yml
|
||||
nuget.config = nuget.config
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.SDL3.Common", "src\Ryujinx.SDL3.Common\Ryujinx.SDL3.Common.csproj", "{F6F9826A-BC58-4D78-A700-F358A66B2B06}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Input.SDL3", "src\Ryujinx.Input.SDL3\Ryujinx.Input.SDL3.csproj", "{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Audio.Backends.SDL3", "src\Ryujinx.Audio.Backends.SDL3\Ryujinx.Audio.Backends.SDL3.csproj", "{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -560,11 +559,6 @@ Global
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{F6F9826A-BC58-4D78-A700-F358A66B2B06} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
||||
{D728444C-3D1F-4A0E-B4C9-5C9375D47EA3} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
||||
{988E6191-82E1-4E13-9DDB-CB9FA2FDAF29} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {110169B3-3328-4730-8AB0-BA05BEF75C1A}
|
||||
EndGlobalSection
|
||||
|
||||
1137
assets/locales.json
1137
assets/locales.json
File diff suppressed because it is too large
Load Diff
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,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user