Compare commits
49 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
9719b6a112 | ||
|
f70236f947 | ||
|
eafadf10c7 | ||
|
9b06ee7736 | ||
|
baba2c2467 | ||
|
286e5d39b2 | ||
|
dc529c1181 | ||
|
c7cf1cbc35 | ||
|
d8e487d018 | ||
|
5fdc46ac7f | ||
|
1e5b45f580 | ||
|
62585755fd | ||
|
56621615b1 | ||
|
2099a3e84b | ||
|
7d26e4ac7b | ||
|
8d41402fa6 | ||
|
5af8ce7c38 | ||
|
77c4291c34 | ||
|
6e92b7a378 | ||
|
9b852c7481 | ||
|
c40c3905e2 | ||
|
a6cd044f0f | ||
|
f5a1de6ac5 | ||
|
2aeb5b00e3 | ||
|
60ba7b71f2 | ||
|
7c1d2bbb98 | ||
|
beacf8c1c8 | ||
|
0dbe45ae37 | ||
|
2b50e52e48 | ||
|
49eadbc209 | ||
|
2df16ded9b | ||
|
e43390c723 | ||
|
5af1327068 | ||
|
88a8d1e567 | ||
|
bf77d1cab9 | ||
|
1ca0517c99 | ||
|
599d485bff | ||
|
60e16c15b6 | ||
|
2068445939 | ||
|
a4fc9f8050 | ||
|
5437d6cb13 | ||
|
7539e26144 | ||
|
1c3697b6a4 | ||
|
81f848e54f | ||
|
358a781639 | ||
|
45ce540b9b | ||
|
96bf7f8522 | ||
|
33e673ceb8 | ||
|
9c2500de5f |
24
.github/dependabot.yml
vendored
Normal file
24
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
labels:
|
||||
- "infra"
|
||||
reviewers:
|
||||
- marysaka
|
||||
commit-message:
|
||||
prefix: "ci"
|
||||
|
||||
- package-ecosystem: nuget
|
||||
directory: /
|
||||
open-pull-requests-limit: 5
|
||||
schedule:
|
||||
interval: daily
|
||||
labels:
|
||||
- "infra"
|
||||
reviewers:
|
||||
- marysaka
|
||||
commit-message:
|
||||
prefix: nuget
|
14
.github/workflows/build.yml
vendored
14
.github/workflows/build.yml
vendored
@@ -48,21 +48,21 @@ jobs:
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
RYUJINX_BASE_VERSION: "1.1.0"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-dotnet@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
- name: Ensure NuGet Source
|
||||
uses: fabriciomurta/ensure-nuget-source@v1
|
||||
- name: Get git short hash
|
||||
id: git_short_hash
|
||||
run: echo "::set-output name=result::$(git rev-parse --short "${{ github.sha }}")"
|
||||
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
- name: Clear
|
||||
run: dotnet clean && dotnet nuget locals all --clear
|
||||
- name: Build
|
||||
run: dotnet build -c "${{ matrix.configuration }}" /p:Version="${{ env.RYUJINX_BASE_VERSION }}" /p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" /p:ExtraDefineConstants=DISABLE_UPDATER
|
||||
- name: Test
|
||||
run: dotnet test -c "${{ matrix.configuration }}"
|
||||
run: dotnet test --no-build -c "${{ matrix.configuration }}"
|
||||
- name: Publish Ryujinx
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish /p:Version="${{ env.RYUJINX_BASE_VERSION }}" /p:DebugType=embedded /p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" /p:ExtraDefineConstants=DISABLE_UPDATER Ryujinx --self-contained
|
||||
if: github.event_name == 'pull_request'
|
||||
@@ -73,19 +73,19 @@ jobs:
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava /p:Version="1.0.0" /p:DebugType=embedded /p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" /p:ExtraDefineConstants=DISABLE_UPDATER Ryujinx.Ava
|
||||
if: github.event_name == 'pull_request'
|
||||
- name: Upload Ryujinx artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||
path: publish
|
||||
if: github.event_name == 'pull_request'
|
||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||
path: publish_sdl2_headless
|
||||
if: github.event_name == 'pull_request'
|
||||
- name: Upload Ryujinx.Ava artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||
path: publish_ava
|
||||
|
12
.github/workflows/nightly_pr_comment.yml
vendored
12
.github/workflows/nightly_pr_comment.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v3
|
||||
- uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const {owner, repo} = context.repo;
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
const pull_head_sha = '${{github.event.workflow_run.head_sha}}';
|
||||
|
||||
const issue_number = await (async () => {
|
||||
const pulls = await github.pulls.list({owner, repo});
|
||||
const pulls = await github.rest.pulls.list({owner, repo});
|
||||
for await (const {data} of github.paginate.iterator(pulls)) {
|
||||
for (const pull of data) {
|
||||
if (pull.head.sha === pull_head_sha) {
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
return core.error(`No matching pull request found`);
|
||||
}
|
||||
|
||||
const {data: {artifacts}} = await github.actions.listWorkflowRunArtifacts({owner, repo, run_id});
|
||||
const {data: {artifacts}} = await github.rest.actions.listWorkflowRunArtifacts({owner, repo, run_id});
|
||||
if (!artifacts.length) {
|
||||
return core.error(`No artifacts found`);
|
||||
}
|
||||
@@ -57,12 +57,12 @@ jobs:
|
||||
body += hidden_headless_artifacts;
|
||||
body += hidden_debug_artifacts;
|
||||
|
||||
const {data: comments} = await github.issues.listComments({repo, owner, issue_number});
|
||||
const {data: comments} = await github.rest.issues.listComments({repo, owner, issue_number});
|
||||
const existing_comment = comments.find((c) => c.user.login === 'github-actions[bot]');
|
||||
if (existing_comment) {
|
||||
core.info(`Updating comment ${existing_comment.id}`);
|
||||
await github.issues.updateComment({repo, owner, comment_id: existing_comment.id, body});
|
||||
await github.rest.issues.updateComment({repo, owner, comment_id: existing_comment.id, body});
|
||||
} else {
|
||||
core.info(`Creating a comment`);
|
||||
await github.issues.createComment({repo, owner, issue_number, body});
|
||||
await github.rest.issues.createComment({repo, owner, issue_number, body});
|
||||
}
|
||||
|
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@@ -25,8 +25,8 @@ jobs:
|
||||
RYUJINX_TARGET_RELEASE_CHANNEL_REPO: "release-channel-master"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-dotnet@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
- name: Ensure NuGet Source
|
||||
@@ -36,8 +36,8 @@ jobs:
|
||||
- name: Get version info
|
||||
id: version_info
|
||||
run: |
|
||||
echo "::set-output name=build_version::${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}"
|
||||
echo "::set-output name=git_short_hash::$(git rev-parse --short "${{ github.sha }}")"
|
||||
echo "build_version=${{ env.RYUJINX_BASE_VERSION }}.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
||||
echo "git_short_hash=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
- name: Configure for release
|
||||
run: |
|
||||
|
@@ -62,224 +62,225 @@ namespace ARMeilleure.CodeGen.X86
|
||||
_instTable = new InstructionInfo[(int)X86Instruction.Count];
|
||||
|
||||
// Name RM/R RM/I8 RM/I32 R/I64 R/RM Flags
|
||||
Add(X86Instruction.Add, new InstructionInfo(0x00000001, 0x00000083, 0x00000081, BadOp, 0x00000003, InstructionFlags.None));
|
||||
Add(X86Instruction.Addpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Addps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Addsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Addss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Aesdec, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38de, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Aesdeclast, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38df, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Aesenc, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38dc, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Aesenclast, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38dd, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Aesimc, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38db, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.And, new InstructionInfo(0x00000021, 0x04000083, 0x04000081, BadOp, 0x00000023, InstructionFlags.None));
|
||||
Add(X86Instruction.Andnpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f55, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Andnps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f55, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Andpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f54, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Andps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f54, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Blendvpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3815, InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Blendvps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3814, InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Bsr, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbd, InstructionFlags.None));
|
||||
Add(X86Instruction.Bswap, new InstructionInfo(0x00000fc8, BadOp, BadOp, BadOp, BadOp, InstructionFlags.RegOnly));
|
||||
Add(X86Instruction.Call, new InstructionInfo(0x020000ff, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Cmovcc, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f40, InstructionFlags.None));
|
||||
Add(X86Instruction.Cmp, new InstructionInfo(0x00000039, 0x07000083, 0x07000081, BadOp, 0x0000003b, InstructionFlags.None));
|
||||
Add(X86Instruction.Cmppd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Cmpps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Cmpsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Cmpss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Cmpxchg, new InstructionInfo(0x00000fb1, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Cmpxchg16b, new InstructionInfo(0x01000fc7, BadOp, BadOp, BadOp, BadOp, InstructionFlags.RexW));
|
||||
Add(X86Instruction.Cmpxchg8, new InstructionInfo(0x00000fb0, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Reg8Src));
|
||||
Add(X86Instruction.Comisd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Comiss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Crc32, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38f1, InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Crc32_16, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38f1, InstructionFlags.PrefixF2 | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Crc32_8, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38f0, InstructionFlags.PrefixF2 | InstructionFlags.Reg8Src));
|
||||
Add(X86Instruction.Cvtdq2pd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe6, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Cvtdq2ps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5b, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Cvtpd2dq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe6, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Cvtpd2ps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Cvtps2dq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5b, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Cvtps2pd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Cvtsd2si, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2d, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Cvtsd2ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Cvtsi2sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2a, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Cvtsi2ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2a, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Cvtss2sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Cvtss2si, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2d, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Div, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x060000f7, InstructionFlags.None));
|
||||
Add(X86Instruction.Divpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Divps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Divsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Divss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Haddpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Haddps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Idiv, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x070000f7, InstructionFlags.None));
|
||||
Add(X86Instruction.Imul, new InstructionInfo(BadOp, 0x0000006b, 0x00000069, BadOp, 0x00000faf, InstructionFlags.None));
|
||||
Add(X86Instruction.Imul128, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x050000f7, InstructionFlags.None));
|
||||
Add(X86Instruction.Insertps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a21, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Jmp, new InstructionInfo(0x040000ff, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Ldmxcsr, new InstructionInfo(0x02000fae, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Lea, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x0000008d, InstructionFlags.None));
|
||||
Add(X86Instruction.Maxpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Maxps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Maxsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Maxss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Minpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Minps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Minsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Minss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Mov, new InstructionInfo(0x00000089, BadOp, 0x000000c7, 0x000000b8, 0x0000008b, InstructionFlags.None));
|
||||
Add(X86Instruction.Mov16, new InstructionInfo(0x00000089, BadOp, 0x000000c7, BadOp, 0x0000008b, InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Mov8, new InstructionInfo(0x00000088, 0x000000c6, BadOp, BadOp, 0x0000008a, InstructionFlags.Reg8Src | InstructionFlags.Reg8Dest));
|
||||
Add(X86Instruction.Movd, new InstructionInfo(0x00000f7e, BadOp, BadOp, BadOp, 0x00000f6e, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Movdqu, new InstructionInfo(0x00000f7f, BadOp, BadOp, BadOp, 0x00000f6f, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Movhlps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f12, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Movlhps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f16, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Movq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7e, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Movsd, new InstructionInfo(0x00000f11, BadOp, BadOp, BadOp, 0x00000f10, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Movss, new InstructionInfo(0x00000f11, BadOp, BadOp, BadOp, 0x00000f10, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Movsx16, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbf, InstructionFlags.None));
|
||||
Add(X86Instruction.Movsx32, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000063, InstructionFlags.None));
|
||||
Add(X86Instruction.Movsx8, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbe, InstructionFlags.Reg8Src));
|
||||
Add(X86Instruction.Movzx16, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb7, InstructionFlags.None));
|
||||
Add(X86Instruction.Movzx8, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb6, InstructionFlags.Reg8Src));
|
||||
Add(X86Instruction.Mul128, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x040000f7, InstructionFlags.None));
|
||||
Add(X86Instruction.Mulpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Mulps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Mulsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Mulss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Neg, new InstructionInfo(0x030000f7, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Not, new InstructionInfo(0x020000f7, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Or, new InstructionInfo(0x00000009, 0x01000083, 0x01000081, BadOp, 0x0000000b, InstructionFlags.None));
|
||||
Add(X86Instruction.Paddb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffc, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Paddd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffe, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Paddq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd4, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Paddw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffd, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Palignr, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0f, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pand, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdb, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pandn, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdf, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pavgb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe0, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pavgw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe3, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pblendvb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3810, InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pclmulqdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a44, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f74, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f76, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3829, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f75, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f64, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f66, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3837, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f65, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pextrb, new InstructionInfo(0x000f3a14, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pextrd, new InstructionInfo(0x000f3a16, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pextrq, new InstructionInfo(0x000f3a16, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.RexW | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pextrw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc5, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pinsrb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a20, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pinsrd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a22, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pinsrq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a22, InstructionFlags.Vex | InstructionFlags.RexW | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pinsrw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc4, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxsb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383c, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383d, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxsw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fee, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxub, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fde, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxud, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383f, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxuw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383e, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pminsb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3838, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pminsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3839, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pminsw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fea, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pminub, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fda, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pminud, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383b, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pminuw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383a, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovsxbw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3820, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovsxdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3825, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovsxwd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3823, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovzxbw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3830, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovzxdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3835, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovzxwd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3833, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmulld, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3840, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmullw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd5, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pop, new InstructionInfo(0x0000008f, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Popcnt, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb8, InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Por, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000feb, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pshufb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3800, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pshufd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f70, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pslld, new InstructionInfo(BadOp, 0x06000f72, BadOp, BadOp, 0x00000ff2, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pslldq, new InstructionInfo(BadOp, 0x07000f73, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psllq, new InstructionInfo(BadOp, 0x06000f73, BadOp, BadOp, 0x00000ff3, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psllw, new InstructionInfo(BadOp, 0x06000f71, BadOp, BadOp, 0x00000ff1, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psrad, new InstructionInfo(BadOp, 0x04000f72, BadOp, BadOp, 0x00000fe2, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psraw, new InstructionInfo(BadOp, 0x04000f71, BadOp, BadOp, 0x00000fe1, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psrld, new InstructionInfo(BadOp, 0x02000f72, BadOp, BadOp, 0x00000fd2, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psrlq, new InstructionInfo(BadOp, 0x02000f73, BadOp, BadOp, 0x00000fd3, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psrldq, new InstructionInfo(BadOp, 0x03000f73, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psrlw, new InstructionInfo(BadOp, 0x02000f71, BadOp, BadOp, 0x00000fd1, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psubb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ff8, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psubd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffa, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psubq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffb, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psubw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ff9, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhbw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f68, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6a, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhqdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6d, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhwd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f69, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpcklbw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f60, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckldq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f62, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpcklqdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6c, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpcklwd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f61, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Push, new InstructionInfo(BadOp, 0x0000006a, 0x00000068, BadOp, 0x060000ff, InstructionFlags.None));
|
||||
Add(X86Instruction.Pxor, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fef, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Rcpps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f53, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Rcpss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f53, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Ror, new InstructionInfo(0x010000d3, 0x010000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Roundpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a09, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Roundps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a08, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Roundsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0b, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Roundss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0a, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Rsqrtps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Rsqrtss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Sar, new InstructionInfo(0x070000d3, 0x070000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Setcc, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f90, InstructionFlags.Reg8Dest));
|
||||
Add(X86Instruction.Sha256Msg1, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38cc, InstructionFlags.None));
|
||||
Add(X86Instruction.Sha256Msg2, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38cd, InstructionFlags.None));
|
||||
Add(X86Instruction.Sha256Rnds2, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38cb, InstructionFlags.None));
|
||||
Add(X86Instruction.Shl, new InstructionInfo(0x040000d3, 0x040000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Shr, new InstructionInfo(0x050000d3, 0x050000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Shufpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Shufps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Sqrtpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Sqrtps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Sqrtsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Sqrtss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Stmxcsr, new InstructionInfo(0x03000fae, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Sub, new InstructionInfo(0x00000029, 0x05000083, 0x05000081, BadOp, 0x0000002b, InstructionFlags.None));
|
||||
Add(X86Instruction.Subpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Subps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Subsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Subss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Test, new InstructionInfo(0x00000085, BadOp, 0x000000f7, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Unpckhpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f15, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Unpckhps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f15, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Unpcklpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f14, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Unpcklps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f14, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Vblendvpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a4b, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vblendvps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a4a, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vcvtph2ps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3813, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vcvtps2ph, new InstructionInfo(0x000f3a1d, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vfmadd231ps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38b8, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vfmadd231sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38b9, InstructionFlags.Vex | InstructionFlags.Prefix66 | InstructionFlags.RexW));
|
||||
Add(X86Instruction.Vfmadd231ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38b9, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vfmsub231sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bb, InstructionFlags.Vex | InstructionFlags.Prefix66 | InstructionFlags.RexW));
|
||||
Add(X86Instruction.Vfmsub231ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bb, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vfnmadd231ps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bc, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vfnmadd231sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bd, InstructionFlags.Vex | InstructionFlags.Prefix66 | InstructionFlags.RexW));
|
||||
Add(X86Instruction.Vfnmadd231ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bd, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vfnmsub231sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bf, InstructionFlags.Vex | InstructionFlags.Prefix66 | InstructionFlags.RexW));
|
||||
Add(X86Instruction.Vfnmsub231ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bf, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vpblendvb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a4c, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Xor, new InstructionInfo(0x00000031, 0x06000083, 0x06000081, BadOp, 0x00000033, InstructionFlags.None));
|
||||
Add(X86Instruction.Xorpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Xorps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Add, new InstructionInfo(0x00000001, 0x00000083, 0x00000081, BadOp, 0x00000003, InstructionFlags.None));
|
||||
Add(X86Instruction.Addpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Addps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Addsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Addss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Aesdec, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38de, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Aesdeclast, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38df, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Aesenc, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38dc, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Aesenclast, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38dd, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Aesimc, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38db, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.And, new InstructionInfo(0x00000021, 0x04000083, 0x04000081, BadOp, 0x00000023, InstructionFlags.None));
|
||||
Add(X86Instruction.Andnpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f55, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Andnps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f55, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Andpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f54, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Andps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f54, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Blendvpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3815, InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Blendvps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3814, InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Bsr, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbd, InstructionFlags.None));
|
||||
Add(X86Instruction.Bswap, new InstructionInfo(0x00000fc8, BadOp, BadOp, BadOp, BadOp, InstructionFlags.RegOnly));
|
||||
Add(X86Instruction.Call, new InstructionInfo(0x020000ff, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Cmovcc, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f40, InstructionFlags.None));
|
||||
Add(X86Instruction.Cmp, new InstructionInfo(0x00000039, 0x07000083, 0x07000081, BadOp, 0x0000003b, InstructionFlags.None));
|
||||
Add(X86Instruction.Cmppd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Cmpps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Cmpsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Cmpss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Cmpxchg, new InstructionInfo(0x00000fb1, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Cmpxchg16b, new InstructionInfo(0x01000fc7, BadOp, BadOp, BadOp, BadOp, InstructionFlags.RexW));
|
||||
Add(X86Instruction.Cmpxchg8, new InstructionInfo(0x00000fb0, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Reg8Src));
|
||||
Add(X86Instruction.Comisd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Comiss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Crc32, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38f1, InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Crc32_16, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38f1, InstructionFlags.PrefixF2 | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Crc32_8, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38f0, InstructionFlags.PrefixF2 | InstructionFlags.Reg8Src));
|
||||
Add(X86Instruction.Cvtdq2pd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe6, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Cvtdq2ps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5b, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Cvtpd2dq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe6, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Cvtpd2ps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Cvtps2dq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5b, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Cvtps2pd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Cvtsd2si, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2d, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Cvtsd2ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Cvtsi2sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2a, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Cvtsi2ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2a, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Cvtss2sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Cvtss2si, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2d, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Div, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x060000f7, InstructionFlags.None));
|
||||
Add(X86Instruction.Divpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Divps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Divsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Divss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Gf2p8affineqb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3ace, InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Haddpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Haddps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Idiv, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x070000f7, InstructionFlags.None));
|
||||
Add(X86Instruction.Imul, new InstructionInfo(BadOp, 0x0000006b, 0x00000069, BadOp, 0x00000faf, InstructionFlags.None));
|
||||
Add(X86Instruction.Imul128, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x050000f7, InstructionFlags.None));
|
||||
Add(X86Instruction.Insertps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a21, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Jmp, new InstructionInfo(0x040000ff, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Ldmxcsr, new InstructionInfo(0x02000fae, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Lea, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x0000008d, InstructionFlags.None));
|
||||
Add(X86Instruction.Maxpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Maxps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Maxsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Maxss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Minpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Minps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Minsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Minss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Mov, new InstructionInfo(0x00000089, BadOp, 0x000000c7, 0x000000b8, 0x0000008b, InstructionFlags.None));
|
||||
Add(X86Instruction.Mov16, new InstructionInfo(0x00000089, BadOp, 0x000000c7, BadOp, 0x0000008b, InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Mov8, new InstructionInfo(0x00000088, 0x000000c6, BadOp, BadOp, 0x0000008a, InstructionFlags.Reg8Src | InstructionFlags.Reg8Dest));
|
||||
Add(X86Instruction.Movd, new InstructionInfo(0x00000f7e, BadOp, BadOp, BadOp, 0x00000f6e, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Movdqu, new InstructionInfo(0x00000f7f, BadOp, BadOp, BadOp, 0x00000f6f, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Movhlps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f12, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Movlhps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f16, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Movq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7e, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Movsd, new InstructionInfo(0x00000f11, BadOp, BadOp, BadOp, 0x00000f10, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Movss, new InstructionInfo(0x00000f11, BadOp, BadOp, BadOp, 0x00000f10, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Movsx16, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbf, InstructionFlags.None));
|
||||
Add(X86Instruction.Movsx32, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000063, InstructionFlags.None));
|
||||
Add(X86Instruction.Movsx8, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbe, InstructionFlags.Reg8Src));
|
||||
Add(X86Instruction.Movzx16, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb7, InstructionFlags.None));
|
||||
Add(X86Instruction.Movzx8, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb6, InstructionFlags.Reg8Src));
|
||||
Add(X86Instruction.Mul128, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x040000f7, InstructionFlags.None));
|
||||
Add(X86Instruction.Mulpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Mulps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Mulsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Mulss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Neg, new InstructionInfo(0x030000f7, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Not, new InstructionInfo(0x020000f7, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Or, new InstructionInfo(0x00000009, 0x01000083, 0x01000081, BadOp, 0x0000000b, InstructionFlags.None));
|
||||
Add(X86Instruction.Paddb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffc, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Paddd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffe, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Paddq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd4, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Paddw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffd, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Palignr, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0f, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pand, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdb, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pandn, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdf, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pavgb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe0, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pavgw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe3, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pblendvb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3810, InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pclmulqdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a44, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f74, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f76, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3829, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f75, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f64, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f66, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3837, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f65, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pextrb, new InstructionInfo(0x000f3a14, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pextrd, new InstructionInfo(0x000f3a16, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pextrq, new InstructionInfo(0x000f3a16, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.RexW | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pextrw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc5, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pinsrb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a20, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pinsrd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a22, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pinsrq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a22, InstructionFlags.Vex | InstructionFlags.RexW | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pinsrw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc4, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxsb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383c, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383d, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxsw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fee, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxub, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fde, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxud, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383f, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxuw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383e, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pminsb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3838, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pminsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3839, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pminsw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fea, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pminub, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fda, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pminud, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383b, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pminuw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383a, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovsxbw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3820, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovsxdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3825, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovsxwd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3823, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovzxbw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3830, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovzxdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3835, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovzxwd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3833, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmulld, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3840, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pmullw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd5, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pop, new InstructionInfo(0x0000008f, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Popcnt, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb8, InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Por, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000feb, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pshufb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3800, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pshufd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f70, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pslld, new InstructionInfo(BadOp, 0x06000f72, BadOp, BadOp, 0x00000ff2, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Pslldq, new InstructionInfo(BadOp, 0x07000f73, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psllq, new InstructionInfo(BadOp, 0x06000f73, BadOp, BadOp, 0x00000ff3, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psllw, new InstructionInfo(BadOp, 0x06000f71, BadOp, BadOp, 0x00000ff1, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psrad, new InstructionInfo(BadOp, 0x04000f72, BadOp, BadOp, 0x00000fe2, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psraw, new InstructionInfo(BadOp, 0x04000f71, BadOp, BadOp, 0x00000fe1, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psrld, new InstructionInfo(BadOp, 0x02000f72, BadOp, BadOp, 0x00000fd2, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psrlq, new InstructionInfo(BadOp, 0x02000f73, BadOp, BadOp, 0x00000fd3, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psrldq, new InstructionInfo(BadOp, 0x03000f73, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psrlw, new InstructionInfo(BadOp, 0x02000f71, BadOp, BadOp, 0x00000fd1, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psubb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ff8, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psubd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffa, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psubq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffb, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Psubw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ff9, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhbw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f68, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6a, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhqdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6d, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhwd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f69, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpcklbw, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f60, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckldq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f62, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpcklqdq, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6c, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Punpcklwd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f61, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Push, new InstructionInfo(BadOp, 0x0000006a, 0x00000068, BadOp, 0x060000ff, InstructionFlags.None));
|
||||
Add(X86Instruction.Pxor, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fef, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Rcpps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f53, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Rcpss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f53, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Ror, new InstructionInfo(0x010000d3, 0x010000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Roundpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a09, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Roundps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a08, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Roundsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0b, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Roundss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0a, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Rsqrtps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Rsqrtss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Sar, new InstructionInfo(0x070000d3, 0x070000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Setcc, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f90, InstructionFlags.Reg8Dest));
|
||||
Add(X86Instruction.Sha256Msg1, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38cc, InstructionFlags.None));
|
||||
Add(X86Instruction.Sha256Msg2, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38cd, InstructionFlags.None));
|
||||
Add(X86Instruction.Sha256Rnds2, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38cb, InstructionFlags.None));
|
||||
Add(X86Instruction.Shl, new InstructionInfo(0x040000d3, 0x040000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Shr, new InstructionInfo(0x050000d3, 0x050000c1, BadOp, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Shufpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Shufps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Sqrtpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Sqrtps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Sqrtsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Sqrtss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Stmxcsr, new InstructionInfo(0x03000fae, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Sub, new InstructionInfo(0x00000029, 0x05000083, 0x05000081, BadOp, 0x0000002b, InstructionFlags.None));
|
||||
Add(X86Instruction.Subpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Subps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Subsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||
Add(X86Instruction.Subss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||
Add(X86Instruction.Test, new InstructionInfo(0x00000085, BadOp, 0x000000f7, BadOp, BadOp, InstructionFlags.None));
|
||||
Add(X86Instruction.Unpckhpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f15, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Unpckhps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f15, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Unpcklpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f14, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Unpcklps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f14, InstructionFlags.Vex));
|
||||
Add(X86Instruction.Vblendvpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a4b, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vblendvps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a4a, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vcvtph2ps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3813, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vcvtps2ph, new InstructionInfo(0x000f3a1d, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vfmadd231ps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38b8, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vfmadd231sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38b9, InstructionFlags.Vex | InstructionFlags.Prefix66 | InstructionFlags.RexW));
|
||||
Add(X86Instruction.Vfmadd231ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38b9, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vfmsub231sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bb, InstructionFlags.Vex | InstructionFlags.Prefix66 | InstructionFlags.RexW));
|
||||
Add(X86Instruction.Vfmsub231ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bb, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vfnmadd231ps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bc, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vfnmadd231sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bd, InstructionFlags.Vex | InstructionFlags.Prefix66 | InstructionFlags.RexW));
|
||||
Add(X86Instruction.Vfnmadd231ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bd, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vfnmsub231sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bf, InstructionFlags.Vex | InstructionFlags.Prefix66 | InstructionFlags.RexW));
|
||||
Add(X86Instruction.Vfnmsub231ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bf, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Vpblendvb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a4c, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Xor, new InstructionInfo(0x00000031, 0x06000083, 0x06000081, BadOp, 0x00000033, InstructionFlags.None));
|
||||
Add(X86Instruction.Xorpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Xorps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex));
|
||||
|
||||
static void Add(X86Instruction inst, in InstructionInfo info)
|
||||
{
|
||||
|
@@ -20,8 +20,9 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
if (maxNum >= 7)
|
||||
{
|
||||
(_, int ebx7, _, _) = X86Base.CpuId(0x00000007, 0x00000000);
|
||||
(_, int ebx7, int ecx7, _) = X86Base.CpuId(0x00000007, 0x00000000);
|
||||
FeatureInfo7Ebx = (FeatureFlags7Ebx)ebx7;
|
||||
FeatureInfo7Ecx = (FeatureFlags7Ecx)ecx7;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,9 +55,16 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Sha = 1 << 29
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum FeatureFlags7Ecx
|
||||
{
|
||||
Gfni = 1 << 8,
|
||||
}
|
||||
|
||||
public static FeatureFlags1Edx FeatureInfo1Edx { get; }
|
||||
public static FeatureFlags1Ecx FeatureInfo1Ecx { get; }
|
||||
public static FeatureFlags7Ebx FeatureInfo7Ebx { get; } = 0;
|
||||
public static FeatureFlags7Ecx FeatureInfo7Ecx { get; } = 0;
|
||||
|
||||
public static bool SupportsSse => FeatureInfo1Edx.HasFlag(FeatureFlags1Edx.Sse);
|
||||
public static bool SupportsSse2 => FeatureInfo1Edx.HasFlag(FeatureFlags1Edx.Sse2);
|
||||
@@ -72,6 +80,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
public static bool SupportsAvx2 => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx2) && SupportsAvx;
|
||||
public static bool SupportsF16c => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.F16c);
|
||||
public static bool SupportsSha => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Sha);
|
||||
public static bool SupportsGfni => FeatureInfo7Ecx.HasFlag(FeatureFlags7Ecx.Gfni);
|
||||
|
||||
public static bool ForceLegacySse { get; set; }
|
||||
|
||||
|
@@ -13,176 +13,177 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
_intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))];
|
||||
|
||||
Add(Intrinsic.X86Addpd, new IntrinsicInfo(X86Instruction.Addpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Addps, new IntrinsicInfo(X86Instruction.Addps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Addsd, new IntrinsicInfo(X86Instruction.Addsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Addss, new IntrinsicInfo(X86Instruction.Addss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Aesdec, new IntrinsicInfo(X86Instruction.Aesdec, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Aesdeclast, new IntrinsicInfo(X86Instruction.Aesdeclast, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Aesenc, new IntrinsicInfo(X86Instruction.Aesenc, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Aesenclast, new IntrinsicInfo(X86Instruction.Aesenclast, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Aesimc, new IntrinsicInfo(X86Instruction.Aesimc, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Andnpd, new IntrinsicInfo(X86Instruction.Andnpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Andnps, new IntrinsicInfo(X86Instruction.Andnps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Andpd, new IntrinsicInfo(X86Instruction.Andpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Andps, new IntrinsicInfo(X86Instruction.Andps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Blendvpd, new IntrinsicInfo(X86Instruction.Blendvpd, IntrinsicType.Ternary));
|
||||
Add(Intrinsic.X86Blendvps, new IntrinsicInfo(X86Instruction.Blendvps, IntrinsicType.Ternary));
|
||||
Add(Intrinsic.X86Cmppd, new IntrinsicInfo(X86Instruction.Cmppd, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Cmpps, new IntrinsicInfo(X86Instruction.Cmpps, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Cmpsd, new IntrinsicInfo(X86Instruction.Cmpsd, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Cmpss, new IntrinsicInfo(X86Instruction.Cmpss, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Comisdeq, new IntrinsicInfo(X86Instruction.Comisd, IntrinsicType.Comis_));
|
||||
Add(Intrinsic.X86Comisdge, new IntrinsicInfo(X86Instruction.Comisd, IntrinsicType.Comis_));
|
||||
Add(Intrinsic.X86Comisdlt, new IntrinsicInfo(X86Instruction.Comisd, IntrinsicType.Comis_));
|
||||
Add(Intrinsic.X86Comisseq, new IntrinsicInfo(X86Instruction.Comiss, IntrinsicType.Comis_));
|
||||
Add(Intrinsic.X86Comissge, new IntrinsicInfo(X86Instruction.Comiss, IntrinsicType.Comis_));
|
||||
Add(Intrinsic.X86Comisslt, new IntrinsicInfo(X86Instruction.Comiss, IntrinsicType.Comis_));
|
||||
Add(Intrinsic.X86Crc32, new IntrinsicInfo(X86Instruction.Crc32, IntrinsicType.Crc32));
|
||||
Add(Intrinsic.X86Crc32_16, new IntrinsicInfo(X86Instruction.Crc32_16, IntrinsicType.Crc32));
|
||||
Add(Intrinsic.X86Crc32_8, new IntrinsicInfo(X86Instruction.Crc32_8, IntrinsicType.Crc32));
|
||||
Add(Intrinsic.X86Cvtdq2pd, new IntrinsicInfo(X86Instruction.Cvtdq2pd, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Cvtdq2ps, new IntrinsicInfo(X86Instruction.Cvtdq2ps, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Cvtpd2dq, new IntrinsicInfo(X86Instruction.Cvtpd2dq, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Cvtpd2ps, new IntrinsicInfo(X86Instruction.Cvtpd2ps, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Cvtps2dq, new IntrinsicInfo(X86Instruction.Cvtps2dq, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Cvtps2pd, new IntrinsicInfo(X86Instruction.Cvtps2pd, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Cvtsd2si, new IntrinsicInfo(X86Instruction.Cvtsd2si, IntrinsicType.UnaryToGpr));
|
||||
Add(Intrinsic.X86Cvtsd2ss, new IntrinsicInfo(X86Instruction.Cvtsd2ss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Cvtsi2sd, new IntrinsicInfo(X86Instruction.Cvtsi2sd, IntrinsicType.BinaryGpr));
|
||||
Add(Intrinsic.X86Cvtsi2si, new IntrinsicInfo(X86Instruction.Movd, IntrinsicType.UnaryToGpr));
|
||||
Add(Intrinsic.X86Cvtsi2ss, new IntrinsicInfo(X86Instruction.Cvtsi2ss, IntrinsicType.BinaryGpr));
|
||||
Add(Intrinsic.X86Cvtss2sd, new IntrinsicInfo(X86Instruction.Cvtss2sd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Cvtss2si, new IntrinsicInfo(X86Instruction.Cvtss2si, IntrinsicType.UnaryToGpr));
|
||||
Add(Intrinsic.X86Divpd, new IntrinsicInfo(X86Instruction.Divpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Divps, new IntrinsicInfo(X86Instruction.Divps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Divsd, new IntrinsicInfo(X86Instruction.Divsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Divss, new IntrinsicInfo(X86Instruction.Divss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Haddpd, new IntrinsicInfo(X86Instruction.Haddpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Haddps, new IntrinsicInfo(X86Instruction.Haddps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Insertps, new IntrinsicInfo(X86Instruction.Insertps, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Maxpd, new IntrinsicInfo(X86Instruction.Maxpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Maxps, new IntrinsicInfo(X86Instruction.Maxps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Maxsd, new IntrinsicInfo(X86Instruction.Maxsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Maxss, new IntrinsicInfo(X86Instruction.Maxss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Minpd, new IntrinsicInfo(X86Instruction.Minpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Minps, new IntrinsicInfo(X86Instruction.Minps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Minsd, new IntrinsicInfo(X86Instruction.Minsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Minss, new IntrinsicInfo(X86Instruction.Minss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Movhlps, new IntrinsicInfo(X86Instruction.Movhlps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Movlhps, new IntrinsicInfo(X86Instruction.Movlhps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Movss, new IntrinsicInfo(X86Instruction.Movss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Mulpd, new IntrinsicInfo(X86Instruction.Mulpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Mulps, new IntrinsicInfo(X86Instruction.Mulps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Mulsd, new IntrinsicInfo(X86Instruction.Mulsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Mulss, new IntrinsicInfo(X86Instruction.Mulss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Mxcsrmb, new IntrinsicInfo(X86Instruction.None, IntrinsicType.Mxcsr)); // Mask bits.
|
||||
Add(Intrinsic.X86Mxcsrub, new IntrinsicInfo(X86Instruction.None, IntrinsicType.Mxcsr)); // Unmask bits.
|
||||
Add(Intrinsic.X86Paddb, new IntrinsicInfo(X86Instruction.Paddb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Paddd, new IntrinsicInfo(X86Instruction.Paddd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Paddq, new IntrinsicInfo(X86Instruction.Paddq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Paddw, new IntrinsicInfo(X86Instruction.Paddw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Palignr, new IntrinsicInfo(X86Instruction.Palignr, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Pand, new IntrinsicInfo(X86Instruction.Pand, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pandn, new IntrinsicInfo(X86Instruction.Pandn, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pavgb, new IntrinsicInfo(X86Instruction.Pavgb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pavgw, new IntrinsicInfo(X86Instruction.Pavgw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pblendvb, new IntrinsicInfo(X86Instruction.Pblendvb, IntrinsicType.Ternary));
|
||||
Add(Intrinsic.X86Pclmulqdq, new IntrinsicInfo(X86Instruction.Pclmulqdq, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Pcmpeqb, new IntrinsicInfo(X86Instruction.Pcmpeqb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pcmpeqd, new IntrinsicInfo(X86Instruction.Pcmpeqd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pcmpeqq, new IntrinsicInfo(X86Instruction.Pcmpeqq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pcmpeqw, new IntrinsicInfo(X86Instruction.Pcmpeqw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pcmpgtb, new IntrinsicInfo(X86Instruction.Pcmpgtb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pcmpgtd, new IntrinsicInfo(X86Instruction.Pcmpgtd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pcmpgtq, new IntrinsicInfo(X86Instruction.Pcmpgtq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pcmpgtw, new IntrinsicInfo(X86Instruction.Pcmpgtw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmaxsb, new IntrinsicInfo(X86Instruction.Pmaxsb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmaxsd, new IntrinsicInfo(X86Instruction.Pmaxsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmaxsw, new IntrinsicInfo(X86Instruction.Pmaxsw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmaxub, new IntrinsicInfo(X86Instruction.Pmaxub, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmaxud, new IntrinsicInfo(X86Instruction.Pmaxud, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmaxuw, new IntrinsicInfo(X86Instruction.Pmaxuw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pminsb, new IntrinsicInfo(X86Instruction.Pminsb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pminsd, new IntrinsicInfo(X86Instruction.Pminsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pminsw, new IntrinsicInfo(X86Instruction.Pminsw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pminub, new IntrinsicInfo(X86Instruction.Pminub, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pminud, new IntrinsicInfo(X86Instruction.Pminud, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pminuw, new IntrinsicInfo(X86Instruction.Pminuw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmovsxbw, new IntrinsicInfo(X86Instruction.Pmovsxbw, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Pmovsxdq, new IntrinsicInfo(X86Instruction.Pmovsxdq, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Pmovsxwd, new IntrinsicInfo(X86Instruction.Pmovsxwd, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Pmovzxbw, new IntrinsicInfo(X86Instruction.Pmovzxbw, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Pmovzxdq, new IntrinsicInfo(X86Instruction.Pmovzxdq, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Pmovzxwd, new IntrinsicInfo(X86Instruction.Pmovzxwd, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Pmulld, new IntrinsicInfo(X86Instruction.Pmulld, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmullw, new IntrinsicInfo(X86Instruction.Pmullw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Popcnt, new IntrinsicInfo(X86Instruction.Popcnt, IntrinsicType.PopCount));
|
||||
Add(Intrinsic.X86Por, new IntrinsicInfo(X86Instruction.Por, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pshufb, new IntrinsicInfo(X86Instruction.Pshufb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pshufd, new IntrinsicInfo(X86Instruction.Pshufd, IntrinsicType.BinaryImm));
|
||||
Add(Intrinsic.X86Pslld, new IntrinsicInfo(X86Instruction.Pslld, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pslldq, new IntrinsicInfo(X86Instruction.Pslldq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psllq, new IntrinsicInfo(X86Instruction.Psllq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psllw, new IntrinsicInfo(X86Instruction.Psllw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psrad, new IntrinsicInfo(X86Instruction.Psrad, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psraw, new IntrinsicInfo(X86Instruction.Psraw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psrld, new IntrinsicInfo(X86Instruction.Psrld, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psrlq, new IntrinsicInfo(X86Instruction.Psrlq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psrldq, new IntrinsicInfo(X86Instruction.Psrldq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psrlw, new IntrinsicInfo(X86Instruction.Psrlw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psubb, new IntrinsicInfo(X86Instruction.Psubb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psubd, new IntrinsicInfo(X86Instruction.Psubd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psubq, new IntrinsicInfo(X86Instruction.Psubq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psubw, new IntrinsicInfo(X86Instruction.Psubw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpckhbw, new IntrinsicInfo(X86Instruction.Punpckhbw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpckhdq, new IntrinsicInfo(X86Instruction.Punpckhdq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpckhqdq, new IntrinsicInfo(X86Instruction.Punpckhqdq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpckhwd, new IntrinsicInfo(X86Instruction.Punpckhwd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpcklbw, new IntrinsicInfo(X86Instruction.Punpcklbw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpckldq, new IntrinsicInfo(X86Instruction.Punpckldq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpcklqdq, new IntrinsicInfo(X86Instruction.Punpcklqdq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpcklwd, new IntrinsicInfo(X86Instruction.Punpcklwd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pxor, new IntrinsicInfo(X86Instruction.Pxor, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Rcpps, new IntrinsicInfo(X86Instruction.Rcpps, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Rcpss, new IntrinsicInfo(X86Instruction.Rcpss, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Roundpd, new IntrinsicInfo(X86Instruction.Roundpd, IntrinsicType.BinaryImm));
|
||||
Add(Intrinsic.X86Roundps, new IntrinsicInfo(X86Instruction.Roundps, IntrinsicType.BinaryImm));
|
||||
Add(Intrinsic.X86Roundsd, new IntrinsicInfo(X86Instruction.Roundsd, IntrinsicType.BinaryImm));
|
||||
Add(Intrinsic.X86Roundss, new IntrinsicInfo(X86Instruction.Roundss, IntrinsicType.BinaryImm));
|
||||
Add(Intrinsic.X86Rsqrtps, new IntrinsicInfo(X86Instruction.Rsqrtps, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Rsqrtss, new IntrinsicInfo(X86Instruction.Rsqrtss, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Sha256Msg1, new IntrinsicInfo(X86Instruction.Sha256Msg1, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Sha256Msg2, new IntrinsicInfo(X86Instruction.Sha256Msg2, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Sha256Rnds2, new IntrinsicInfo(X86Instruction.Sha256Rnds2, IntrinsicType.Ternary));
|
||||
Add(Intrinsic.X86Shufpd, new IntrinsicInfo(X86Instruction.Shufpd, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Shufps, new IntrinsicInfo(X86Instruction.Shufps, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Sqrtpd, new IntrinsicInfo(X86Instruction.Sqrtpd, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Sqrtps, new IntrinsicInfo(X86Instruction.Sqrtps, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Sqrtsd, new IntrinsicInfo(X86Instruction.Sqrtsd, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Sqrtss, new IntrinsicInfo(X86Instruction.Sqrtss, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Subpd, new IntrinsicInfo(X86Instruction.Subpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Subps, new IntrinsicInfo(X86Instruction.Subps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Subsd, new IntrinsicInfo(X86Instruction.Subsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Subss, new IntrinsicInfo(X86Instruction.Subss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Unpckhpd, new IntrinsicInfo(X86Instruction.Unpckhpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Unpckhps, new IntrinsicInfo(X86Instruction.Unpckhps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Unpcklpd, new IntrinsicInfo(X86Instruction.Unpcklpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Unpcklps, new IntrinsicInfo(X86Instruction.Unpcklps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Vcvtph2ps, new IntrinsicInfo(X86Instruction.Vcvtph2ps, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Vcvtps2ph, new IntrinsicInfo(X86Instruction.Vcvtps2ph, IntrinsicType.BinaryImm));
|
||||
Add(Intrinsic.X86Vfmadd231ps, new IntrinsicInfo(X86Instruction.Vfmadd231ps, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfmadd231sd, new IntrinsicInfo(X86Instruction.Vfmadd231sd, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfmadd231ss, new IntrinsicInfo(X86Instruction.Vfmadd231ss, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfmsub231sd, new IntrinsicInfo(X86Instruction.Vfmsub231sd, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfmsub231ss, new IntrinsicInfo(X86Instruction.Vfmsub231ss, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfnmadd231ps, new IntrinsicInfo(X86Instruction.Vfnmadd231ps, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfnmadd231sd, new IntrinsicInfo(X86Instruction.Vfnmadd231sd, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfnmadd231ss, new IntrinsicInfo(X86Instruction.Vfnmadd231ss, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfnmsub231sd, new IntrinsicInfo(X86Instruction.Vfnmsub231sd, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfnmsub231ss, new IntrinsicInfo(X86Instruction.Vfnmsub231ss, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Xorpd, new IntrinsicInfo(X86Instruction.Xorpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Xorps, new IntrinsicInfo(X86Instruction.Xorps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Addpd, new IntrinsicInfo(X86Instruction.Addpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Addps, new IntrinsicInfo(X86Instruction.Addps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Addsd, new IntrinsicInfo(X86Instruction.Addsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Addss, new IntrinsicInfo(X86Instruction.Addss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Aesdec, new IntrinsicInfo(X86Instruction.Aesdec, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Aesdeclast, new IntrinsicInfo(X86Instruction.Aesdeclast, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Aesenc, new IntrinsicInfo(X86Instruction.Aesenc, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Aesenclast, new IntrinsicInfo(X86Instruction.Aesenclast, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Aesimc, new IntrinsicInfo(X86Instruction.Aesimc, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Andnpd, new IntrinsicInfo(X86Instruction.Andnpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Andnps, new IntrinsicInfo(X86Instruction.Andnps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Andpd, new IntrinsicInfo(X86Instruction.Andpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Andps, new IntrinsicInfo(X86Instruction.Andps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Blendvpd, new IntrinsicInfo(X86Instruction.Blendvpd, IntrinsicType.Ternary));
|
||||
Add(Intrinsic.X86Blendvps, new IntrinsicInfo(X86Instruction.Blendvps, IntrinsicType.Ternary));
|
||||
Add(Intrinsic.X86Cmppd, new IntrinsicInfo(X86Instruction.Cmppd, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Cmpps, new IntrinsicInfo(X86Instruction.Cmpps, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Cmpsd, new IntrinsicInfo(X86Instruction.Cmpsd, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Cmpss, new IntrinsicInfo(X86Instruction.Cmpss, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Comisdeq, new IntrinsicInfo(X86Instruction.Comisd, IntrinsicType.Comis_));
|
||||
Add(Intrinsic.X86Comisdge, new IntrinsicInfo(X86Instruction.Comisd, IntrinsicType.Comis_));
|
||||
Add(Intrinsic.X86Comisdlt, new IntrinsicInfo(X86Instruction.Comisd, IntrinsicType.Comis_));
|
||||
Add(Intrinsic.X86Comisseq, new IntrinsicInfo(X86Instruction.Comiss, IntrinsicType.Comis_));
|
||||
Add(Intrinsic.X86Comissge, new IntrinsicInfo(X86Instruction.Comiss, IntrinsicType.Comis_));
|
||||
Add(Intrinsic.X86Comisslt, new IntrinsicInfo(X86Instruction.Comiss, IntrinsicType.Comis_));
|
||||
Add(Intrinsic.X86Crc32, new IntrinsicInfo(X86Instruction.Crc32, IntrinsicType.Crc32));
|
||||
Add(Intrinsic.X86Crc32_16, new IntrinsicInfo(X86Instruction.Crc32_16, IntrinsicType.Crc32));
|
||||
Add(Intrinsic.X86Crc32_8, new IntrinsicInfo(X86Instruction.Crc32_8, IntrinsicType.Crc32));
|
||||
Add(Intrinsic.X86Cvtdq2pd, new IntrinsicInfo(X86Instruction.Cvtdq2pd, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Cvtdq2ps, new IntrinsicInfo(X86Instruction.Cvtdq2ps, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Cvtpd2dq, new IntrinsicInfo(X86Instruction.Cvtpd2dq, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Cvtpd2ps, new IntrinsicInfo(X86Instruction.Cvtpd2ps, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Cvtps2dq, new IntrinsicInfo(X86Instruction.Cvtps2dq, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Cvtps2pd, new IntrinsicInfo(X86Instruction.Cvtps2pd, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Cvtsd2si, new IntrinsicInfo(X86Instruction.Cvtsd2si, IntrinsicType.UnaryToGpr));
|
||||
Add(Intrinsic.X86Cvtsd2ss, new IntrinsicInfo(X86Instruction.Cvtsd2ss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Cvtsi2sd, new IntrinsicInfo(X86Instruction.Cvtsi2sd, IntrinsicType.BinaryGpr));
|
||||
Add(Intrinsic.X86Cvtsi2si, new IntrinsicInfo(X86Instruction.Movd, IntrinsicType.UnaryToGpr));
|
||||
Add(Intrinsic.X86Cvtsi2ss, new IntrinsicInfo(X86Instruction.Cvtsi2ss, IntrinsicType.BinaryGpr));
|
||||
Add(Intrinsic.X86Cvtss2sd, new IntrinsicInfo(X86Instruction.Cvtss2sd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Cvtss2si, new IntrinsicInfo(X86Instruction.Cvtss2si, IntrinsicType.UnaryToGpr));
|
||||
Add(Intrinsic.X86Divpd, new IntrinsicInfo(X86Instruction.Divpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Divps, new IntrinsicInfo(X86Instruction.Divps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Divsd, new IntrinsicInfo(X86Instruction.Divsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Divss, new IntrinsicInfo(X86Instruction.Divss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Gf2p8affineqb, new IntrinsicInfo(X86Instruction.Gf2p8affineqb, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Haddpd, new IntrinsicInfo(X86Instruction.Haddpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Haddps, new IntrinsicInfo(X86Instruction.Haddps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Insertps, new IntrinsicInfo(X86Instruction.Insertps, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Maxpd, new IntrinsicInfo(X86Instruction.Maxpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Maxps, new IntrinsicInfo(X86Instruction.Maxps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Maxsd, new IntrinsicInfo(X86Instruction.Maxsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Maxss, new IntrinsicInfo(X86Instruction.Maxss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Minpd, new IntrinsicInfo(X86Instruction.Minpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Minps, new IntrinsicInfo(X86Instruction.Minps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Minsd, new IntrinsicInfo(X86Instruction.Minsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Minss, new IntrinsicInfo(X86Instruction.Minss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Movhlps, new IntrinsicInfo(X86Instruction.Movhlps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Movlhps, new IntrinsicInfo(X86Instruction.Movlhps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Movss, new IntrinsicInfo(X86Instruction.Movss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Mulpd, new IntrinsicInfo(X86Instruction.Mulpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Mulps, new IntrinsicInfo(X86Instruction.Mulps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Mulsd, new IntrinsicInfo(X86Instruction.Mulsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Mulss, new IntrinsicInfo(X86Instruction.Mulss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Mxcsrmb, new IntrinsicInfo(X86Instruction.None, IntrinsicType.Mxcsr)); // Mask bits.
|
||||
Add(Intrinsic.X86Mxcsrub, new IntrinsicInfo(X86Instruction.None, IntrinsicType.Mxcsr)); // Unmask bits.
|
||||
Add(Intrinsic.X86Paddb, new IntrinsicInfo(X86Instruction.Paddb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Paddd, new IntrinsicInfo(X86Instruction.Paddd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Paddq, new IntrinsicInfo(X86Instruction.Paddq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Paddw, new IntrinsicInfo(X86Instruction.Paddw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Palignr, new IntrinsicInfo(X86Instruction.Palignr, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Pand, new IntrinsicInfo(X86Instruction.Pand, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pandn, new IntrinsicInfo(X86Instruction.Pandn, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pavgb, new IntrinsicInfo(X86Instruction.Pavgb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pavgw, new IntrinsicInfo(X86Instruction.Pavgw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pblendvb, new IntrinsicInfo(X86Instruction.Pblendvb, IntrinsicType.Ternary));
|
||||
Add(Intrinsic.X86Pclmulqdq, new IntrinsicInfo(X86Instruction.Pclmulqdq, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Pcmpeqb, new IntrinsicInfo(X86Instruction.Pcmpeqb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pcmpeqd, new IntrinsicInfo(X86Instruction.Pcmpeqd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pcmpeqq, new IntrinsicInfo(X86Instruction.Pcmpeqq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pcmpeqw, new IntrinsicInfo(X86Instruction.Pcmpeqw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pcmpgtb, new IntrinsicInfo(X86Instruction.Pcmpgtb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pcmpgtd, new IntrinsicInfo(X86Instruction.Pcmpgtd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pcmpgtq, new IntrinsicInfo(X86Instruction.Pcmpgtq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pcmpgtw, new IntrinsicInfo(X86Instruction.Pcmpgtw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmaxsb, new IntrinsicInfo(X86Instruction.Pmaxsb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmaxsd, new IntrinsicInfo(X86Instruction.Pmaxsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmaxsw, new IntrinsicInfo(X86Instruction.Pmaxsw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmaxub, new IntrinsicInfo(X86Instruction.Pmaxub, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmaxud, new IntrinsicInfo(X86Instruction.Pmaxud, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmaxuw, new IntrinsicInfo(X86Instruction.Pmaxuw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pminsb, new IntrinsicInfo(X86Instruction.Pminsb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pminsd, new IntrinsicInfo(X86Instruction.Pminsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pminsw, new IntrinsicInfo(X86Instruction.Pminsw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pminub, new IntrinsicInfo(X86Instruction.Pminub, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pminud, new IntrinsicInfo(X86Instruction.Pminud, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pminuw, new IntrinsicInfo(X86Instruction.Pminuw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmovsxbw, new IntrinsicInfo(X86Instruction.Pmovsxbw, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Pmovsxdq, new IntrinsicInfo(X86Instruction.Pmovsxdq, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Pmovsxwd, new IntrinsicInfo(X86Instruction.Pmovsxwd, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Pmovzxbw, new IntrinsicInfo(X86Instruction.Pmovzxbw, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Pmovzxdq, new IntrinsicInfo(X86Instruction.Pmovzxdq, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Pmovzxwd, new IntrinsicInfo(X86Instruction.Pmovzxwd, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Pmulld, new IntrinsicInfo(X86Instruction.Pmulld, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pmullw, new IntrinsicInfo(X86Instruction.Pmullw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Popcnt, new IntrinsicInfo(X86Instruction.Popcnt, IntrinsicType.PopCount));
|
||||
Add(Intrinsic.X86Por, new IntrinsicInfo(X86Instruction.Por, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pshufb, new IntrinsicInfo(X86Instruction.Pshufb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pshufd, new IntrinsicInfo(X86Instruction.Pshufd, IntrinsicType.BinaryImm));
|
||||
Add(Intrinsic.X86Pslld, new IntrinsicInfo(X86Instruction.Pslld, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pslldq, new IntrinsicInfo(X86Instruction.Pslldq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psllq, new IntrinsicInfo(X86Instruction.Psllq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psllw, new IntrinsicInfo(X86Instruction.Psllw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psrad, new IntrinsicInfo(X86Instruction.Psrad, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psraw, new IntrinsicInfo(X86Instruction.Psraw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psrld, new IntrinsicInfo(X86Instruction.Psrld, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psrlq, new IntrinsicInfo(X86Instruction.Psrlq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psrldq, new IntrinsicInfo(X86Instruction.Psrldq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psrlw, new IntrinsicInfo(X86Instruction.Psrlw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psubb, new IntrinsicInfo(X86Instruction.Psubb, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psubd, new IntrinsicInfo(X86Instruction.Psubd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psubq, new IntrinsicInfo(X86Instruction.Psubq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Psubw, new IntrinsicInfo(X86Instruction.Psubw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpckhbw, new IntrinsicInfo(X86Instruction.Punpckhbw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpckhdq, new IntrinsicInfo(X86Instruction.Punpckhdq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpckhqdq, new IntrinsicInfo(X86Instruction.Punpckhqdq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpckhwd, new IntrinsicInfo(X86Instruction.Punpckhwd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpcklbw, new IntrinsicInfo(X86Instruction.Punpcklbw, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpckldq, new IntrinsicInfo(X86Instruction.Punpckldq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpcklqdq, new IntrinsicInfo(X86Instruction.Punpcklqdq, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Punpcklwd, new IntrinsicInfo(X86Instruction.Punpcklwd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Pxor, new IntrinsicInfo(X86Instruction.Pxor, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Rcpps, new IntrinsicInfo(X86Instruction.Rcpps, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Rcpss, new IntrinsicInfo(X86Instruction.Rcpss, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Roundpd, new IntrinsicInfo(X86Instruction.Roundpd, IntrinsicType.BinaryImm));
|
||||
Add(Intrinsic.X86Roundps, new IntrinsicInfo(X86Instruction.Roundps, IntrinsicType.BinaryImm));
|
||||
Add(Intrinsic.X86Roundsd, new IntrinsicInfo(X86Instruction.Roundsd, IntrinsicType.BinaryImm));
|
||||
Add(Intrinsic.X86Roundss, new IntrinsicInfo(X86Instruction.Roundss, IntrinsicType.BinaryImm));
|
||||
Add(Intrinsic.X86Rsqrtps, new IntrinsicInfo(X86Instruction.Rsqrtps, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Rsqrtss, new IntrinsicInfo(X86Instruction.Rsqrtss, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Sha256Msg1, new IntrinsicInfo(X86Instruction.Sha256Msg1, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Sha256Msg2, new IntrinsicInfo(X86Instruction.Sha256Msg2, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Sha256Rnds2, new IntrinsicInfo(X86Instruction.Sha256Rnds2, IntrinsicType.Ternary));
|
||||
Add(Intrinsic.X86Shufpd, new IntrinsicInfo(X86Instruction.Shufpd, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Shufps, new IntrinsicInfo(X86Instruction.Shufps, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Sqrtpd, new IntrinsicInfo(X86Instruction.Sqrtpd, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Sqrtps, new IntrinsicInfo(X86Instruction.Sqrtps, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Sqrtsd, new IntrinsicInfo(X86Instruction.Sqrtsd, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Sqrtss, new IntrinsicInfo(X86Instruction.Sqrtss, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Subpd, new IntrinsicInfo(X86Instruction.Subpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Subps, new IntrinsicInfo(X86Instruction.Subps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Subsd, new IntrinsicInfo(X86Instruction.Subsd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Subss, new IntrinsicInfo(X86Instruction.Subss, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Unpckhpd, new IntrinsicInfo(X86Instruction.Unpckhpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Unpckhps, new IntrinsicInfo(X86Instruction.Unpckhps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Unpcklpd, new IntrinsicInfo(X86Instruction.Unpcklpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Unpcklps, new IntrinsicInfo(X86Instruction.Unpcklps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Vcvtph2ps, new IntrinsicInfo(X86Instruction.Vcvtph2ps, IntrinsicType.Unary));
|
||||
Add(Intrinsic.X86Vcvtps2ph, new IntrinsicInfo(X86Instruction.Vcvtps2ph, IntrinsicType.BinaryImm));
|
||||
Add(Intrinsic.X86Vfmadd231ps, new IntrinsicInfo(X86Instruction.Vfmadd231ps, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfmadd231sd, new IntrinsicInfo(X86Instruction.Vfmadd231sd, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfmadd231ss, new IntrinsicInfo(X86Instruction.Vfmadd231ss, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfmsub231sd, new IntrinsicInfo(X86Instruction.Vfmsub231sd, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfmsub231ss, new IntrinsicInfo(X86Instruction.Vfmsub231ss, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfnmadd231ps, new IntrinsicInfo(X86Instruction.Vfnmadd231ps, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfnmadd231sd, new IntrinsicInfo(X86Instruction.Vfnmadd231sd, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfnmadd231ss, new IntrinsicInfo(X86Instruction.Vfnmadd231ss, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfnmsub231sd, new IntrinsicInfo(X86Instruction.Vfnmsub231sd, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Vfnmsub231ss, new IntrinsicInfo(X86Instruction.Vfnmsub231ss, IntrinsicType.Fma));
|
||||
Add(Intrinsic.X86Xorpd, new IntrinsicInfo(X86Instruction.Xorpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Xorps, new IntrinsicInfo(X86Instruction.Xorps, IntrinsicType.Binary));
|
||||
}
|
||||
|
||||
private static void Add(Intrinsic intrin, IntrinsicInfo info)
|
||||
|
@@ -54,6 +54,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
Divps,
|
||||
Divsd,
|
||||
Divss,
|
||||
Gf2p8affineqb,
|
||||
Haddpd,
|
||||
Haddps,
|
||||
Idiv,
|
||||
|
44
ARMeilleure/Decoders/OpCode32SimdCvtTB.cs
Normal file
44
ARMeilleure/Decoders/OpCode32SimdCvtTB.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdCvtTB : OpCode32, IOpCode32Simd
|
||||
{
|
||||
public int Vd { get; }
|
||||
public int Vm { get; }
|
||||
public bool Op { get; } // Convert to Half / Convert from Half
|
||||
public bool T { get; } // Top / Bottom
|
||||
public int Size { get; } // Double / Single
|
||||
|
||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtTB(inst, address, opCode, false);
|
||||
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtTB(inst, address, opCode, true);
|
||||
|
||||
public OpCode32SimdCvtTB(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
|
||||
{
|
||||
IsThumb = isThumb;
|
||||
|
||||
Op = ((opCode >> 16) & 0x1) != 0;
|
||||
T = ((opCode >> 7) & 0x1) != 0;
|
||||
Size = ((opCode >> 8) & 0x1);
|
||||
|
||||
RegisterSize = Size == 1 ? RegisterSize.Int64 : RegisterSize.Int32;
|
||||
|
||||
if (Size == 1)
|
||||
{
|
||||
if (Op)
|
||||
{
|
||||
Vm = ((opCode >> 1) & 0x10) | ((opCode >> 0) & 0xf);
|
||||
Vd = ((opCode >> 22) & 0x1) | ((opCode >> 11) & 0x1e);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vm = ((opCode >> 5) & 0x1) | ((opCode << 1) & 0x1e);
|
||||
Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vm = ((opCode >> 5) & 0x1) | ((opCode << 1) & 0x1e);
|
||||
Vd = ((opCode >> 22) & 0x1) | ((opCode >> 11) & 0x1e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -828,6 +828,7 @@ namespace ARMeilleure.Decoders
|
||||
SetVfp("<<<<11101x11110xxxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create, OpCode32SimdCvtFI.CreateT32); // FP32 to int.
|
||||
SetVfp("<<<<11101x111000xxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create, OpCode32SimdCvtFI.CreateT32); // Int to FP32.
|
||||
SetVfp("111111101x1111xxxxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_RM, OpCode32SimdCvtFI.Create, OpCode32SimdCvtFI.CreateT32); // The many FP32 to int encodings (fp).
|
||||
SetVfp("<<<<11101x11001xxxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_TB, OpCode32SimdCvtTB.Create, OpCode32SimdCvtTB.CreateT32);
|
||||
SetVfp("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||
SetVfp("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, OpCode32SimdDupGP.Create, OpCode32SimdDupGP.CreateT32);
|
||||
SetVfp("<<<<11101x10xxxxxxxx101xx0x0xxxx", InstName.Vfma, InstEmit32.Vfma_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||
|
@@ -1617,18 +1617,32 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Frinta_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
return EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1);
|
||||
});
|
||||
EmitSse41ScalarRoundOpF(context, FPRoundingMode.ToNearestAway);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void Frinta_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
return EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1);
|
||||
});
|
||||
EmitSse41VectorRoundOpF(context, FPRoundingMode.ToNearestAway);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void Frinti_S(ArmEmitterContext context)
|
||||
@@ -3516,9 +3530,18 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Intrinsic inst = (op.Size & 1) != 0 ? Intrinsic.X86Roundsd : Intrinsic.X86Roundss;
|
||||
Operand res;
|
||||
|
||||
Operand res = context.AddIntrinsic(inst, n, Const(X86GetRoundControl(roundMode)));
|
||||
if (roundMode != FPRoundingMode.ToNearestAway)
|
||||
{
|
||||
Intrinsic inst = (op.Size & 1) != 0 ? Intrinsic.X86Roundsd : Intrinsic.X86Roundss;
|
||||
|
||||
res = context.AddIntrinsic(inst, n, Const(X86GetRoundControl(roundMode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
res = EmitSse41RoundToNearestWithTiesToAwayOpF(context, n, scalar: true);
|
||||
}
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
@@ -3538,9 +3561,18 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Intrinsic inst = (op.Size & 1) != 0 ? Intrinsic.X86Roundpd : Intrinsic.X86Roundps;
|
||||
Operand res;
|
||||
|
||||
Operand res = context.AddIntrinsic(inst, n, Const(X86GetRoundControl(roundMode)));
|
||||
if (roundMode != FPRoundingMode.ToNearestAway)
|
||||
{
|
||||
Intrinsic inst = (op.Size & 1) != 0 ? Intrinsic.X86Roundpd : Intrinsic.X86Roundps;
|
||||
|
||||
res = context.AddIntrinsic(inst, n, Const(X86GetRoundControl(roundMode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
res = EmitSse41RoundToNearestWithTiesToAwayOpF(context, n, scalar: false);
|
||||
}
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd64)
|
||||
{
|
||||
|
@@ -164,32 +164,74 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtas_Gp(ArmEmitterContext context)
|
||||
{
|
||||
EmitFcvt_s_Gp(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1));
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvts_Gp(context, FPRoundingMode.ToNearestAway, isFixed: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitFcvt_s_Gp(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Fcvtas_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitFcvt(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1), signed: true, scalar: true);
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtsOpF(context, FPRoundingMode.ToNearestAway, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitFcvt(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1), signed: true, scalar: true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Fcvtas_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitFcvt(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1), signed: true, scalar: false);
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtsOpF(context, FPRoundingMode.ToNearestAway, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitFcvt(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1), signed: true, scalar: false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Fcvtau_Gp(ArmEmitterContext context)
|
||||
{
|
||||
EmitFcvt_u_Gp(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1));
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvtu_Gp(context, FPRoundingMode.ToNearestAway, isFixed: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitFcvt_u_Gp(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Fcvtau_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitFcvt(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1), signed: false, scalar: true);
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtuOpF(context, FPRoundingMode.ToNearestAway, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitFcvt(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1), signed: false, scalar: true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Fcvtau_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitFcvt(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1), signed: false, scalar: false);
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtuOpF(context, FPRoundingMode.ToNearestAway, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitFcvt(context, (op1) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, op1), signed: false, scalar: false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Fcvtl_V(ArmEmitterContext context)
|
||||
@@ -1223,7 +1265,14 @@ namespace ARMeilleure.Instructions
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulps, nRes, fpScaledMask);
|
||||
}
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundps, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
if (roundMode != FPRoundingMode.ToNearestAway)
|
||||
{
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundps, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
nRes = EmitSse41RoundToNearestWithTiesToAwayOpF(context, nRes, scalar);
|
||||
}
|
||||
|
||||
Operand nInt = context.AddIntrinsic(Intrinsic.X86Cvtps2dq, nRes);
|
||||
|
||||
@@ -1265,7 +1314,14 @@ namespace ARMeilleure.Instructions
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulpd, nRes, fpScaledMask);
|
||||
}
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundpd, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
if (roundMode != FPRoundingMode.ToNearestAway)
|
||||
{
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundpd, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
nRes = EmitSse41RoundToNearestWithTiesToAwayOpF(context, nRes, scalar);
|
||||
}
|
||||
|
||||
Operand nLong = EmitSse2CvtDoubleToInt64OpF(context, nRes, scalar);
|
||||
|
||||
@@ -1314,7 +1370,14 @@ namespace ARMeilleure.Instructions
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulps, nRes, fpScaledMask);
|
||||
}
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundps, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
if (roundMode != FPRoundingMode.ToNearestAway)
|
||||
{
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundps, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
nRes = EmitSse41RoundToNearestWithTiesToAwayOpF(context, nRes, scalar);
|
||||
}
|
||||
|
||||
Operand zero = context.VectorZero();
|
||||
|
||||
@@ -1369,7 +1432,14 @@ namespace ARMeilleure.Instructions
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulpd, nRes, fpScaledMask);
|
||||
}
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundpd, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
if (roundMode != FPRoundingMode.ToNearestAway)
|
||||
{
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundpd, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
nRes = EmitSse41RoundToNearestWithTiesToAwayOpF(context, nRes, scalar);
|
||||
}
|
||||
|
||||
Operand zero = context.VectorZero();
|
||||
|
||||
@@ -1424,7 +1494,14 @@ namespace ARMeilleure.Instructions
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulss, nRes, fpScaledMask);
|
||||
}
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundss, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
if (roundMode != FPRoundingMode.ToNearestAway)
|
||||
{
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundss, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
nRes = EmitSse41RoundToNearestWithTiesToAwayOpF(context, nRes, scalar: true);
|
||||
}
|
||||
|
||||
Operand nIntOrLong = op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (Intrinsic.X86Cvtss2si, nRes)
|
||||
@@ -1464,7 +1541,14 @@ namespace ARMeilleure.Instructions
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulsd, nRes, fpScaledMask);
|
||||
}
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundsd, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
if (roundMode != FPRoundingMode.ToNearestAway)
|
||||
{
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundsd, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
nRes = EmitSse41RoundToNearestWithTiesToAwayOpF(context, nRes, scalar: true);
|
||||
}
|
||||
|
||||
Operand nIntOrLong = op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (Intrinsic.X86Cvtsd2si, nRes)
|
||||
@@ -1512,7 +1596,14 @@ namespace ARMeilleure.Instructions
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulss, nRes, fpScaledMask);
|
||||
}
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundss, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
if (roundMode != FPRoundingMode.ToNearestAway)
|
||||
{
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundss, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
nRes = EmitSse41RoundToNearestWithTiesToAwayOpF(context, nRes, scalar: true);
|
||||
}
|
||||
|
||||
Operand zero = context.VectorZero();
|
||||
|
||||
@@ -1567,7 +1658,14 @@ namespace ARMeilleure.Instructions
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulsd, nRes, fpScaledMask);
|
||||
}
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundsd, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
if (roundMode != FPRoundingMode.ToNearestAway)
|
||||
{
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundsd, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
nRes = EmitSse41RoundToNearestWithTiesToAwayOpF(context, nRes, scalar: true);
|
||||
}
|
||||
|
||||
Operand zero = context.VectorZero();
|
||||
|
||||
|
@@ -203,6 +203,9 @@ namespace ARMeilleure.Instructions
|
||||
FPRoundingMode roundMode;
|
||||
switch (rm)
|
||||
{
|
||||
case 0b00:
|
||||
roundMode = FPRoundingMode.ToNearestAway;
|
||||
break;
|
||||
case 0b01:
|
||||
roundMode = FPRoundingMode.ToNearest;
|
||||
break;
|
||||
@@ -228,7 +231,7 @@ namespace ARMeilleure.Instructions
|
||||
bool unsigned = op.Opc == 0;
|
||||
int rm = op.Opc2 & 3;
|
||||
|
||||
if (Optimizations.UseSse41 && rm != 0b00)
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41ConvertInt32(context, RMToRoundMode(rm), !unsigned);
|
||||
}
|
||||
@@ -258,6 +261,74 @@ namespace ARMeilleure.Instructions
|
||||
}
|
||||
}
|
||||
|
||||
public static void Vcvt_TB(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdCvtTB op = (OpCode32SimdCvtTB)context.CurrOp;
|
||||
|
||||
if (Optimizations.UseF16c)
|
||||
{
|
||||
Debug.Assert(!Optimizations.ForceLegacySse);
|
||||
|
||||
if (op.Op)
|
||||
{
|
||||
Operand res = ExtractScalar(context, op.Size == 1 ? OperandType.FP64 : OperandType.FP32, op.Vm);
|
||||
if (op.Size == 1)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Cvtsd2ss, context.VectorZero(), res);
|
||||
}
|
||||
res = context.AddIntrinsic(Intrinsic.X86Vcvtps2ph, res, Const(X86GetRoundControl(FPRoundingMode.ToNearest)));
|
||||
res = context.VectorExtract16(res, 0);
|
||||
InsertScalar16(context, op.Vd, op.T, res);
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand res = context.VectorCreateScalar(ExtractScalar16(context, op.Vm, op.T));
|
||||
res = context.AddIntrinsic(Intrinsic.X86Vcvtph2ps, res);
|
||||
if (op.Size == 1)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Cvtss2sd, context.VectorZero(), res);
|
||||
}
|
||||
res = context.VectorExtract(op.Size == 1 ? OperandType.I64 : OperandType.I32, res, 0);
|
||||
InsertScalar(context, op.Vd, res);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (op.Op)
|
||||
{
|
||||
// Convert to half.
|
||||
|
||||
Operand src = ExtractScalar(context, op.Size == 1 ? OperandType.FP64 : OperandType.FP32, op.Vm);
|
||||
|
||||
MethodInfo method = op.Size == 1
|
||||
? typeof(SoftFloat64_16).GetMethod(nameof(SoftFloat64_16.FPConvert))
|
||||
: typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert));
|
||||
|
||||
context.StoreToContext();
|
||||
Operand res = context.Call(method, src);
|
||||
context.LoadFromContext();
|
||||
|
||||
InsertScalar16(context, op.Vd, op.T, res);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert from half.
|
||||
|
||||
Operand src = ExtractScalar16(context, op.Vm, op.T);
|
||||
|
||||
MethodInfo method = op.Size == 1
|
||||
? typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert))
|
||||
: typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert));
|
||||
|
||||
context.StoreToContext();
|
||||
Operand res = context.Call(method, src);
|
||||
context.LoadFromContext();
|
||||
|
||||
InsertScalar(context, op.Vd, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// VRINTA/M/N/P (floating-point).
|
||||
public static void Vrint_RM(ArmEmitterContext context)
|
||||
{
|
||||
@@ -267,15 +338,21 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
int rm = op.Opc2 & 3;
|
||||
|
||||
if (Optimizations.UseSse2 && rm != 0b00)
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitScalarUnaryOpSimd32(context, (m) =>
|
||||
{
|
||||
Intrinsic inst = (op.Size & 1) == 0 ? Intrinsic.X86Roundss : Intrinsic.X86Roundsd;
|
||||
|
||||
FPRoundingMode roundMode = RMToRoundMode(rm);
|
||||
|
||||
return context.AddIntrinsic(inst, m, Const(X86GetRoundControl(roundMode)));
|
||||
if (roundMode != FPRoundingMode.ToNearestAway)
|
||||
{
|
||||
Intrinsic inst = (op.Size & 1) == 0 ? Intrinsic.X86Roundss : Intrinsic.X86Roundsd;
|
||||
return context.AddIntrinsic(inst, m, Const(X86GetRoundControl(roundMode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return EmitSse41RoundToNearestWithTiesToAwayOpF(context, m, scalar: true);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
@@ -305,7 +382,17 @@ namespace ARMeilleure.Instructions
|
||||
// VRINTA (vector).
|
||||
public static void Vrinta_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitVectorUnaryOpF32(context, (m) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, m));
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitVectorUnaryOpSimd32(context, (m) =>
|
||||
{
|
||||
return EmitSse41RoundToNearestWithTiesToAwayOpF(context, m, scalar: false);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitVectorUnaryOpF32(context, (m) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, m));
|
||||
}
|
||||
}
|
||||
|
||||
// VRINTM (vector).
|
||||
@@ -413,7 +500,14 @@ namespace ARMeilleure.Instructions
|
||||
Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmpss, n, n, Const((int)CmpCondition.OrderedQ));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundss, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
if (roundMode != FPRoundingMode.ToNearestAway)
|
||||
{
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundss, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
nRes = EmitSse41RoundToNearestWithTiesToAwayOpF(context, nRes, scalar: true);
|
||||
}
|
||||
|
||||
Operand zero = context.VectorZero();
|
||||
|
||||
@@ -464,7 +558,14 @@ namespace ARMeilleure.Instructions
|
||||
Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmpsd, n, n, Const((int)CmpCondition.OrderedQ));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundsd, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
if (roundMode != FPRoundingMode.ToNearestAway)
|
||||
{
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Roundsd, nRes, Const(X86GetRoundControl(roundMode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
nRes = EmitSse41RoundToNearestWithTiesToAwayOpF(context, nRes, scalar: true);
|
||||
}
|
||||
|
||||
Operand zero = context.VectorZero();
|
||||
|
||||
|
@@ -33,6 +33,14 @@ namespace ARMeilleure.Instructions
|
||||
};
|
||||
|
||||
public static readonly long ZeroMask = 128L << 56 | 128L << 48 | 128L << 40 | 128L << 32 | 128L << 24 | 128L << 16 | 128L << 8 | 128L << 0;
|
||||
|
||||
public static ulong X86GetGf2p8LogicalShiftLeft(int shift)
|
||||
{
|
||||
ulong identity = (0b00000001UL << 56) | (0b00000010UL << 48) | (0b00000100UL << 40) | (0b00001000UL << 32) |
|
||||
(0b00010000UL << 24) | (0b00100000UL << 16) | (0b01000000UL << 8) | (0b10000000UL << 0);
|
||||
|
||||
return shift >= 0 ? identity >> (shift * 8) : identity << (-shift * 8);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region "X86 SSE Intrinsics"
|
||||
@@ -243,6 +251,46 @@ namespace ARMeilleure.Instructions
|
||||
throw new ArgumentException($"Invalid rounding mode \"{roundMode}\".");
|
||||
}
|
||||
|
||||
public static Operand EmitSse41RoundToNearestWithTiesToAwayOpF(ArmEmitterContext context, Operand n, bool scalar)
|
||||
{
|
||||
Debug.Assert(n.Type == OperandType.V128);
|
||||
|
||||
Operand nCopy = context.Copy(n);
|
||||
|
||||
Operand rC = Const(X86GetRoundControl(FPRoundingMode.TowardsZero));
|
||||
|
||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||
|
||||
if ((op.Size & 1) == 0)
|
||||
{
|
||||
Operand signMask = scalar ? X86GetScalar(context, int.MinValue) : X86GetAllElements(context, int.MinValue);
|
||||
signMask = context.AddIntrinsic(Intrinsic.X86Pand, signMask, nCopy);
|
||||
|
||||
// 0x3EFFFFFF == BitConverter.SingleToInt32Bits(0.5f) - 1
|
||||
Operand valueMask = scalar ? X86GetScalar(context, 0x3EFFFFFF) : X86GetAllElements(context, 0x3EFFFFFF);
|
||||
valueMask = context.AddIntrinsic(Intrinsic.X86Por, valueMask, signMask);
|
||||
|
||||
nCopy = context.AddIntrinsic(scalar ? Intrinsic.X86Addss : Intrinsic.X86Addps, nCopy, valueMask);
|
||||
|
||||
nCopy = context.AddIntrinsic(scalar ? Intrinsic.X86Roundss : Intrinsic.X86Roundps, nCopy, rC);
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand signMask = scalar ? X86GetScalar(context, long.MinValue) : X86GetAllElements(context, long.MinValue);
|
||||
signMask = context.AddIntrinsic(Intrinsic.X86Pand, signMask, nCopy);
|
||||
|
||||
// 0x3FDFFFFFFFFFFFFFL == BitConverter.DoubleToInt64Bits(0.5d) - 1L
|
||||
Operand valueMask = scalar ? X86GetScalar(context, 0x3FDFFFFFFFFFFFFFL) : X86GetAllElements(context, 0x3FDFFFFFFFFFFFFFL);
|
||||
valueMask = context.AddIntrinsic(Intrinsic.X86Por, valueMask, signMask);
|
||||
|
||||
nCopy = context.AddIntrinsic(scalar ? Intrinsic.X86Addsd : Intrinsic.X86Addpd, nCopy, valueMask);
|
||||
|
||||
nCopy = context.AddIntrinsic(scalar ? Intrinsic.X86Roundsd : Intrinsic.X86Roundpd, nCopy, rC);
|
||||
}
|
||||
|
||||
return nCopy;
|
||||
}
|
||||
|
||||
public static Operand EmitCountSetBits8(ArmEmitterContext context, Operand op) // "size" is 8 (SIMD&FP Inst.).
|
||||
{
|
||||
Debug.Assert(op.Type == OperandType.I32 || op.Type == OperandType.I64);
|
||||
|
@@ -70,6 +70,22 @@ namespace ARMeilleure.Instructions
|
||||
context.Copy(vec, insert);
|
||||
}
|
||||
|
||||
public static Operand ExtractScalar16(ArmEmitterContext context, int reg, bool top)
|
||||
{
|
||||
return context.VectorExtract16(GetVecA32(reg >> 2), ((reg & 3) << 1) | (top ? 1 : 0));
|
||||
}
|
||||
|
||||
public static void InsertScalar16(ArmEmitterContext context, int reg, bool top, Operand value)
|
||||
{
|
||||
Debug.Assert(value.Type == OperandType.FP32 || value.Type == OperandType.I32);
|
||||
|
||||
Operand vec, insert;
|
||||
vec = GetVecA32(reg >> 2);
|
||||
insert = context.VectorInsert16(vec, value, ((reg & 3) << 1) | (top ? 1 : 0));
|
||||
|
||||
context.Copy(vec, insert);
|
||||
}
|
||||
|
||||
public static Operand ExtractElement(ArmEmitterContext context, int reg, int size, bool signed)
|
||||
{
|
||||
return EmitVectorExtract32(context, reg >> (4 - size), reg & ((16 >> size) - 1), size, signed);
|
||||
|
@@ -336,20 +336,45 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand res = context.VectorZero();
|
||||
|
||||
int elems = op.RegisterSize == RegisterSize.Simd128 ? 16 : 8;
|
||||
|
||||
for (int index = 0; index < elems; index++)
|
||||
if (Optimizations.UseGfni)
|
||||
{
|
||||
Operand ne = EmitVectorExtractZx(context, op.Rn, index, 0);
|
||||
const long bitMatrix =
|
||||
(0b10000000L << 56) |
|
||||
(0b01000000L << 48) |
|
||||
(0b00100000L << 40) |
|
||||
(0b00010000L << 32) |
|
||||
(0b00001000L << 24) |
|
||||
(0b00000100L << 16) |
|
||||
(0b00000010L << 8) |
|
||||
(0b00000001L << 0);
|
||||
|
||||
Operand de = EmitReverseBits8Op(context, ne);
|
||||
Operand vBitMatrix = X86GetAllElements(context, bitMatrix);
|
||||
|
||||
res = EmitVectorInsert(context, res, de, index, 0);
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, GetVec(op.Rn), vBitMatrix, Const(0));
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd64)
|
||||
{
|
||||
res = context.VectorZeroUpper64(res);
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand res = context.VectorZero();
|
||||
int elems = op.RegisterSize == RegisterSize.Simd128 ? 16 : 8;
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
for (int index = 0; index < elems; index++)
|
||||
{
|
||||
Operand ne = EmitVectorExtractZx(context, op.Rn, index, 0);
|
||||
|
||||
Operand de = EmitReverseBits8Op(context, ne);
|
||||
|
||||
res = EmitVectorInsert(context, res, de, index, 0);
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
}
|
||||
|
||||
private static Operand EmitReverseBits8Op(ArmEmitterContext context, Operand op)
|
||||
|
@@ -88,8 +88,35 @@ namespace ARMeilleure.Instructions
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShl(op);
|
||||
int eSize = 8 << op.Size;
|
||||
|
||||
if (Optimizations.UseSse2 && op.Size > 0)
|
||||
if (shift >= eSize)
|
||||
{
|
||||
if ((op.RegisterSize == RegisterSize.Simd64))
|
||||
{
|
||||
Operand res = context.VectorZeroUpper64(GetVec(op.Rd));
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
}
|
||||
else if (Optimizations.UseGfni && op.Size == 0)
|
||||
{
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
ulong bitMatrix = X86GetGf2p8LogicalShiftLeft(shift);
|
||||
|
||||
Operand vBitMatrix = X86GetElements(context, bitMatrix, bitMatrix);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, n, vBitMatrix, Const(0));
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd64)
|
||||
{
|
||||
res = context.VectorZeroUpper64(res);
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
else if (Optimizations.UseSse2 && op.Size > 0)
|
||||
{
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
@@ -396,10 +423,40 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
if (Optimizations.UseSse2 && op.Size > 0 && op.Size < 3)
|
||||
{
|
||||
int shift = GetImmShr(op);
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
if (Optimizations.UseGfni && op.Size == 0)
|
||||
{
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
ulong bitMatrix;
|
||||
|
||||
if (shift < 8)
|
||||
{
|
||||
bitMatrix = X86GetGf2p8LogicalShiftLeft(-shift);
|
||||
|
||||
// Extend sign-bit
|
||||
bitMatrix |= 0x8080808080808080UL >> (64 - shift * 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Replicate sign-bit into all bits
|
||||
bitMatrix = 0x8080808080808080UL;
|
||||
}
|
||||
|
||||
Operand vBitMatrix = X86GetElements(context, bitMatrix, bitMatrix);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, n, vBitMatrix, Const(0));
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd64)
|
||||
{
|
||||
res = context.VectorZeroUpper64(res);
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
else if (Optimizations.UseSse2 && op.Size > 0 && op.Size < 3)
|
||||
{
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Intrinsic sraInst = X86PsraInstruction[op.Size];
|
||||
@@ -929,10 +986,44 @@ namespace ARMeilleure.Instructions
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShl(op);
|
||||
int eSize = 8 << op.Size;
|
||||
|
||||
ulong mask = shift != 0 ? ulong.MaxValue >> (64 - shift) : 0UL;
|
||||
|
||||
if (Optimizations.UseSse2 && op.Size > 0)
|
||||
if (shift >= eSize)
|
||||
{
|
||||
if ((op.RegisterSize == RegisterSize.Simd64) || scalar)
|
||||
{
|
||||
Operand res = context.VectorZeroUpper64(GetVec(op.Rd));
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
}
|
||||
else if (Optimizations.UseGfni && op.Size == 0)
|
||||
{
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
ulong bitMatrix = X86GetGf2p8LogicalShiftLeft(shift);
|
||||
|
||||
Operand vBitMatrix = X86GetElements(context, bitMatrix, bitMatrix);
|
||||
|
||||
Operand nShifted = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, n, vBitMatrix, Const(0));
|
||||
|
||||
Operand dMask = X86GetAllElements(context, (long)mask * _masks_SliSri[op.Size]);
|
||||
|
||||
Operand dMasked = context.AddIntrinsic(Intrinsic.X86Pand, d, dMask);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Por, nShifted, dMasked);
|
||||
|
||||
if ((op.RegisterSize == RegisterSize.Simd64) || scalar)
|
||||
{
|
||||
res = context.VectorZeroUpper64(res);
|
||||
}
|
||||
|
||||
context.Copy(d, res);
|
||||
}
|
||||
else if (Optimizations.UseSse2 && op.Size > 0)
|
||||
{
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
@@ -988,7 +1079,40 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
ulong mask = (ulong.MaxValue << (eSize - shift)) & (ulong.MaxValue >> (64 - eSize));
|
||||
|
||||
if (Optimizations.UseSse2 && op.Size > 0)
|
||||
if (shift >= eSize)
|
||||
{
|
||||
if ((op.RegisterSize == RegisterSize.Simd64) || scalar)
|
||||
{
|
||||
Operand res = context.VectorZeroUpper64(GetVec(op.Rd));
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
}
|
||||
else if (Optimizations.UseGfni && op.Size == 0)
|
||||
{
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
ulong bitMatrix = X86GetGf2p8LogicalShiftLeft(-shift);
|
||||
|
||||
Operand vBitMatrix = X86GetElements(context, bitMatrix, bitMatrix);
|
||||
|
||||
Operand nShifted = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, n, vBitMatrix, Const(0));
|
||||
|
||||
Operand dMask = X86GetAllElements(context, (long)mask * _masks_SliSri[op.Size]);
|
||||
|
||||
Operand dMasked = context.AddIntrinsic(Intrinsic.X86Pand, d, dMask);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Por, nShifted, dMasked);
|
||||
|
||||
if ((op.RegisterSize == RegisterSize.Simd64) || scalar)
|
||||
{
|
||||
res = context.VectorZeroUpper64(res);
|
||||
}
|
||||
|
||||
context.Copy(d, res);
|
||||
}
|
||||
else if (Optimizations.UseSse2 && op.Size > 0)
|
||||
{
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
@@ -47,6 +47,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
X86Divps,
|
||||
X86Divsd,
|
||||
X86Divss,
|
||||
X86Gf2p8affineqb,
|
||||
X86Haddpd,
|
||||
X86Haddps,
|
||||
X86Insertps,
|
||||
|
@@ -22,6 +22,7 @@ namespace ARMeilleure
|
||||
public static bool UseAesniIfAvailable { get; set; } = true;
|
||||
public static bool UsePclmulqdqIfAvailable { get; set; } = true;
|
||||
public static bool UseShaIfAvailable { get; set; } = true;
|
||||
public static bool UseGfniIfAvailable { get; set; } = true;
|
||||
|
||||
public static bool ForceLegacySse
|
||||
{
|
||||
@@ -42,5 +43,6 @@ namespace ARMeilleure
|
||||
internal static bool UseAesni => UseAesniIfAvailable && HardwareCapabilities.SupportsAesni;
|
||||
internal static bool UsePclmulqdq => UsePclmulqdqIfAvailable && HardwareCapabilities.SupportsPclmulqdq;
|
||||
internal static bool UseSha => UseShaIfAvailable && HardwareCapabilities.SupportsSha;
|
||||
internal static bool UseGfni => UseGfniIfAvailable && HardwareCapabilities.SupportsGfni;
|
||||
}
|
||||
}
|
@@ -2,9 +2,10 @@ namespace ARMeilleure.State
|
||||
{
|
||||
public enum FPRoundingMode
|
||||
{
|
||||
ToNearest = 0,
|
||||
ToNearest = 0, // With ties to even.
|
||||
TowardsPlusInfinity = 1,
|
||||
TowardsMinusInfinity = 2,
|
||||
TowardsZero = 3
|
||||
TowardsZero = 3,
|
||||
ToNearestAway = 4 // With ties to away.
|
||||
}
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||
|
||||
private const uint InternalVersion = 3703; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
private const uint InternalVersion = 3713; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
|
||||
private const string ActualDir = "0";
|
||||
private const string BackupDir = "1";
|
||||
@@ -951,7 +951,8 @@ namespace ARMeilleure.Translation.PTC
|
||||
return new FeatureInfo(
|
||||
(uint)HardwareCapabilities.FeatureInfo1Ecx,
|
||||
(uint)HardwareCapabilities.FeatureInfo1Edx,
|
||||
(uint)HardwareCapabilities.FeatureInfo7Ebx);
|
||||
(uint)HardwareCapabilities.FeatureInfo7Ebx,
|
||||
(uint)HardwareCapabilities.FeatureInfo7Ecx);
|
||||
}
|
||||
|
||||
private static byte GetMemoryManagerMode()
|
||||
@@ -971,7 +972,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
return osPlatform;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 54*/)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 58*/)]
|
||||
private struct OuterHeader
|
||||
{
|
||||
public ulong Magic;
|
||||
@@ -1002,8 +1003,8 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 12*/)]
|
||||
private record struct FeatureInfo(uint FeatureInfo0, uint FeatureInfo1, uint FeatureInfo2);
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 16*/)]
|
||||
private record struct FeatureInfo(uint FeatureInfo0, uint FeatureInfo1, uint FeatureInfo2, uint FeatureInfo3);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 128*/)]
|
||||
private struct InnerHeader
|
||||
|
@@ -455,13 +455,16 @@ namespace ARMeilleure.Translation
|
||||
|
||||
public void InvalidateJitCacheRegion(ulong address, ulong size)
|
||||
{
|
||||
// If rejit is running, stop it as it may be trying to rejit a function on the invalidated region.
|
||||
ClearRejitQueue(allowRequeue: true);
|
||||
|
||||
ulong[] overlapAddresses = Array.Empty<ulong>();
|
||||
|
||||
int overlapsCount = Functions.GetOverlaps(address, size, ref overlapAddresses);
|
||||
|
||||
if (overlapsCount != 0)
|
||||
{
|
||||
// If rejit is running, stop it as it may be trying to rejit a function on the invalidated region.
|
||||
ClearRejitQueue(allowRequeue: true);
|
||||
}
|
||||
|
||||
for (int index = 0; index < overlapsCount; index++)
|
||||
{
|
||||
ulong overlapAddress = overlapAddresses[index];
|
||||
|
@@ -36,8 +36,8 @@
|
||||
|
||||
## Compatibility
|
||||
|
||||
As of September 2022, Ryujinx has been tested on approximately 3,600 titles; over 3,400 boot past menus and into gameplay, with roughly 2,700 of those being considered playable. You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues).
|
||||
Anyone is free to submit a new game test or update an existing game test entry; simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue. Use the search function to see if a game has been tested already!
|
||||
As of October 2022, Ryujinx has been tested on approximately 3,700 titles; over 3,500 boot past menus and into gameplay, with roughly 3,000 of those being considered playable.
|
||||
You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues). Anyone is free to submit a new game test or update an existing game test entry; simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue. Use the search function to see if a game has been tested already!
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -90,7 +90,7 @@ Ryujinx system files are stored in the `Ryujinx` folder. This folder is located
|
||||
|
||||
- **GPU**
|
||||
|
||||
The GPU emulator emulates the Switch's Maxwell GPU using the OpenGL API (version 4.5 minimum) through a custom build of OpenTK. There are currently four graphics enhancements available to the end user in Ryujinx: disk shader caching, resolution scaling, aspect ratio adjustment and anisotropic filtering. These enhancements can be adjusted or toggled as desired in the GUI.
|
||||
The GPU emulator emulates the Switch's Maxwell GPU using either the OpenGL (version 4.5 minimum) or Vulkan APIs through a custom build of OpenTK or Silk.NET respectively. There are currently four graphics enhancements available to the end user in Ryujinx: Disk Shader Caching, Resolution Scaling, Aspect Ratio Adjustment, and Anisotropic Filtering. These enhancements can be adjusted or toggled as desired in the GUI.
|
||||
|
||||
- **Input**
|
||||
|
||||
|
@@ -58,6 +58,8 @@ namespace Ryujinx.Ava
|
||||
private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping.
|
||||
private const int TargetFps = 60;
|
||||
|
||||
private const float VolumeDelta = 0.05f;
|
||||
|
||||
private static readonly Cursor InvisibleCursor = new Cursor(StandardCursorType.None);
|
||||
|
||||
private readonly long _ticksPerFrame;
|
||||
@@ -73,6 +75,7 @@ namespace Ryujinx.Ava
|
||||
private bool _isStopped;
|
||||
private bool _isActive;
|
||||
private long _lastCursorMoveTime;
|
||||
private float _newVolume;
|
||||
private long _ticks = 0;
|
||||
|
||||
private KeyboardHotkeyState _prevHotkeyState;
|
||||
@@ -1003,6 +1006,18 @@ namespace Ryujinx.Ava
|
||||
GraphicsConfig.ResScale =
|
||||
(MaxResolutionScale + GraphicsConfig.ResScale - 2) % MaxResolutionScale + 1;
|
||||
break;
|
||||
case KeyboardHotkeyState.VolumeUp:
|
||||
_newVolume = MathF.Round((Device.GetVolume() + VolumeDelta), 2);
|
||||
Device.SetVolume(_newVolume);
|
||||
|
||||
_parent.ViewModel.Volume = Device.GetVolume();
|
||||
break;
|
||||
case KeyboardHotkeyState.VolumeDown:
|
||||
_newVolume = MathF.Round((Device.GetVolume() - VolumeDelta), 2);
|
||||
Device.SetVolume(_newVolume);
|
||||
|
||||
_parent.ViewModel.Volume = Device.GetVolume();
|
||||
break;
|
||||
case KeyboardHotkeyState.None:
|
||||
(_keyboardInterface as AvaloniaKeyboard).Clear();
|
||||
break;
|
||||
@@ -1068,6 +1083,14 @@ namespace Ryujinx.Ava
|
||||
{
|
||||
state = KeyboardHotkeyState.ResScaleDown;
|
||||
}
|
||||
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeUp))
|
||||
{
|
||||
state = KeyboardHotkeyState.VolumeUp;
|
||||
}
|
||||
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeDown))
|
||||
{
|
||||
state = KeyboardHotkeyState.VolumeDown;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
@@ -574,12 +574,12 @@
|
||||
"Discard": "Discard",
|
||||
"UserProfilesSetProfileImage": "Set Profile Image",
|
||||
"UserProfileEmptyNameError": "Name is required",
|
||||
"UserProfileNoImageError": "Profile image must be set",
|
||||
"UserProfileNoImageError": "Profile image must be set",
|
||||
"GameUpdateWindowHeading": "Updates Available for {0} [{1}]",
|
||||
"SettingsTabHotkeysResScaleUpHotkey": "Increase resolution:",
|
||||
"SettingsTabHotkeysResScaleDownHotkey": "Decrease resolution:",
|
||||
"UserProfilesName": "Name:",
|
||||
"UserProfilesUserId" : "User Id:",
|
||||
"UserProfilesUserId": "User Id:",
|
||||
"SettingsTabGraphicsBackend": "Graphics Backend",
|
||||
"SettingsTabGraphicsBackendTooltip": "Graphics Backend to use",
|
||||
"SettingsEnableTextureRecompression": "Enable Texture Recompression",
|
||||
@@ -589,5 +589,8 @@
|
||||
"SettingsAppRequiredRestartMessage": "Ryujinx Restart Required",
|
||||
"SettingsGpuBackendRestartMessage": "Graphics Backend or Gpu settings have been modified. This will require a restart to be applied",
|
||||
"SettingsGpuBackendRestartSubMessage": "Do you want to restart now?",
|
||||
"RyujinxUpdaterMessage": "Do you want to update Ryujinx to the latest version?",
|
||||
"SettingsTabHotkeysVolumeUpHotkey": "Increase Volume:",
|
||||
"SettingsTabHotkeysVolumeDownHotkey": "Decrease Volume:",
|
||||
"VolumeShort": "Vol"
|
||||
}
|
||||
|
@@ -49,8 +49,8 @@
|
||||
"GameListContextMenuManageTitleUpdatesToolTip": "Apre la finestra di gestione aggiornamenti del gioco",
|
||||
"GameListContextMenuManageDlc": "Gestici DLC",
|
||||
"GameListContextMenuManageDlcToolTip": "Apre la finestra di gestione DLC",
|
||||
"GameListContextMenuOpenModsDirectory": "Apri cartella delle mods",
|
||||
"GameListContextMenuOpenModsDirectoryToolTip": "Apre la cartella che contiene le mods dell'applicazione",
|
||||
"GameListContextMenuOpenModsDirectory": "Apri cartella delle mod",
|
||||
"GameListContextMenuOpenModsDirectoryToolTip": "Apre la cartella che contiene le mod dell'applicazione",
|
||||
"GameListContextMenuCacheManagement": "Gestione della cache",
|
||||
"GameListContextMenuCacheManagementPurgePptc": "Pulisci PPTC cache",
|
||||
"GameListContextMenuCacheManagementPurgePptcToolTip": "Elimina la PPTC cache dell'applicazione",
|
||||
@@ -81,7 +81,7 @@
|
||||
"SettingsTabGeneralRemove": "Rimuovi",
|
||||
"SettingsTabSystem": "Sistema",
|
||||
"SettingsTabSystemCore": "Core",
|
||||
"SettingsTabSystemSystemRegion": "Regione di sistema:",
|
||||
"SettingsTabSystemSystemRegion": "Regione del sistema:",
|
||||
"SettingsTabSystemSystemRegionJapan": "Giappone",
|
||||
"SettingsTabSystemSystemRegionUSA": "Stati Uniti d'America",
|
||||
"SettingsTabSystemSystemRegionEurope": "Europa",
|
||||
@@ -89,7 +89,7 @@
|
||||
"SettingsTabSystemSystemRegionChina": "Cina",
|
||||
"SettingsTabSystemSystemRegionKorea": "Corea",
|
||||
"SettingsTabSystemSystemRegionTaiwan": "Taiwan",
|
||||
"SettingsTabSystemSystemLanguage": "Lingua di sistema:",
|
||||
"SettingsTabSystemSystemLanguage": "Lingua del sistema:",
|
||||
"SettingsTabSystemSystemLanguageJapanese": "Giapponese",
|
||||
"SettingsTabSystemSystemLanguageAmericanEnglish": "Inglese americano",
|
||||
"SettingsTabSystemSystemLanguageFrench": "Francese",
|
||||
@@ -107,8 +107,8 @@
|
||||
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "Spagnolo latino americano",
|
||||
"SettingsTabSystemSystemLanguageSimplifiedChinese": "Cinese semplificato",
|
||||
"SettingsTabSystemSystemLanguageTraditionalChinese": "Cinese tradizionale",
|
||||
"SettingsTabSystemSystemTimeZone": "Fuso orario di sistema:",
|
||||
"SettingsTabSystemSystemTime": "Data e ora di sistema:",
|
||||
"SettingsTabSystemSystemTimeZone": "Fuso orario del sistema:",
|
||||
"SettingsTabSystemSystemTime": "Data e ora del sistema:",
|
||||
"SettingsTabSystemEnableVsync": "Attiva VSync",
|
||||
"SettingsTabSystemEnablePptc": "Attiva PPTC (Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "Attiva controlli d'integrità FS",
|
||||
@@ -155,7 +155,7 @@
|
||||
"SettingsTabLoggingEnableTraceLogs": "Attiva Trace Logs",
|
||||
"SettingsTabLoggingEnableGuestLogs": "Attiva Guest Logs",
|
||||
"SettingsTabLoggingEnableFsAccessLogs": "Attiva Fs Access Logs",
|
||||
"SettingsTabLoggingFsGlobalAccessLogMode": "Modalità di log accesso globale Fs:",
|
||||
"SettingsTabLoggingFsGlobalAccessLogMode": "Modalità log accesso globale Fs:",
|
||||
"SettingsTabLoggingDeveloperOptions": "Opzioni da sviluppatore (AVVISO: Ridurrà le prestazioni)",
|
||||
"SettingsTabLoggingOpenglLogLevel": "Livello di log OpenGL:",
|
||||
"SettingsTabLoggingOpenglLogLevelNone": "Nessuno",
|
||||
@@ -240,7 +240,7 @@
|
||||
"ControllerSettingsRightSR": "SR",
|
||||
"ControllerSettingsExtraButtonsLeft": "Tasto sinitro",
|
||||
"ControllerSettingsExtraButtonsRight": "Tasto destro",
|
||||
"ControllerSettingsMisc": "Miscellanee",
|
||||
"ControllerSettingsMisc": "Varie",
|
||||
"ControllerSettingsTriggerThreshold": "Sensibilità dei grilletti:",
|
||||
"ControllerSettingsMotion": "Movimento",
|
||||
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "Usa sensore compatibile con CemuHook",
|
||||
@@ -261,7 +261,7 @@
|
||||
"UserProfilesClose": "Chiudi",
|
||||
"ProfileImageSelectionTitle": "Selezione dell'immagine profilo",
|
||||
"ProfileImageSelectionHeader": "Scegli un'immagine profilo",
|
||||
"ProfileImageSelectionNote": "Puoi importare un'immagine profilo personalizzata o selezionare un avatar dal firmware di sistema",
|
||||
"ProfileImageSelectionNote": "Puoi importare un'immagine profilo personalizzata o selezionare un avatar dal firmware del sistema",
|
||||
"ProfileImageSelectionImportImage": "Importa file immagine",
|
||||
"ProfileImageSelectionSelectAvatar": "Seleziona avatar dal firmware",
|
||||
"InputDialogTitle": "Input Dialog",
|
||||
@@ -293,7 +293,7 @@
|
||||
"ControllerSettingsRumbleStrongMultiplier": "Moltiplicatore vibrazione forte",
|
||||
"ControllerSettingsRumbleWeakMultiplier": "Moltiplicatore vibrazione debole",
|
||||
"DialogMessageSaveNotAvailableMessage": "Non ci sono dati di salvataggio per {0} [{1:x16}]",
|
||||
"DialogMessageSaveNotAvailableCreateSaveMessage": "Vuoi creare dei dat di salvataggio per questo gioco?",
|
||||
"DialogMessageSaveNotAvailableCreateSaveMessage": "Vuoi creare dei dati di salvataggio per questo gioco?",
|
||||
"DialogConfirmationTitle": "Ryujinx - Conferma",
|
||||
"DialogUpdaterTitle": "Ryujinx - Updater",
|
||||
"DialogErrorTitle": "Ryujinx - Errore",
|
||||
@@ -318,7 +318,7 @@
|
||||
"DialogUpdaterDownloadingMessage": "Download dell'aggiornamento...",
|
||||
"DialogUpdaterExtractionMessage": "Estrazione dell'aggiornamento...",
|
||||
"DialogUpdaterRenamingMessage": "Rinominazione dell'aggiornamento...",
|
||||
"DialogUpdaterAddingFilesMessage": "Aggiunta nuovo aggiornamento...",
|
||||
"DialogUpdaterAddingFilesMessage": "Aggiunta del nuovo aggiornamento...",
|
||||
"DialogUpdaterCompleteMessage": "Aggiornamento completato!",
|
||||
"DialogUpdaterRestartMessage": "Vuoi riavviare Ryujinx adesso?",
|
||||
"DialogUpdaterArchNotSupportedMessage": "Non stai usando un'architettura di sistema supportata!",
|
||||
@@ -331,7 +331,7 @@
|
||||
"DialogThemeRestartMessage": "Il tema è stato salvato. E' richiesto un riavvio per applicare un tema.",
|
||||
"DialogThemeRestartSubMessage": "Vuoi riavviare?",
|
||||
"DialogFirmwareInstallEmbeddedMessage": "Vuoi installare il firmware incorporato in questo gioco? (Firmware {0})",
|
||||
"DialogFirmwareInstallEmbeddedSuccessMessage": "Non è stato trovato alcun firmware installato, ma Ryujinx è riuscito di installare il firmware {0} dal gioco fornito.\nL'emulatore si avvierà adesso.",
|
||||
"DialogFirmwareInstallEmbeddedSuccessMessage": "Non è stato trovato alcun firmware installato, ma Ryujinx è riuscito ad installare il firmware {0} dal gioco fornito.\nL'emulatore si avvierà adesso.",
|
||||
"DialogFirmwareNoFirmwareInstalledMessage": "Nessun firmware installato",
|
||||
"DialogFirmwareInstalledMessage": "Il firmware {0} è stato installato",
|
||||
"DialogOpenSettingsWindowLabel": "Apri finestra delle impostazioni",
|
||||
@@ -355,14 +355,14 @@
|
||||
"DialogShaderDeletionMessage": "Stai per eliminare la Shader cache per :\n\n{0}\n\nSei sicuro di voler proseguire?",
|
||||
"DialogShaderDeletionErrorMessage": "Errore nell'eliminazione della Shader cache a {0}: {1}",
|
||||
"DialogRyujinxErrorMessage": "Ryujinx ha incontrato un errore",
|
||||
"DialogInvalidTitleIdErrorMessage": "Errore UI: Il gioco selezionato non ha un title ID valido",
|
||||
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "Un firmware di sistema valido non è stato trovato in {0}.",
|
||||
"DialogInvalidTitleIdErrorMessage": "Errore UI: Il gioco selezionato non ha un ID titolo valido",
|
||||
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "Un firmware del sistema valido non è stato trovato in {0}.",
|
||||
"DialogFirmwareInstallerFirmwareInstallTitle": "Installa firmware {0}",
|
||||
"DialogFirmwareInstallerFirmwareInstallMessage": "La versione di sistema {0} sarà installata.",
|
||||
"DialogFirmwareInstallerFirmwareInstallMessage": "La versione del sistema {0} sarà installata.",
|
||||
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\nQuesta sostituirà l'attuale versione di sistema {0}.",
|
||||
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nVuoi continuare?",
|
||||
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installazione del firmware...",
|
||||
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "La versione di sistema {0} è stata installata.",
|
||||
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "La versione del sistema {0} è stata installata.",
|
||||
"DialogUserProfileDeletionWarningMessage": "Non ci sarebbero altri profili da aprire se il profilo selezionato viene cancellato",
|
||||
"DialogUserProfileDeletionConfirmMessage": "Vuoi eliminare il profilo selezionato?",
|
||||
"DialogControllerSettingsModifiedConfirmMessage": "Le attuali impostazioni del controller sono state aggiornate.",
|
||||
@@ -557,4 +557,40 @@
|
||||
"SettingsXamlThemeFile" : "File del tema xaml",
|
||||
"SettingsTabHotkeysResScaleUpHotkey": "Aumentare la risoluzione:",
|
||||
"SettingsTabHotkeysResScaleDownHotkey": "Diminuire la risoluzione:"
|
||||
"AvatarWindowTitle": "Gestisci account - Avatar"
|
||||
"Amiibo": "Amiibo",
|
||||
"Unknown": "Sconosciuto",
|
||||
"Usage": "Utilizzo",
|
||||
"Writable": "Scrivibile",
|
||||
"SelectDlcDialogTitle": "Seleziona file dei DLC",
|
||||
"SelectUpdateDialogTitle": "Seleziona file di aggiornamento",
|
||||
"UserProfileWindowTitle": "Gestisci profili degli utenti",
|
||||
"CheatWindowTitle": "Gestisci cheat dei giochi",
|
||||
"DlcWindowTitle": "Gestisci DLC dei giochi",
|
||||
"UpdateWindowTitle": "Gestisci aggiornamenti dei giochi",
|
||||
"CheatWindowHeading": "Cheat disponibiili per {0} [{1}]",
|
||||
"DlcWindowHeading": "DLC disponibili per {0} [{1}]",
|
||||
"UserProfilesEditProfile": "Modifica selezionati",
|
||||
"Cancel": "Annulla",
|
||||
"Save": "Salva",
|
||||
"Discard": "Scarta",
|
||||
"UserProfilesSetProfileImage": "Imposta immagine profilo",
|
||||
"UserProfileEmptyNameError": "È richiesto un nome",
|
||||
"UserProfileNoImageError": "Dev'essere impostata un'immagine profilo",
|
||||
"GameUpdateWindowHeading": "Aggiornamenti disponibili per {0} [{1}]",
|
||||
"UserProfilesName": "Name:",
|
||||
"UserProfilesUserId": "User Id:",
|
||||
"SettingsTabGraphicsBackend": "Backend grafica",
|
||||
"SettingsTabGraphicsBackendTooltip": "Backend grafica da usare",
|
||||
"SettingsEnableTextureRecompression": "Abilita Ricompressione Texture",
|
||||
"SettingsEnableTextureRecompressionTooltip": "Comprime alcune texture per ridurre l'utilizzo della VRAM.\n\nL'utilizzo è consigliato con GPU con meno di 4GB di VRAM.\n\nLascia su OFF se non sei sicuro.",
|
||||
"SettingsTabGraphicsPreferredGpu": "GPU preferita",
|
||||
"SettingsTabGraphicsPreferredGpuTooltip": "Seleziona la scheda grafica che verrà usata con la backend grafica Vulkan.\n\nNon influenza la GPU che userà OpenGL.\n\nImposta la GPU contrassegnata come \"dGPU\" se non sei sicuro. Se non ce n'è una, lascia intatta quest'impostazione.",
|
||||
"SettingsAppRequiredRestartMessage": "È richiesto un riavvio di Ryujinx",
|
||||
"SettingsGpuBackendRestartMessage": "Le impostazioni della backend grafica o della GPU sono state modificate. Questo richiederà un riavvio perché le modifiche siano applicate",
|
||||
"SettingsGpuBackendRestartSubMessage": "Vuoi riavviare ora?",
|
||||
"RyujinxUpdaterMessage": "Vuoi aggiornare Ryujinx all'ultima versione?",
|
||||
"SettingsTabHotkeysVolumeUpHotkey": "Aumentare il volume:",
|
||||
"SettingsTabHotkeysVolumeDownHotkey": "Diminuire il volume:",
|
||||
"VolumeShort": "Vol"
|
||||
}
|
||||
|
@@ -588,5 +588,9 @@
|
||||
"SettingsTabGraphicsPreferredGpuTooltip": "Wybierz kartę graficzną, która będzie używana z backendem graficznym Vulkan.\n\nNie wpływa na GPU używane przez OpenGL.\n\nW razie wątpliwości ustaw flagę GPU jako \"dGPU\". Jeśli żadnej nie ma, pozostaw nietknięte.",
|
||||
"SettingsAppRequiredRestartMessage": "Wymagane Zrestartowanie Ryujinx",
|
||||
"SettingsGpuBackendRestartMessage": "Zmieniono ustawienia Backendu Graficznego lub GPU. Będzie to wymagało ponownego uruchomienia",
|
||||
"SettingsGpuBackendRestartSubMessage": "Czy chcesz zrestartować teraz?"
|
||||
"SettingsGpuBackendRestartSubMessage": "Czy chcesz zrestartować teraz?",
|
||||
"RyujinxUpdaterMessage": "Czy chcesz zaktualizować Ryujinx do najnowszej wersji?",
|
||||
"SettingsTabHotkeysVolumeUpHotkey": "Zwiększ Głośność:",
|
||||
"SettingsTabHotkeysVolumeDownHotkey": "Zmniejsz Głośność:",
|
||||
"VolumeShort": "Głoś"
|
||||
}
|
||||
|
@@ -9,6 +9,8 @@
|
||||
Pause,
|
||||
ToggleMute,
|
||||
ResScaleUp,
|
||||
ResScaleDown
|
||||
ResScaleDown,
|
||||
VolumeUp,
|
||||
VolumeDown
|
||||
}
|
||||
}
|
@@ -1,4 +1,6 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Threading;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using ICSharpCode.SharpZipLib.GZip;
|
||||
using ICSharpCode.SharpZipLib.Tar;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
@@ -11,11 +13,13 @@ using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
@@ -40,6 +44,8 @@ namespace Ryujinx.Modules
|
||||
|
||||
private static readonly string[] WindowsDependencyDirs = Array.Empty<string>();
|
||||
|
||||
public static bool UpdateSuccessful { get; private set; }
|
||||
|
||||
public static async Task BeginParse(MainWindow mainWindow, bool showVersionUpToDate)
|
||||
{
|
||||
if (Running)
|
||||
@@ -198,11 +204,18 @@ namespace Ryujinx.Modules
|
||||
_buildSize = -1;
|
||||
}
|
||||
}
|
||||
|
||||
Dispatcher.UIThread.Post(async () =>
|
||||
{
|
||||
// Show a message asking the user if they want to update
|
||||
UpdaterWindow updateDialog = new(mainWindow, newVersion, _buildUrl);
|
||||
await updateDialog.ShowDialog(mainWindow);
|
||||
var shouldUpdate = await ContentDialogHelper.CreateChoiceDialog(LocaleManager.Instance["RyujinxUpdater"],
|
||||
LocaleManager.Instance["RyujinxUpdaterMessage"],
|
||||
$"{Program.Version} -> {newVersion}");
|
||||
|
||||
if (shouldUpdate)
|
||||
{
|
||||
UpdateRyujinx(mainWindow, _buildUrl);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -216,8 +229,10 @@ namespace Ryujinx.Modules
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void UpdateRyujinx(UpdaterWindow updateDialog, string downloadUrl)
|
||||
public static async void UpdateRyujinx(Window parent, string downloadUrl)
|
||||
{
|
||||
UpdateSuccessful = false;
|
||||
|
||||
// Empty update dir, although it shouldn't ever have anything inside it
|
||||
if (Directory.Exists(UpdateDir))
|
||||
{
|
||||
@@ -228,25 +243,56 @@ namespace Ryujinx.Modules
|
||||
|
||||
string updateFile = Path.Combine(UpdateDir, "update.bin");
|
||||
|
||||
// Download the update .zip
|
||||
updateDialog.MainText.Text = LocaleManager.Instance["UpdaterDownloading"];
|
||||
updateDialog.ProgressBar.Value = 0;
|
||||
updateDialog.ProgressBar.Maximum = 100;
|
||||
var taskDialog = new TaskDialog()
|
||||
{
|
||||
Header = LocaleManager.Instance["RyujinxUpdater"],
|
||||
SubHeader = LocaleManager.Instance["UpdaterDownloading"],
|
||||
IconSource = new SymbolIconSource { Symbol = Symbol.Download },
|
||||
Buttons = { },
|
||||
ShowProgressBar = true
|
||||
};
|
||||
|
||||
Task.Run(() =>
|
||||
taskDialog.XamlRoot = parent;
|
||||
|
||||
taskDialog.Opened += (s, e) =>
|
||||
{
|
||||
if (_buildSize >= 0)
|
||||
{
|
||||
DoUpdateWithMultipleThreads(updateDialog, downloadUrl, updateFile);
|
||||
DoUpdateWithMultipleThreads(taskDialog, downloadUrl, updateFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoUpdateWithSingleThread(updateDialog, downloadUrl, updateFile);
|
||||
DoUpdateWithSingleThread(taskDialog, downloadUrl, updateFile);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
await taskDialog.ShowAsync(true);
|
||||
|
||||
if (UpdateSuccessful)
|
||||
{
|
||||
var shouldRestart = await ContentDialogHelper.CreateChoiceDialog(LocaleManager.Instance["RyujinxUpdater"],
|
||||
LocaleManager.Instance["DialogUpdaterCompleteMessage"],
|
||||
LocaleManager.Instance["DialogUpdaterRestartMessage"]);
|
||||
|
||||
if (shouldRestart)
|
||||
{
|
||||
string ryuName = Path.GetFileName(Environment.ProcessPath);
|
||||
string ryuExe = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ryuName);
|
||||
var ryuArg = Environment.GetCommandLineArgs().Skip(1);
|
||||
|
||||
if (!OperatingSystem.IsWindows())
|
||||
{
|
||||
chmod(ryuExe, Convert.ToUInt32("0777", 8));
|
||||
}
|
||||
|
||||
Process.Start(ryuExe, ryuArg);
|
||||
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DoUpdateWithMultipleThreads(UpdaterWindow updateDialog, string downloadUrl, string updateFile)
|
||||
private static void DoUpdateWithMultipleThreads(TaskDialog taskDialog, string downloadUrl, string updateFile)
|
||||
{
|
||||
// Multi-Threaded Updater
|
||||
long chunkSize = _buildSize / ConnectionCount;
|
||||
@@ -290,7 +336,7 @@ namespace Ryujinx.Modules
|
||||
Interlocked.Exchange(ref progressPercentage[index], args.ProgressPercentage);
|
||||
Interlocked.Add(ref totalProgressPercentage, args.ProgressPercentage);
|
||||
|
||||
updateDialog.ProgressBar.Value = totalProgressPercentage / ConnectionCount;
|
||||
taskDialog.SetProgressBarState(totalProgressPercentage / ConnectionCount, TaskDialogProgressState.Normal);
|
||||
};
|
||||
|
||||
client.DownloadDataCompleted += (_, args) =>
|
||||
@@ -301,6 +347,8 @@ namespace Ryujinx.Modules
|
||||
{
|
||||
webClients[index].Dispose();
|
||||
|
||||
taskDialog.Hide();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -320,14 +368,14 @@ namespace Ryujinx.Modules
|
||||
|
||||
try
|
||||
{
|
||||
InstallUpdate(updateDialog, updateFile);
|
||||
InstallUpdate(taskDialog, updateFile);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, e.Message);
|
||||
Logger.Warning?.Print(LogClass.Application, "Multi-Threaded update failed, falling back to single-threaded updater.");
|
||||
|
||||
DoUpdateWithSingleThread(updateDialog, downloadUrl, updateFile);
|
||||
DoUpdateWithSingleThread(taskDialog, downloadUrl, updateFile);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -348,7 +396,7 @@ namespace Ryujinx.Modules
|
||||
webClients[j].CancelAsync();
|
||||
}
|
||||
|
||||
DoUpdateWithSingleThread(updateDialog, downloadUrl, updateFile);
|
||||
DoUpdateWithSingleThread(taskDialog, downloadUrl, updateFile);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -356,7 +404,7 @@ namespace Ryujinx.Modules
|
||||
}
|
||||
}
|
||||
|
||||
private static void DoUpdateWithSingleThreadWorker(UpdaterWindow updateDialog, string downloadUrl, string updateFile)
|
||||
private static void DoUpdateWithSingleThreadWorker(TaskDialog taskDialog, string downloadUrl, string updateFile)
|
||||
{
|
||||
using (HttpClient client = new HttpClient())
|
||||
{
|
||||
@@ -384,19 +432,26 @@ namespace Ryujinx.Modules
|
||||
|
||||
byteWritten += readSize;
|
||||
|
||||
updateDialog.ProgressBar.Value = ((double)byteWritten / totalBytes) * 100;
|
||||
taskDialog.SetProgressBarState(GetPercentage(byteWritten, totalBytes), TaskDialogProgressState.Normal);
|
||||
|
||||
updateFileStream.Write(buffer, 0, readSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InstallUpdate(updateDialog, updateFile);
|
||||
InstallUpdate(taskDialog, updateFile);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DoUpdateWithSingleThread(UpdaterWindow updateDialog, string downloadUrl, string updateFile)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static double GetPercentage(double value, double max)
|
||||
{
|
||||
Thread worker = new Thread(() => DoUpdateWithSingleThreadWorker(updateDialog, downloadUrl, updateFile));
|
||||
return max == 0 ? 0 : value / max * 100;
|
||||
}
|
||||
|
||||
private static void DoUpdateWithSingleThread(TaskDialog taskDialog, string downloadUrl, string updateFile)
|
||||
{
|
||||
Thread worker = new Thread(() => DoUpdateWithSingleThreadWorker(taskDialog, downloadUrl, updateFile));
|
||||
worker.Name = "Updater.SingleThreadWorker";
|
||||
worker.Start();
|
||||
}
|
||||
@@ -414,11 +469,11 @@ namespace Ryujinx.Modules
|
||||
}
|
||||
}
|
||||
|
||||
private static async void InstallUpdate(UpdaterWindow updateDialog, string updateFile)
|
||||
private static async void InstallUpdate(TaskDialog taskDialog, string updateFile)
|
||||
{
|
||||
// Extract Update
|
||||
updateDialog.MainText.Text = LocaleManager.Instance["UpdaterExtracting"];
|
||||
updateDialog.ProgressBar.Value = 0;
|
||||
taskDialog.SubHeader = LocaleManager.Instance["UpdaterExtracting"];
|
||||
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
|
||||
|
||||
if (OperatingSystem.IsLinux())
|
||||
{
|
||||
@@ -426,8 +481,6 @@ namespace Ryujinx.Modules
|
||||
using (Stream gzipStream = new GZipInputStream(inStream))
|
||||
using (TarInputStream tarStream = new TarInputStream(gzipStream, Encoding.ASCII))
|
||||
{
|
||||
updateDialog.ProgressBar.Maximum = inStream.Length;
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
TarEntry tarEntry;
|
||||
@@ -450,12 +503,12 @@ namespace Ryujinx.Modules
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
updateDialog.ProgressBar.Value += entry.Size;
|
||||
taskDialog.SetProgressBarState(GetPercentage(entry.Size, inStream.Length), TaskDialogProgressState.Normal);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
updateDialog.ProgressBar.Value = inStream.Length;
|
||||
taskDialog.SetProgressBarState(100, TaskDialogProgressState.Normal);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -463,12 +516,12 @@ namespace Ryujinx.Modules
|
||||
using (Stream inStream = File.OpenRead(updateFile))
|
||||
using (ZipFile zipFile = new ZipFile(inStream))
|
||||
{
|
||||
updateDialog.ProgressBar.Maximum = zipFile.Count;
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
double count = 0;
|
||||
foreach (ZipEntry zipEntry in zipFile)
|
||||
{
|
||||
count++;
|
||||
if (zipEntry.IsDirectory) continue;
|
||||
|
||||
string outPath = Path.Combine(UpdateDir, zipEntry.Name);
|
||||
@@ -485,7 +538,7 @@ namespace Ryujinx.Modules
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
updateDialog.ProgressBar.Value++;
|
||||
taskDialog.SetProgressBarState(GetPercentage(count, zipFile.Count), TaskDialogProgressState.Normal);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -497,22 +550,23 @@ namespace Ryujinx.Modules
|
||||
|
||||
List<string> allFiles = EnumerateFilesToDelete().ToList();
|
||||
|
||||
updateDialog.MainText.Text = LocaleManager.Instance["UpdaterRenaming"];
|
||||
updateDialog.ProgressBar.Value = 0;
|
||||
updateDialog.ProgressBar.Maximum = allFiles.Count;
|
||||
taskDialog.SubHeader = LocaleManager.Instance["UpdaterRenaming"];
|
||||
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
|
||||
|
||||
// Replace old files
|
||||
await Task.Run(() =>
|
||||
{
|
||||
double count = 0;
|
||||
foreach (string file in allFiles)
|
||||
{
|
||||
count++;
|
||||
try
|
||||
{
|
||||
File.Move(file, file + ".ryuold");
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
updateDialog.ProgressBar.Value++;
|
||||
taskDialog.SetProgressBarState(GetPercentage(count, allFiles.Count), TaskDialogProgressState.Normal);
|
||||
});
|
||||
}
|
||||
catch
|
||||
@@ -523,23 +577,20 @@ namespace Ryujinx.Modules
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
updateDialog.MainText.Text = LocaleManager.Instance["UpdaterAddingFiles"];
|
||||
updateDialog.ProgressBar.Value = 0;
|
||||
updateDialog.ProgressBar.Maximum = Directory.GetFiles(UpdatePublishDir, "*", SearchOption.AllDirectories).Length;
|
||||
taskDialog.SubHeader = LocaleManager.Instance["UpdaterAddingFiles"];
|
||||
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
|
||||
});
|
||||
|
||||
MoveAllFilesOver(UpdatePublishDir, HomeDir, updateDialog);
|
||||
MoveAllFilesOver(UpdatePublishDir, HomeDir, taskDialog);
|
||||
});
|
||||
|
||||
Directory.Delete(UpdateDir, true);
|
||||
|
||||
SetUnixPermissions();
|
||||
|
||||
updateDialog.MainText.Text = LocaleManager.Instance["DialogUpdaterCompleteMessage"];
|
||||
updateDialog.SecondaryText.Text = LocaleManager.Instance["DialogUpdaterRestartMessage"];
|
||||
UpdateSuccessful = true;
|
||||
|
||||
updateDialog.ProgressBar.IsVisible = false;
|
||||
updateDialog.ButtonBox.IsVisible = true;
|
||||
taskDialog.Hide();
|
||||
}
|
||||
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
@@ -618,8 +669,9 @@ namespace Ryujinx.Modules
|
||||
return files;
|
||||
}
|
||||
|
||||
private static void MoveAllFilesOver(string root, string dest, UpdaterWindow dialog)
|
||||
private static void MoveAllFilesOver(string root, string dest, TaskDialog taskDialog)
|
||||
{
|
||||
var total = Directory.GetFiles(root, "*", SearchOption.AllDirectories).Length;
|
||||
foreach (string directory in Directory.GetDirectories(root))
|
||||
{
|
||||
string dirName = Path.GetFileName(directory);
|
||||
@@ -629,16 +681,18 @@ namespace Ryujinx.Modules
|
||||
Directory.CreateDirectory(Path.Combine(dest, dirName));
|
||||
}
|
||||
|
||||
MoveAllFilesOver(directory, Path.Combine(dest, dirName), dialog);
|
||||
MoveAllFilesOver(directory, Path.Combine(dest, dirName), taskDialog);
|
||||
}
|
||||
|
||||
double count = 0;
|
||||
foreach (string file in Directory.GetFiles(root))
|
||||
{
|
||||
count++;
|
||||
File.Move(file, Path.Combine(dest, Path.GetFileName(file)), true);
|
||||
|
||||
Dispatcher.UIThread.InvokeAsync(() =>
|
||||
{
|
||||
dialog.ProgressBar.Value++;
|
||||
taskDialog.SetProgressBarState(GetPercentage(count, total), TaskDialogProgressState.Normal);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@
|
||||
<PackageReference Include="Silk.NET.Vulkan" Version="2.10.1" />
|
||||
<PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.10.1" />
|
||||
<PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.10.1" />
|
||||
<PackageReference Include="SPB" Version="0.0.4-build24" />
|
||||
<PackageReference Include="SPB" Version="0.0.4-build27" />
|
||||
<PackageReference Include="SharpZipLib" Version="1.3.3" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.4" />
|
||||
</ItemGroup>
|
||||
|
@@ -4,6 +4,7 @@ using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Threading;
|
||||
using FluentAvalonia.Core;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Ui.Models;
|
||||
@@ -27,7 +28,10 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
string secondaryButton,
|
||||
string closeButton,
|
||||
int iconSymbol,
|
||||
UserResult primaryButtonResult = UserResult.Ok)
|
||||
UserResult primaryButtonResult = UserResult.Ok,
|
||||
ManualResetEvent deferResetEvent = null,
|
||||
Func<Window, Task> doWhileDeferred = null,
|
||||
TypedEventHandler<ContentDialog, ContentDialogButtonClickEventArgs> deferCloseAction = null)
|
||||
{
|
||||
UserResult result = UserResult.None;
|
||||
|
||||
@@ -110,12 +114,19 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
contentDialog.SecondaryButtonCommand = MiniCommand.Create(() =>
|
||||
{
|
||||
result = UserResult.No;
|
||||
contentDialog.PrimaryButtonClick -= deferCloseAction;
|
||||
});
|
||||
contentDialog.CloseButtonCommand = MiniCommand.Create(() =>
|
||||
{
|
||||
result = UserResult.Cancel;
|
||||
contentDialog.PrimaryButtonClick -= deferCloseAction;
|
||||
});
|
||||
|
||||
if (deferResetEvent != null)
|
||||
{
|
||||
contentDialog.PrimaryButtonClick += deferCloseAction;
|
||||
}
|
||||
|
||||
await contentDialog.ShowAsync(ContentDialogPlacement.Popup);
|
||||
|
||||
overlay?.Close();
|
||||
@@ -143,35 +154,20 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
Func<Window, Task> doWhileDeferred = null)
|
||||
{
|
||||
bool startedDeferring = false;
|
||||
|
||||
UserResult result = UserResult.None;
|
||||
|
||||
ContentDialog contentDialog = new ContentDialog
|
||||
{
|
||||
Title = title,
|
||||
PrimaryButtonText = primaryButton,
|
||||
SecondaryButtonText = secondaryButton,
|
||||
CloseButtonText = closeButton,
|
||||
Content = CreateDialogTextContent(primaryText, secondaryText, iconSymbol),
|
||||
PrimaryButtonCommand = MiniCommand.Create(() =>
|
||||
{
|
||||
result = primaryButton == LocaleManager.Instance["InputDialogYes"] ? UserResult.Yes : UserResult.Ok;
|
||||
}),
|
||||
};
|
||||
contentDialog.SecondaryButtonCommand = MiniCommand.Create(() =>
|
||||
{
|
||||
contentDialog.PrimaryButtonClick -= DeferClose;
|
||||
result = UserResult.No;
|
||||
});
|
||||
contentDialog.CloseButtonCommand = MiniCommand.Create(() =>
|
||||
{
|
||||
contentDialog.PrimaryButtonClick -= DeferClose;
|
||||
result = UserResult.Cancel;
|
||||
});
|
||||
contentDialog.PrimaryButtonClick += DeferClose;
|
||||
await contentDialog.ShowAsync(ContentDialogPlacement.Popup);
|
||||
|
||||
return result;
|
||||
return await ShowContentDialog(
|
||||
title,
|
||||
primaryText,
|
||||
secondaryText,
|
||||
primaryButton,
|
||||
secondaryButton,
|
||||
closeButton,
|
||||
iconSymbol,
|
||||
primaryButton == LocaleManager.Instance["InputDialogYes"] ? UserResult.Yes : UserResult.Ok,
|
||||
deferResetEvent,
|
||||
doWhileDeferred,
|
||||
DeferClose);
|
||||
|
||||
async void DeferClose(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
@@ -180,7 +176,7 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
return;
|
||||
}
|
||||
|
||||
contentDialog.PrimaryButtonClick -= DeferClose;
|
||||
sender.PrimaryButtonClick -= DeferClose;
|
||||
|
||||
startedDeferring = true;
|
||||
|
||||
@@ -188,7 +184,7 @@ namespace Ryujinx.Ava.Ui.Controls
|
||||
|
||||
result = primaryButton == LocaleManager.Instance["InputDialogYes"] ? UserResult.Yes : UserResult.Ok;
|
||||
|
||||
contentDialog.PrimaryButtonClick -= DeferClose;
|
||||
sender.PrimaryButtonClick -= DeferClose;
|
||||
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
Task.Run(() =>
|
||||
|
@@ -295,8 +295,6 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||
if (_validTzRegions.Contains(location))
|
||||
{
|
||||
TimeZone = location;
|
||||
|
||||
OnPropertyChanged(nameof(TimeZone));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -6,7 +6,6 @@
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:window="clr-namespace:Ryujinx.Ava.Ui.Windows"
|
||||
Title="Ryujinx - About"
|
||||
Width="850"
|
||||
Height="550"
|
||||
MinWidth="500"
|
||||
|
@@ -164,7 +164,7 @@
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="pl_PL"
|
||||
Header="Polish" />
|
||||
Header="Polski" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding ChangeLanguage}"
|
||||
CommandParameter="ru_RU"
|
||||
|
@@ -257,6 +257,22 @@
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysVolumeUpHotkey}" Width="230" />
|
||||
<ToggleButton Width="90" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock
|
||||
Text="{Binding KeyboardHotkeys.VolumeUp, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysVolumeDownHotkey}" Width="230" />
|
||||
<ToggleButton Width="90" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock
|
||||
Text="{Binding KeyboardHotkeys.VolumeDown, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</ScrollViewer>
|
||||
|
@@ -37,7 +37,7 @@ namespace Ryujinx.Ava.Ui.Windows
|
||||
InitializeComponent();
|
||||
Load();
|
||||
|
||||
FuncMultiValueConverter<string, string> converter = new(parts => string.Format("{0} {1} {2}", parts.ToArray()));
|
||||
FuncMultiValueConverter<string, string> converter = new(parts => string.Format("{0} {1} {2}", parts.ToArray()).Trim());
|
||||
MultiBinding tzMultiBinding = new() { Converter = converter };
|
||||
tzMultiBinding.Bindings.Add(new Binding("UtcDifference"));
|
||||
tzMultiBinding.Bindings.Add(new Binding("Location"));
|
||||
|
@@ -1,66 +0,0 @@
|
||||
<window:StyleableWindow
|
||||
x:Class="Ryujinx.Ava.Ui.Windows.UpdaterWindow"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:window="clr-namespace:Ryujinx.Ava.Ui.Windows"
|
||||
Title="Ryujinx Updater"
|
||||
Width="500"
|
||||
Height="500"
|
||||
MinWidth="500"
|
||||
MinHeight="500"
|
||||
d:DesignHeight="350"
|
||||
d:DesignWidth="400"
|
||||
CanResize="False"
|
||||
SizeToContent="Height"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
mc:Ignorable="d">
|
||||
<Grid
|
||||
Margin="20"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
Name="MainText"
|
||||
Grid.Row="1"
|
||||
Height="20"
|
||||
HorizontalAlignment="Stretch"
|
||||
TextAlignment="Center" />
|
||||
<TextBlock
|
||||
Name="SecondaryText"
|
||||
Grid.Row="2"
|
||||
Height="20"
|
||||
HorizontalAlignment="Stretch"
|
||||
TextAlignment="Center" />
|
||||
<ProgressBar
|
||||
Name="ProgressBar"
|
||||
Grid.Row="3"
|
||||
Margin="20"
|
||||
HorizontalAlignment="Stretch"
|
||||
IsVisible="False"
|
||||
Maximum="100"
|
||||
Minimum="0" />
|
||||
<StackPanel
|
||||
Name="ButtonBox"
|
||||
Grid.Row="4"
|
||||
HorizontalAlignment="Right"
|
||||
IsVisible="False"
|
||||
Orientation="Horizontal"
|
||||
Spacing="20">
|
||||
<Button MinWidth="50" Command="{Binding YesPressed}">
|
||||
<TextBlock Text="{locale:Locale InputDialogYes}" TextAlignment="Center" />
|
||||
</Button>
|
||||
<Button MinWidth="50" Command="{Binding NoPressed}">
|
||||
<TextBlock Text="{locale:Locale InputDialogNo}" TextAlignment="Center" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</window:StyleableWindow>
|
@@ -1,73 +0,0 @@
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Modules;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Ava.Ui.Windows
|
||||
{
|
||||
public partial class UpdaterWindow : StyleableWindow
|
||||
{
|
||||
private readonly string _buildUrl;
|
||||
private readonly MainWindow _mainWindow;
|
||||
private readonly Version _newVersion;
|
||||
private bool _restartQuery;
|
||||
|
||||
public UpdaterWindow()
|
||||
{
|
||||
DataContext = this;
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
Title = LocaleManager.Instance["RyujinxUpdater"];
|
||||
}
|
||||
|
||||
public UpdaterWindow(MainWindow mainWindow, Version newVersion, string buildUrl) : this()
|
||||
{
|
||||
_mainWindow = mainWindow;
|
||||
_newVersion = newVersion;
|
||||
_buildUrl = buildUrl;
|
||||
}
|
||||
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
private static extern int chmod(string path, uint mode);
|
||||
|
||||
public void YesPressed()
|
||||
{
|
||||
if (_restartQuery)
|
||||
{
|
||||
string ryuName = OperatingSystem.IsWindows() ? "Ryujinx.Ava.exe" : "Ryujinx.Ava";
|
||||
string ryuExe = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ryuName);
|
||||
string ryuArg = string.Join(" ", Environment.GetCommandLineArgs().AsEnumerable().Skip(1).ToArray());
|
||||
|
||||
if (!OperatingSystem.IsWindows())
|
||||
{
|
||||
chmod(ryuExe, 0777);
|
||||
}
|
||||
|
||||
Process.Start(ryuExe, ryuArg);
|
||||
|
||||
Environment.Exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ButtonBox.IsVisible = false;
|
||||
ProgressBar.IsVisible = true;
|
||||
|
||||
SecondaryText.Text = "";
|
||||
_restartQuery = true;
|
||||
|
||||
Updater.UpdateRyujinx(this, _buildUrl);
|
||||
}
|
||||
}
|
||||
|
||||
public void NoPressed()
|
||||
{
|
||||
_mainWindow.UpdateMenuItem.IsEnabled = true;
|
||||
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
@@ -9,5 +9,7 @@
|
||||
public Key ToggleMute { get; set; }
|
||||
public Key ResScaleUp { get; set; }
|
||||
public Key ResScaleDown { get; set; }
|
||||
public Key VolumeUp { get; set; }
|
||||
public Key VolumeDown { get; set; }
|
||||
}
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@ namespace Ryujinx.Common.Logging
|
||||
ServiceBsd,
|
||||
ServiceBtm,
|
||||
ServiceCaps,
|
||||
ServiceFatal,
|
||||
ServiceFriend,
|
||||
ServiceFs,
|
||||
ServiceHid,
|
||||
|
89
Ryujinx.Common/Memory/SpanOrArray.cs
Normal file
89
Ryujinx.Common/Memory/SpanOrArray.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Common.Memory
|
||||
{
|
||||
/// <summary>
|
||||
/// A struct that can represent both a Span and Array.
|
||||
/// This is useful to keep the Array representation when possible to avoid copies.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Element Type</typeparam>
|
||||
public ref struct SpanOrArray<T> where T : unmanaged
|
||||
{
|
||||
public readonly T[] Array;
|
||||
public readonly ReadOnlySpan<T> Span;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new SpanOrArray from an array.
|
||||
/// </summary>
|
||||
/// <param name="array">Array to store</param>
|
||||
public SpanOrArray(T[] array)
|
||||
{
|
||||
Array = array;
|
||||
Span = ReadOnlySpan<T>.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new SpanOrArray from a readonly span.
|
||||
/// </summary>
|
||||
/// <param name="array">Span to store</param>
|
||||
public SpanOrArray(ReadOnlySpan<T> span)
|
||||
{
|
||||
Array = null;
|
||||
Span = span;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the contained array, or convert the span if necessary.
|
||||
/// </summary>
|
||||
/// <returns>An array containing the data</returns>
|
||||
public T[] ToArray()
|
||||
{
|
||||
return Array ?? Span.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a ReadOnlySpan from either the array or ReadOnlySpan.
|
||||
/// </summary>
|
||||
/// <returns>A ReadOnlySpan containing the data</returns>
|
||||
public ReadOnlySpan<T> AsSpan()
|
||||
{
|
||||
return Array ?? Span;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cast an array to a SpanOrArray.
|
||||
/// </summary>
|
||||
/// <param name="array">Source array</param>
|
||||
public static implicit operator SpanOrArray<T>(T[] array)
|
||||
{
|
||||
return new SpanOrArray<T>(array);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cast a ReadOnlySpan to a SpanOrArray.
|
||||
/// </summary>
|
||||
/// <param name="span">Source ReadOnlySpan</param>
|
||||
public static implicit operator SpanOrArray<T>(ReadOnlySpan<T> span)
|
||||
{
|
||||
return new SpanOrArray<T>(span);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cast a Span to a SpanOrArray.
|
||||
/// </summary>
|
||||
/// <param name="span">Source Span</param>
|
||||
public static implicit operator SpanOrArray<T>(Span<T> span)
|
||||
{
|
||||
return new SpanOrArray<T>(span);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cast a SpanOrArray to a ReadOnlySpan
|
||||
/// </summary>
|
||||
/// <param name="spanOrArray">Source SpanOrArray</param>
|
||||
public static implicit operator ReadOnlySpan<T>(SpanOrArray<T> spanOrArray)
|
||||
{
|
||||
return spanOrArray.AsSpan();
|
||||
}
|
||||
}
|
||||
}
|
@@ -129,7 +129,7 @@ namespace Ryujinx.Common
|
||||
|
||||
private static (Assembly, string) ResolveManifestPath(string filename)
|
||||
{
|
||||
var segments = filename.Split(new[] { '/' }, 2, StringSplitOptions.RemoveEmptyEntries);
|
||||
var segments = filename.Split('/', 2, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (segments.Length >= 2)
|
||||
{
|
||||
|
@@ -1,3 +1,4 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
@@ -17,9 +18,9 @@ namespace Ryujinx.Graphics.GAL
|
||||
ReadOnlySpan<byte> GetData();
|
||||
ReadOnlySpan<byte> GetData(int layer, int level);
|
||||
|
||||
void SetData(ReadOnlySpan<byte> data);
|
||||
void SetData(ReadOnlySpan<byte> data, int layer, int level);
|
||||
void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region);
|
||||
void SetData(SpanOrArray<byte> data);
|
||||
void SetData(SpanOrArray<byte> data, int layer, int level);
|
||||
void SetData(SpanOrArray<byte> data, int layer, int level, Rectangle<int> region);
|
||||
void SetStorage(BufferRange buffer);
|
||||
void Release();
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Commands.Texture;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Commands.Texture;
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||
using System;
|
||||
|
||||
@@ -107,19 +108,19 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
||||
}
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data)
|
||||
public void SetData(SpanOrArray<byte> data)
|
||||
{
|
||||
_renderer.New<TextureSetDataCommand>().Set(Ref(this), Ref(data.ToArray()));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level)
|
||||
public void SetData(SpanOrArray<byte> data, int layer, int level)
|
||||
{
|
||||
_renderer.New<TextureSetDataSliceCommand>().Set(Ref(this), Ref(data.ToArray()), layer, level);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
|
||||
public void SetData(SpanOrArray<byte> data, int layer, int level, Rectangle<int> region)
|
||||
{
|
||||
_renderer.New<TextureSetDataSliceRegionCommand>().Set(Ref(this), Ref(data.ToArray()), layer, level, region);
|
||||
_renderer.QueueCommand();
|
||||
|
@@ -229,7 +229,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||
|
||||
if (target != null)
|
||||
{
|
||||
ReadOnlySpan<byte> data;
|
||||
byte[] data;
|
||||
if (srcLinear)
|
||||
{
|
||||
data = LayoutConverter.ConvertLinearStridedToLinear(
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
using Ryujinx.Graphics.Texture;
|
||||
@@ -136,11 +137,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
/// </summary>
|
||||
public LinkedListNode<Texture> CacheNode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Event to fire when texture data is disposed.
|
||||
/// </summary>
|
||||
public event Action<Texture> Disposed;
|
||||
|
||||
/// <summary>
|
||||
/// Physical memory ranges where the texture data is located.
|
||||
/// </summary>
|
||||
@@ -720,9 +716,9 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
}
|
||||
}
|
||||
|
||||
data = ConvertToHostCompatibleFormat(data);
|
||||
SpanOrArray<byte> result = ConvertToHostCompatibleFormat(data);
|
||||
|
||||
HostTexture.SetData(data);
|
||||
HostTexture.SetData(result);
|
||||
|
||||
_hasData = true;
|
||||
}
|
||||
@@ -731,7 +727,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
/// Uploads new texture data to the host GPU.
|
||||
/// </summary>
|
||||
/// <param name="data">New data</param>
|
||||
public void SetData(ReadOnlySpan<byte> data)
|
||||
public void SetData(SpanOrArray<byte> data)
|
||||
{
|
||||
BlacklistScale();
|
||||
|
||||
@@ -750,7 +746,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
/// <param name="data">New data</param>
|
||||
/// <param name="layer">Target layer</param>
|
||||
/// <param name="level">Target level</param>
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level)
|
||||
public void SetData(SpanOrArray<byte> data, int layer, int level)
|
||||
{
|
||||
BlacklistScale();
|
||||
|
||||
@@ -786,7 +782,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
/// <param name="level">Mip level to convert</param>
|
||||
/// <param name="single">True to convert a single slice</param>
|
||||
/// <returns>Converted data</returns>
|
||||
public ReadOnlySpan<byte> ConvertToHostCompatibleFormat(ReadOnlySpan<byte> data, int level = 0, bool single = false)
|
||||
public SpanOrArray<byte> ConvertToHostCompatibleFormat(ReadOnlySpan<byte> data, int level = 0, bool single = false)
|
||||
{
|
||||
int width = Info.Width;
|
||||
int height = Info.Height;
|
||||
@@ -799,9 +795,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
height = Math.Max(height >> level, 1);
|
||||
depth = Math.Max(depth >> level, 1);
|
||||
|
||||
SpanOrArray<byte> result;
|
||||
|
||||
if (Info.IsLinear)
|
||||
{
|
||||
data = LayoutConverter.ConvertLinearStridedToLinear(
|
||||
result = LayoutConverter.ConvertLinearStridedToLinear(
|
||||
width,
|
||||
height,
|
||||
Info.FormatInfo.BlockWidth,
|
||||
@@ -813,7 +811,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
}
|
||||
else
|
||||
{
|
||||
data = LayoutConverter.ConvertBlockLinearToLinear(
|
||||
result = LayoutConverter.ConvertBlockLinearToLinear(
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
@@ -836,7 +834,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
if (!_context.Capabilities.SupportsAstcCompression && Format.IsAstc())
|
||||
{
|
||||
if (!AstcDecoder.TryDecodeToRgba8P(
|
||||
data.ToArray(),
|
||||
result.ToArray(),
|
||||
Info.FormatInfo.BlockWidth,
|
||||
Info.FormatInfo.BlockHeight,
|
||||
width,
|
||||
@@ -856,11 +854,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
decoded = BCnEncoder.EncodeBC7(decoded, width, height, depth, levels, layers);
|
||||
}
|
||||
|
||||
data = decoded;
|
||||
result = decoded;
|
||||
}
|
||||
else if (!_context.Capabilities.SupportsR4G4Format && Format == Format.R4G4Unorm)
|
||||
{
|
||||
data = PixelConverter.ConvertR4G4ToR4G4B4A4(data);
|
||||
result = PixelConverter.ConvertR4G4ToR4G4B4A4(result);
|
||||
}
|
||||
else if (!TextureCompatibility.HostSupportsBcFormat(Format, Target, _context.Capabilities))
|
||||
{
|
||||
@@ -868,36 +866,36 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
{
|
||||
case Format.Bc1RgbaSrgb:
|
||||
case Format.Bc1RgbaUnorm:
|
||||
data = BCnDecoder.DecodeBC1(data, width, height, depth, levels, layers);
|
||||
result = BCnDecoder.DecodeBC1(result, width, height, depth, levels, layers);
|
||||
break;
|
||||
case Format.Bc2Srgb:
|
||||
case Format.Bc2Unorm:
|
||||
data = BCnDecoder.DecodeBC2(data, width, height, depth, levels, layers);
|
||||
result = BCnDecoder.DecodeBC2(result, width, height, depth, levels, layers);
|
||||
break;
|
||||
case Format.Bc3Srgb:
|
||||
case Format.Bc3Unorm:
|
||||
data = BCnDecoder.DecodeBC3(data, width, height, depth, levels, layers);
|
||||
result = BCnDecoder.DecodeBC3(result, width, height, depth, levels, layers);
|
||||
break;
|
||||
case Format.Bc4Snorm:
|
||||
case Format.Bc4Unorm:
|
||||
data = BCnDecoder.DecodeBC4(data, width, height, depth, levels, layers, Format == Format.Bc4Snorm);
|
||||
result = BCnDecoder.DecodeBC4(result, width, height, depth, levels, layers, Format == Format.Bc4Snorm);
|
||||
break;
|
||||
case Format.Bc5Snorm:
|
||||
case Format.Bc5Unorm:
|
||||
data = BCnDecoder.DecodeBC5(data, width, height, depth, levels, layers, Format == Format.Bc5Snorm);
|
||||
result = BCnDecoder.DecodeBC5(result, width, height, depth, levels, layers, Format == Format.Bc5Snorm);
|
||||
break;
|
||||
case Format.Bc6HSfloat:
|
||||
case Format.Bc6HUfloat:
|
||||
data = BCnDecoder.DecodeBC6(data, width, height, depth, levels, layers, Format == Format.Bc6HSfloat);
|
||||
result = BCnDecoder.DecodeBC6(result, width, height, depth, levels, layers, Format == Format.Bc6HSfloat);
|
||||
break;
|
||||
case Format.Bc7Srgb:
|
||||
case Format.Bc7Unorm:
|
||||
data = BCnDecoder.DecodeBC7(data, width, height, depth, levels, layers);
|
||||
result = BCnDecoder.DecodeBC7(result, width, height, depth, levels, layers);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1445,7 +1443,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
DisposeTextures();
|
||||
|
||||
HostTexture = hostTexture;
|
||||
InvalidatedSequence++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1600,6 +1597,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
/// </summary>
|
||||
private void DisposeTextures()
|
||||
{
|
||||
InvalidatedSequence++;
|
||||
|
||||
_currentData = null;
|
||||
HostTexture.Release();
|
||||
|
||||
@@ -1634,8 +1633,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
{
|
||||
DisposeTextures();
|
||||
|
||||
Disposed?.Invoke(this);
|
||||
|
||||
if (Group.Storage == this)
|
||||
{
|
||||
Group.Dispose();
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Ryujinx.Cpu.Tracking;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Cpu.Tracking;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
using Ryujinx.Graphics.Texture;
|
||||
@@ -348,9 +349,9 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||
|
||||
ReadOnlySpan<byte> data = _physicalMemory.GetSpan(Storage.Range.GetSlice((ulong)offset, (ulong)size));
|
||||
|
||||
data = Storage.ConvertToHostCompatibleFormat(data, info.BaseLevel, true);
|
||||
SpanOrArray<byte> result = Storage.ConvertToHostCompatibleFormat(data, info.BaseLevel, true);
|
||||
|
||||
Storage.SetData(data, info.BaseLayer, info.BaseLevel);
|
||||
Storage.SetData(result, info.BaseLayer, info.BaseLevel);
|
||||
|
||||
offsetIndex++;
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||
private const ushort FileFormatVersionMajor = 1;
|
||||
private const ushort FileFormatVersionMinor = 2;
|
||||
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
||||
private const uint CodeGenVersion = 3697;
|
||||
private const uint CodeGenVersion = 3781;
|
||||
|
||||
private const string SharedTocFileName = "shared.toc";
|
||||
private const string SharedDataFileName = "shared.data";
|
||||
|
@@ -123,7 +123,8 @@ namespace Ryujinx.Graphics.Gpu
|
||||
/// <param name="releaseCallback">Texture release callback</param>
|
||||
/// <param name="userObj">User defined object passed to the release callback</param>
|
||||
/// <exception cref="ArgumentException">Thrown when <paramref name="pid"/> is invalid</exception>
|
||||
public void EnqueueFrameThreadSafe(
|
||||
/// <returns>True if the frame was added to the queue, false otherwise</returns>
|
||||
public bool EnqueueFrameThreadSafe(
|
||||
ulong pid,
|
||||
ulong address,
|
||||
int width,
|
||||
@@ -140,7 +141,7 @@ namespace Ryujinx.Graphics.Gpu
|
||||
{
|
||||
if (!_context.PhysicalMemoryRegistry.TryGetValue(pid, out var physicalMemory))
|
||||
{
|
||||
throw new ArgumentException("The PID is invalid or the process was not registered", nameof(pid));
|
||||
return false;
|
||||
}
|
||||
|
||||
FormatInfo formatInfo = new FormatInfo(format, 1, 1, bytesPerPixel, 4);
|
||||
@@ -184,6 +185,8 @@ namespace Ryujinx.Graphics.Gpu
|
||||
acquireCallback,
|
||||
releaseCallback,
|
||||
userObj));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using System;
|
||||
|
||||
@@ -48,17 +49,19 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
return GetData();
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data)
|
||||
public void SetData(SpanOrArray<byte> data)
|
||||
{
|
||||
Buffer.SetData(_buffer, _bufferOffset, data.Slice(0, Math.Min(data.Length, _bufferSize)));
|
||||
var dataSpan = data.AsSpan();
|
||||
|
||||
Buffer.SetData(_buffer, _bufferOffset, dataSpan.Slice(0, Math.Min(dataSpan.Length, _bufferSize)));
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level)
|
||||
public void SetData(SpanOrArray<byte> data, int layer, int level)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
|
||||
public void SetData(SpanOrArray<byte> data, int layer, int level, Rectangle<int> region)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using System;
|
||||
|
||||
@@ -317,32 +318,36 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
}
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data)
|
||||
public void SetData(SpanOrArray<byte> data)
|
||||
{
|
||||
var dataSpan = data.AsSpan();
|
||||
|
||||
if (Format == Format.S8UintD24Unorm)
|
||||
{
|
||||
data = FormatConverter.ConvertS8D24ToD24S8(data);
|
||||
dataSpan = FormatConverter.ConvertS8D24ToD24S8(dataSpan);
|
||||
}
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* ptr = data)
|
||||
fixed (byte* ptr = dataSpan)
|
||||
{
|
||||
ReadFrom((IntPtr)ptr, data.Length);
|
||||
ReadFrom((IntPtr)ptr, dataSpan.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level)
|
||||
public void SetData(SpanOrArray<byte> data, int layer, int level)
|
||||
{
|
||||
var dataSpan = data.AsSpan();
|
||||
|
||||
if (Format == Format.S8UintD24Unorm)
|
||||
{
|
||||
data = FormatConverter.ConvertS8D24ToD24S8(data);
|
||||
dataSpan = FormatConverter.ConvertS8D24ToD24S8(dataSpan);
|
||||
}
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* ptr = data)
|
||||
fixed (byte* ptr = dataSpan)
|
||||
{
|
||||
int width = Math.Max(Info.Width >> level, 1);
|
||||
int height = Math.Max(Info.Height >> level, 1);
|
||||
@@ -352,11 +357,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
}
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
|
||||
public void SetData(SpanOrArray<byte> data, int layer, int level, Rectangle<int> region)
|
||||
{
|
||||
var dataSpan = data.AsSpan();
|
||||
|
||||
if (Format == Format.S8UintD24Unorm)
|
||||
{
|
||||
data = FormatConverter.ConvertS8D24ToD24S8(data);
|
||||
dataSpan = FormatConverter.ConvertS8D24ToD24S8(dataSpan);
|
||||
}
|
||||
|
||||
int wInBlocks = BitUtils.DivRoundUp(region.Width, Info.BlockWidth);
|
||||
@@ -364,7 +371,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* ptr = data)
|
||||
fixed (byte* ptr = dataSpan)
|
||||
{
|
||||
ReadFrom2D(
|
||||
(IntPtr)ptr,
|
||||
|
@@ -2,6 +2,7 @@ using Ryujinx.Common;
|
||||
using Ryujinx.Graphics.Shader.StructuredIr;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
@@ -163,9 +164,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
}
|
||||
else if (context.Config.Stage == ShaderStage.TessellationEvaluation)
|
||||
{
|
||||
bool tessCw = context.Config.GpuAccessor.QueryTessCw();
|
||||
|
||||
if (context.Config.Options.TargetApi == TargetApi.Vulkan)
|
||||
{
|
||||
// We invert the front face on Vulkan backend, so we need to do that here aswell.
|
||||
tessCw = !tessCw;
|
||||
}
|
||||
|
||||
string patchType = context.Config.GpuAccessor.QueryTessPatchType().ToGlsl();
|
||||
string spacing = context.Config.GpuAccessor.QueryTessSpacing().ToGlsl();
|
||||
string windingOrder = context.Config.GpuAccessor.QueryTessCw() ? "cw" : "ccw";
|
||||
string windingOrder = tessCw ? "cw" : "ccw";
|
||||
|
||||
context.AppendLine($"layout ({patchType}, {spacing}, {windingOrder}) in;");
|
||||
context.AppendLine();
|
||||
@@ -185,14 +194,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
if (context.Config.UsedInputAttributesPerPatch != 0)
|
||||
if (context.Config.UsedInputAttributesPerPatch.Count != 0)
|
||||
{
|
||||
DeclareInputAttributesPerPatch(context, context.Config.UsedInputAttributesPerPatch);
|
||||
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
if (context.Config.UsedOutputAttributesPerPatch != 0)
|
||||
if (context.Config.UsedOutputAttributesPerPatch.Count != 0)
|
||||
{
|
||||
DeclareUsedOutputAttributesPerPatch(context, context.Config.UsedOutputAttributesPerPatch);
|
||||
|
||||
@@ -248,7 +257,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
DeclareSupportUniformBlock(context, context.Config.Stage, scaleElements);
|
||||
|
||||
if (context.Config.UsedFeatures.HasFlag(FeatureFlags.IntegerSampling))
|
||||
if (context.Config.UsedFeatures.HasFlag(FeatureFlags.IntegerSampling) && scaleElements != 0)
|
||||
{
|
||||
AppendHelperFunction(context, $"Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_{stage}.glsl");
|
||||
context.AppendLine();
|
||||
@@ -509,13 +518,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeclareInputAttributesPerPatch(CodeGenContext context, int usedAttributes)
|
||||
private static void DeclareInputAttributesPerPatch(CodeGenContext context, HashSet<int> attrs)
|
||||
{
|
||||
while (usedAttributes != 0)
|
||||
foreach (int attr in attrs.OrderBy(x => x))
|
||||
{
|
||||
int index = BitOperations.TrailingZeroCount(usedAttributes);
|
||||
DeclareInputAttributePerPatch(context, index);
|
||||
usedAttributes &= ~(1 << index);
|
||||
DeclareInputAttributePerPatch(context, attr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -566,16 +573,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
private static void DeclareInputAttributePerPatch(CodeGenContext context, int attr)
|
||||
{
|
||||
string layout = string.Empty;
|
||||
|
||||
if (context.Config.Options.TargetApi == TargetApi.Vulkan)
|
||||
{
|
||||
layout = $"layout (location = {32 + attr}) ";
|
||||
}
|
||||
|
||||
int location = context.Config.GetPerPatchAttributeLocation(attr);
|
||||
string name = $"{DefaultNames.PerPatchAttributePrefix}{attr}";
|
||||
|
||||
context.AppendLine($"{layout}patch in vec4 {name};");
|
||||
context.AppendLine($"layout (location = {location}) patch in vec4 {name};");
|
||||
}
|
||||
|
||||
private static void DeclareOutputAttributes(CodeGenContext context, StructuredProgramInfo info)
|
||||
@@ -624,28 +625,20 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeclareUsedOutputAttributesPerPatch(CodeGenContext context, int usedAttributes)
|
||||
private static void DeclareUsedOutputAttributesPerPatch(CodeGenContext context, HashSet<int> attrs)
|
||||
{
|
||||
while (usedAttributes != 0)
|
||||
foreach (int attr in attrs.OrderBy(x => x))
|
||||
{
|
||||
int index = BitOperations.TrailingZeroCount(usedAttributes);
|
||||
DeclareOutputAttributePerPatch(context, index);
|
||||
usedAttributes &= ~(1 << index);
|
||||
DeclareOutputAttributePerPatch(context, attr);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeclareOutputAttributePerPatch(CodeGenContext context, int attr)
|
||||
{
|
||||
string layout = string.Empty;
|
||||
|
||||
if (context.Config.Options.TargetApi == TargetApi.Vulkan)
|
||||
{
|
||||
layout = $"layout (location = {32 + attr}) ";
|
||||
}
|
||||
|
||||
int location = context.Config.GetPerPatchAttributeLocation(attr);
|
||||
string name = $"{DefaultNames.PerPatchAttributePrefix}{attr}";
|
||||
|
||||
context.AppendLine($"{layout}patch out vec4 {name};");
|
||||
context.AppendLine($"layout (location = {location}) patch out vec4 {name};");
|
||||
}
|
||||
|
||||
private static void DeclareSupportUniformBlock(CodeGenContext context, ShaderStage stage, int scaleElements)
|
||||
|
@@ -28,33 +28,27 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
private static Dictionary<int, BuiltInAttribute> _builtInAttributes = new Dictionary<int, BuiltInAttribute>()
|
||||
{
|
||||
{ AttributeConsts.TessLevelOuter0, new BuiltInAttribute("gl_TessLevelOuter[0]", VariableType.F32) },
|
||||
{ AttributeConsts.TessLevelOuter1, new BuiltInAttribute("gl_TessLevelOuter[1]", VariableType.F32) },
|
||||
{ AttributeConsts.TessLevelOuter2, new BuiltInAttribute("gl_TessLevelOuter[2]", VariableType.F32) },
|
||||
{ AttributeConsts.TessLevelOuter3, new BuiltInAttribute("gl_TessLevelOuter[3]", VariableType.F32) },
|
||||
{ AttributeConsts.TessLevelInner0, new BuiltInAttribute("gl_TessLevelInner[0]", VariableType.F32) },
|
||||
{ AttributeConsts.TessLevelInner1, new BuiltInAttribute("gl_TessLevelInner[1]", VariableType.F32) },
|
||||
{ AttributeConsts.Layer, new BuiltInAttribute("gl_Layer", VariableType.S32) },
|
||||
{ AttributeConsts.PointSize, new BuiltInAttribute("gl_PointSize", VariableType.F32) },
|
||||
{ AttributeConsts.PositionX, new BuiltInAttribute("gl_Position.x", VariableType.F32) },
|
||||
{ AttributeConsts.PositionY, new BuiltInAttribute("gl_Position.y", VariableType.F32) },
|
||||
{ AttributeConsts.PositionZ, new BuiltInAttribute("gl_Position.z", VariableType.F32) },
|
||||
{ AttributeConsts.PositionW, new BuiltInAttribute("gl_Position.w", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance0, new BuiltInAttribute("gl_ClipDistance[0]", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance1, new BuiltInAttribute("gl_ClipDistance[1]", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance2, new BuiltInAttribute("gl_ClipDistance[2]", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance3, new BuiltInAttribute("gl_ClipDistance[3]", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance4, new BuiltInAttribute("gl_ClipDistance[4]", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance5, new BuiltInAttribute("gl_ClipDistance[5]", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance6, new BuiltInAttribute("gl_ClipDistance[6]", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance7, new BuiltInAttribute("gl_ClipDistance[7]", VariableType.F32) },
|
||||
{ AttributeConsts.PointCoordX, new BuiltInAttribute("gl_PointCoord.x", VariableType.F32) },
|
||||
{ AttributeConsts.PointCoordY, new BuiltInAttribute("gl_PointCoord.y", VariableType.F32) },
|
||||
{ AttributeConsts.TessCoordX, new BuiltInAttribute("gl_TessCoord.x", VariableType.F32) },
|
||||
{ AttributeConsts.TessCoordY, new BuiltInAttribute("gl_TessCoord.y", VariableType.F32) },
|
||||
{ AttributeConsts.InstanceId, new BuiltInAttribute("gl_InstanceID", VariableType.S32) },
|
||||
{ AttributeConsts.VertexId, new BuiltInAttribute("gl_VertexID", VariableType.S32) },
|
||||
{ AttributeConsts.FrontFacing, new BuiltInAttribute("gl_FrontFacing", VariableType.Bool) },
|
||||
{ AttributeConsts.Layer, new BuiltInAttribute("gl_Layer", VariableType.S32) },
|
||||
{ AttributeConsts.PointSize, new BuiltInAttribute("gl_PointSize", VariableType.F32) },
|
||||
{ AttributeConsts.PositionX, new BuiltInAttribute("gl_Position.x", VariableType.F32) },
|
||||
{ AttributeConsts.PositionY, new BuiltInAttribute("gl_Position.y", VariableType.F32) },
|
||||
{ AttributeConsts.PositionZ, new BuiltInAttribute("gl_Position.z", VariableType.F32) },
|
||||
{ AttributeConsts.PositionW, new BuiltInAttribute("gl_Position.w", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance0, new BuiltInAttribute("gl_ClipDistance[0]", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance1, new BuiltInAttribute("gl_ClipDistance[1]", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance2, new BuiltInAttribute("gl_ClipDistance[2]", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance3, new BuiltInAttribute("gl_ClipDistance[3]", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance4, new BuiltInAttribute("gl_ClipDistance[4]", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance5, new BuiltInAttribute("gl_ClipDistance[5]", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance6, new BuiltInAttribute("gl_ClipDistance[6]", VariableType.F32) },
|
||||
{ AttributeConsts.ClipDistance7, new BuiltInAttribute("gl_ClipDistance[7]", VariableType.F32) },
|
||||
{ AttributeConsts.PointCoordX, new BuiltInAttribute("gl_PointCoord.x", VariableType.F32) },
|
||||
{ AttributeConsts.PointCoordY, new BuiltInAttribute("gl_PointCoord.y", VariableType.F32) },
|
||||
{ AttributeConsts.TessCoordX, new BuiltInAttribute("gl_TessCoord.x", VariableType.F32) },
|
||||
{ AttributeConsts.TessCoordY, new BuiltInAttribute("gl_TessCoord.y", VariableType.F32) },
|
||||
{ AttributeConsts.InstanceId, new BuiltInAttribute("gl_InstanceID", VariableType.S32) },
|
||||
{ AttributeConsts.VertexId, new BuiltInAttribute("gl_VertexID", VariableType.S32) },
|
||||
{ AttributeConsts.FrontFacing, new BuiltInAttribute("gl_FrontFacing", VariableType.Bool) },
|
||||
|
||||
// Special.
|
||||
{ AttributeConsts.FragmentOutputDepth, new BuiltInAttribute("gl_FragDepth", VariableType.F32) },
|
||||
@@ -170,7 +164,29 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
value &= AttributeConsts.Mask & ~3;
|
||||
char swzMask = GetSwizzleMask((value >> 2) & 3);
|
||||
|
||||
if (value >= AttributeConsts.UserAttributeBase && value < AttributeConsts.UserAttributeEnd)
|
||||
if (perPatch)
|
||||
{
|
||||
if (value >= AttributeConsts.UserAttributePerPatchBase && value < AttributeConsts.UserAttributePerPatchEnd)
|
||||
{
|
||||
value -= AttributeConsts.UserAttributePerPatchBase;
|
||||
|
||||
return $"{DefaultNames.PerPatchAttributePrefix}{(value >> 4)}.{swzMask}";
|
||||
}
|
||||
else if (value < AttributeConsts.UserAttributePerPatchBase)
|
||||
{
|
||||
return value switch
|
||||
{
|
||||
AttributeConsts.TessLevelOuter0 => "gl_TessLevelOuter[0]",
|
||||
AttributeConsts.TessLevelOuter1 => "gl_TessLevelOuter[1]",
|
||||
AttributeConsts.TessLevelOuter2 => "gl_TessLevelOuter[2]",
|
||||
AttributeConsts.TessLevelOuter3 => "gl_TessLevelOuter[3]",
|
||||
AttributeConsts.TessLevelInner0 => "gl_TessLevelInner[0]",
|
||||
AttributeConsts.TessLevelInner1 => "gl_TessLevelInner[1]",
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
}
|
||||
else if (value >= AttributeConsts.UserAttributeBase && value < AttributeConsts.UserAttributeEnd)
|
||||
{
|
||||
value -= AttributeConsts.UserAttributeBase;
|
||||
|
||||
@@ -180,11 +196,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
bool indexable = config.UsedFeatures.HasFlag(isOutAttr ? FeatureFlags.OaIndexing : FeatureFlags.IaIndexing);
|
||||
|
||||
if (!indexable && perPatch)
|
||||
{
|
||||
prefix = DefaultNames.PerPatchAttributePrefix;
|
||||
}
|
||||
|
||||
if (indexable)
|
||||
{
|
||||
string name = prefix;
|
||||
@@ -202,7 +213,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
{
|
||||
string name = $"{prefix}{(value >> 4)}_{swzMask}";
|
||||
|
||||
if (!perPatch && AttributeInfo.IsArrayAttributeGlsl(config.Stage, isOutAttr))
|
||||
if (AttributeInfo.IsArrayAttributeGlsl(config.Stage, isOutAttr))
|
||||
{
|
||||
name += isOutAttr ? "[gl_InvocationID]" : $"[{indexExpr}]";
|
||||
}
|
||||
@@ -213,7 +224,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
{
|
||||
string name = $"{prefix}{(value >> 4)}";
|
||||
|
||||
if (!perPatch && AttributeInfo.IsArrayAttributeGlsl(config.Stage, isOutAttr))
|
||||
if (AttributeInfo.IsArrayAttributeGlsl(config.Stage, isOutAttr))
|
||||
{
|
||||
name += isOutAttr ? "[gl_InvocationID]" : $"[{indexExpr}]";
|
||||
}
|
||||
@@ -277,7 +288,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
string name = builtInAttr.Name;
|
||||
|
||||
if (!perPatch && AttributeInfo.IsArrayAttributeGlsl(config.Stage, isOutAttr) && AttributeInfo.IsArrayBuiltIn(value))
|
||||
if (AttributeInfo.IsArrayAttributeGlsl(config.Stage, isOutAttr) && AttributeInfo.IsArrayBuiltIn(value))
|
||||
{
|
||||
name = isOutAttr ? $"gl_out[gl_InvocationID].{name}" : $"gl_in[{indexExpr}].{name}";
|
||||
}
|
||||
|
@@ -382,17 +382,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
public Instruction GetAttributePerPatchElemPointer(int attr, bool isOutAttr, out AggregateType elemType)
|
||||
{
|
||||
var storageClass = isOutAttr ? StorageClass.Output : StorageClass.Input;
|
||||
var attrInfo = AttributeInfo.From(Config, attr, isOutAttr);
|
||||
var attrInfo = AttributeInfo.FromPatch(Config, attr, isOutAttr);
|
||||
|
||||
int attrOffset = attrInfo.BaseValue;
|
||||
Instruction ioVariable;
|
||||
|
||||
bool isUserAttr = attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd;
|
||||
Instruction ioVariable = isOutAttr ? OutputsPerPatch[attrOffset] : InputsPerPatch[attrOffset];
|
||||
|
||||
elemType = attrInfo.Type & AggregateType.ElementTypeMask;
|
||||
|
||||
ioVariable = isOutAttr ? OutputsPerPatch[attrOffset] : InputsPerPatch[attrOffset];
|
||||
|
||||
if ((attrInfo.Type & (AggregateType.Array | AggregateType.Vector)) == 0)
|
||||
{
|
||||
return ioVariable;
|
||||
@@ -404,7 +400,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
public Instruction GetAttributePerPatch(AggregateType type, int attr, bool isOutAttr)
|
||||
{
|
||||
if (!AttributeInfo.Validate(Config, attr, isOutAttr: false))
|
||||
if (!AttributeInfo.ValidatePerPatch(Config, attr, isOutAttr: false))
|
||||
{
|
||||
return GetConstant(type, new AstOperand(IrOperandType.Constant, 0));
|
||||
}
|
||||
|
@@ -403,7 +403,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
foreach (int attr in inputs)
|
||||
{
|
||||
if (!AttributeInfo.Validate(context.Config, attr, isOutAttr: false))
|
||||
if (!AttributeInfo.Validate(context.Config, attr, isOutAttr: false, perPatch))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -459,7 +459,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
foreach (int attr in outputs)
|
||||
{
|
||||
if (!AttributeInfo.Validate(context.Config, attr, isOutAttr: true))
|
||||
if (!AttributeInfo.Validate(context.Config, attr, isOutAttr: true, perPatch))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -519,7 +519,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
? (isOutAttr ? context.OutputsPerPatch : context.InputsPerPatch)
|
||||
: (isOutAttr ? context.Outputs : context.Inputs);
|
||||
|
||||
var attrInfo = AttributeInfo.From(context.Config, attr, isOutAttr);
|
||||
var attrInfo = perPatch
|
||||
? AttributeInfo.FromPatch(context.Config, attr, isOutAttr)
|
||||
: AttributeInfo.From(context.Config, attr, isOutAttr);
|
||||
|
||||
if (dict.ContainsKey(attrInfo.BaseValue))
|
||||
{
|
||||
@@ -544,11 +546,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
var spvType = context.TypePointer(storageClass, attrType);
|
||||
var spvVar = context.Variable(spvType, storageClass);
|
||||
|
||||
if (perPatch)
|
||||
{
|
||||
context.Decorate(spvVar, Decoration.Patch);
|
||||
}
|
||||
|
||||
if (builtInPassthrough)
|
||||
{
|
||||
context.Decorate(spvVar, Decoration.PassthroughNV);
|
||||
@@ -556,6 +553,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
if (attrInfo.IsBuiltin)
|
||||
{
|
||||
if (perPatch)
|
||||
{
|
||||
context.Decorate(spvVar, Decoration.Patch);
|
||||
}
|
||||
|
||||
context.Decorate(spvVar, Decoration.BuiltIn, (LiteralInteger)GetBuiltIn(context, attrInfo.BaseValue));
|
||||
|
||||
if (context.Config.TransformFeedbackEnabled && context.Config.LastInVertexPipeline && isOutAttr)
|
||||
@@ -569,6 +571,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (perPatch)
|
||||
{
|
||||
context.Decorate(spvVar, Decoration.Patch);
|
||||
|
||||
int location = context.Config.GetPerPatchAttributeLocation((attr - AttributeConsts.UserAttributePerPatchBase) / 16);
|
||||
|
||||
context.Decorate(spvVar, Decoration.Location, (LiteralInteger)location);
|
||||
}
|
||||
else if (isUserAttr)
|
||||
{
|
||||
int location = (attr - AttributeConsts.UserAttributeBase) / 16;
|
||||
|
@@ -882,7 +882,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
if (src2 is AstOperand operand && operand.Type == OperandType.Constant)
|
||||
{
|
||||
int attrOffset = (baseAttr.Value & AttributeConsts.Mask) + (operand.Value << 2);
|
||||
return new OperationResult(resultType, context.GetAttribute(resultType, attrOffset, isOutAttr: false, index));
|
||||
bool isOutAttr = (baseAttr.Value & AttributeConsts.LoadOutputMask) != 0;
|
||||
return new OperationResult(resultType, context.GetAttribute(resultType, attrOffset, isOutAttr, index));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -191,7 +191,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
break;
|
||||
}
|
||||
|
||||
if (context.Config.GpuAccessor.QueryTessCw())
|
||||
bool tessCw = context.Config.GpuAccessor.QueryTessCw();
|
||||
|
||||
if (context.Config.Options.TargetApi == TargetApi.Vulkan)
|
||||
{
|
||||
// We invert the front face on Vulkan backend, so we need to do that here aswell.
|
||||
tessCw = !tessCw;
|
||||
}
|
||||
|
||||
if (tessCw)
|
||||
{
|
||||
context.AddExecutionMode(spvFunc, ExecutionMode.VertexOrderCw);
|
||||
}
|
||||
@@ -375,9 +383,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
}
|
||||
else if (dest.Type == OperandType.Attribute || dest.Type == OperandType.AttributePerPatch)
|
||||
{
|
||||
if (AttributeInfo.Validate(context.Config, dest.Value, isOutAttr: true))
|
||||
bool perPatch = dest.Type == OperandType.AttributePerPatch;
|
||||
|
||||
if (AttributeInfo.Validate(context.Config, dest.Value, isOutAttr: true, perPatch))
|
||||
{
|
||||
bool perPatch = dest.Type == OperandType.AttributePerPatch;
|
||||
AggregateType elemType;
|
||||
|
||||
var elemPointer = perPatch
|
||||
|
@@ -306,18 +306,36 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
for (int elemIndex = 0; elemIndex < count; elemIndex++)
|
||||
{
|
||||
int attr = offset + elemIndex * 4;
|
||||
if (attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd)
|
||||
|
||||
if (perPatch)
|
||||
{
|
||||
if (attr >= AttributeConsts.UserAttributePerPatchBase && attr < AttributeConsts.UserAttributePerPatchEnd)
|
||||
{
|
||||
int userAttr = attr - AttributeConsts.UserAttributePerPatchBase;
|
||||
int index = userAttr / 16;
|
||||
|
||||
if (isStore)
|
||||
{
|
||||
config.SetOutputUserAttributePerPatch(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
config.SetInputUserAttributePerPatch(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd)
|
||||
{
|
||||
int userAttr = attr - AttributeConsts.UserAttributeBase;
|
||||
int index = userAttr / 16;
|
||||
|
||||
if (isStore)
|
||||
{
|
||||
config.SetOutputUserAttribute(index, perPatch);
|
||||
config.SetOutputUserAttribute(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
config.SetInputUserAttribute(index, (userAttr >> 2) & 3, perPatch);
|
||||
config.SetInputUserAttribute(index, (userAttr >> 2) & 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,6 +377,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
|
||||
if (lastOp.Name == InstName.Brx && block.Successors.Count == (hasNext ? 1 : 0))
|
||||
{
|
||||
HashSet<ulong> visited = new HashSet<ulong>();
|
||||
|
||||
InstBrx opBrx = new InstBrx(lastOp.RawOpCode);
|
||||
ulong baseOffset = lastOp.GetAbsoluteAddress();
|
||||
|
||||
@@ -374,9 +394,14 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
for (int i = 0; i < cbOffsetsCount; i++)
|
||||
{
|
||||
uint targetOffset = config.ConstantBuffer1Read(cbBaseOffset + i * 4);
|
||||
Block target = getBlock(baseOffset + targetOffset);
|
||||
target.Predecessors.Add(block);
|
||||
block.Successors.Add(target);
|
||||
ulong targetAddress = baseOffset + targetOffset;
|
||||
|
||||
if (visited.Add(targetAddress))
|
||||
{
|
||||
Block target = getBlock(targetAddress);
|
||||
target.Predecessors.Add(block);
|
||||
block.Successors.Add(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -279,16 +279,16 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
Add("1110101110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomB2, InstEmit.SuatomB2, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
|
||||
Add("1110101011010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomCasB, InstEmit.SuatomCasB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.SPd);
|
||||
Add("1110101x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomCas, InstEmit.SuatomCas, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.SPd);
|
||||
Add("111010110001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldDB, InstEmit.SuldDB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.SPd | InstProps.TexB);
|
||||
Add("1110101100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldDB, InstEmit.SuldDB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.SPd | InstProps.TexB);
|
||||
Add("1110101100011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldD, InstEmit.SuldD, InstProps.Rd | InstProps.Ra | InstProps.SPd | InstProps.Tex);
|
||||
Add("11101011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldB, InstEmit.SuldB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.SPd | InstProps.TexB);
|
||||
Add("11101011000x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Suld, InstEmit.Suld, InstProps.Rd | InstProps.Ra | InstProps.SPd | InstProps.Tex);
|
||||
Add("111010110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuredB, InstEmit.SuredB, InstProps.Rd | InstProps.Ra | InstProps.Rc);
|
||||
Add("1110101100000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldB, InstEmit.SuldB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.SPd | InstProps.TexB);
|
||||
Add("1110101100001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Suld, InstEmit.Suld, InstProps.Rd | InstProps.Ra | InstProps.SPd | InstProps.Tex);
|
||||
Add("1110101101010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuredB, InstEmit.SuredB, InstProps.Rd | InstProps.Ra | InstProps.Rc);
|
||||
Add("1110101101011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sured, InstEmit.Sured, InstProps.Rd | InstProps.Ra);
|
||||
Add("111010110011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustDB, InstEmit.SustDB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.TexB);
|
||||
Add("1110101100110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustDB, InstEmit.SustDB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.TexB);
|
||||
Add("1110101100111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustD, InstEmit.SustD, InstProps.Rd | InstProps.Ra | InstProps.Tex);
|
||||
Add("11101011001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustB, InstEmit.SustB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.TexB);
|
||||
Add("11101011001x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sust, InstEmit.Sust, InstProps.Rd | InstProps.Ra | InstProps.Tex);
|
||||
Add("1110101100100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustB, InstEmit.SustB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.TexB);
|
||||
Add("1110101100101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sust, InstEmit.Sust, InstProps.Rd | InstProps.Ra | InstProps.Tex);
|
||||
Add("1111000011111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sync, InstEmit.Sync, InstProps.Bra);
|
||||
Add("11000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tex, InstEmit.Tex, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.Tex);
|
||||
Add("1101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TexB, InstEmit.TexB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.TexB);
|
||||
|
@@ -46,7 +46,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
context.FlagAttributeRead(offset);
|
||||
|
||||
if (op.O)
|
||||
if (op.O && CanLoadOutput(offset))
|
||||
{
|
||||
offset |= AttributeConsts.LoadOutputMask;
|
||||
}
|
||||
@@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
context.FlagAttributeRead(offset);
|
||||
|
||||
if (op.O)
|
||||
if (op.O && CanLoadOutput(offset))
|
||||
{
|
||||
offset |= AttributeConsts.LoadOutputMask;
|
||||
}
|
||||
@@ -241,6 +241,11 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
}
|
||||
}
|
||||
|
||||
private static bool CanLoadOutput(int attr)
|
||||
{
|
||||
return attr != AttributeConsts.TessCoordX && attr != AttributeConsts.TessCoordY;
|
||||
}
|
||||
|
||||
private static bool TryFixedFuncToUserAttributeIpa(EmitterContext context, int attr, out Operand selectedAttr)
|
||||
{
|
||||
if (attr >= AttributeConsts.FrontColorDiffuseR && attr < AttributeConsts.BackColorDiffuseR)
|
||||
|
@@ -41,24 +41,82 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
Operand address = context.IAdd(Register(op.SrcA, RegisterType.Gpr), Const(offset));
|
||||
|
||||
// Sorting the target addresses in descending order improves the code,
|
||||
// since it will always check the most distant targets first, then the
|
||||
// near ones. This can be easily transformed into if/else statements.
|
||||
var sortedTargets = context.CurrBlock.Successors.Skip(startIndex).OrderByDescending(x => x.Address);
|
||||
var targets = context.CurrBlock.Successors.Skip(startIndex);
|
||||
|
||||
Block lastTarget = sortedTargets.LastOrDefault();
|
||||
bool allTargetsSinglePred = true;
|
||||
int total = context.CurrBlock.Successors.Count - startIndex;
|
||||
int count = 0;
|
||||
|
||||
foreach (Block possibleTarget in sortedTargets)
|
||||
foreach (var target in targets.OrderBy(x => x.Address))
|
||||
{
|
||||
Operand label = context.GetLabel(possibleTarget.Address);
|
||||
|
||||
if (possibleTarget != lastTarget)
|
||||
if (++count < total && (target.Predecessors.Count > 1 || target.Address <= context.CurrBlock.Address))
|
||||
{
|
||||
context.BranchIfTrue(label, context.ICompareEqual(address, Const((int)possibleTarget.Address)));
|
||||
allTargetsSinglePred = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
if (allTargetsSinglePred)
|
||||
{
|
||||
// Chain blocks, each target block will check if the BRX target address
|
||||
// matches its own address, if not, it jumps to the next target which will do the same check,
|
||||
// until it reaches the last possible target, which executed unconditionally.
|
||||
// We can only do this if the BRX block is the only predecessor of all target blocks.
|
||||
// Additionally, this is not supported for blocks located before the current block,
|
||||
// since it will be too late to insert a label, but this is something that can be improved
|
||||
// in the future if necessary.
|
||||
|
||||
var sortedTargets = targets.OrderBy(x => x.Address);
|
||||
|
||||
Block currentTarget = null;
|
||||
ulong firstTargetAddress = 0;
|
||||
|
||||
foreach (Block nextTarget in sortedTargets)
|
||||
{
|
||||
context.Branch(label);
|
||||
if (currentTarget != null)
|
||||
{
|
||||
if (currentTarget.Address != nextTarget.Address)
|
||||
{
|
||||
context.SetBrxTarget(currentTarget.Address, address, (int)currentTarget.Address, nextTarget.Address);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
firstTargetAddress = nextTarget.Address;
|
||||
}
|
||||
|
||||
currentTarget = nextTarget;
|
||||
}
|
||||
|
||||
context.Branch(context.GetLabel(firstTargetAddress));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Emit the branches sequentially.
|
||||
// This generates slightly worse code, but should work for all cases.
|
||||
|
||||
var sortedTargets = targets.OrderByDescending(x => x.Address);
|
||||
ulong lastTargetAddress = ulong.MaxValue;
|
||||
|
||||
count = 0;
|
||||
|
||||
foreach (Block target in sortedTargets)
|
||||
{
|
||||
Operand label = context.GetLabel(target.Address);
|
||||
|
||||
if (++count < total)
|
||||
{
|
||||
if (target.Address != lastTargetAddress)
|
||||
{
|
||||
context.BranchIfTrue(label, context.ICompareEqual(address, Const((int)target.Address)));
|
||||
}
|
||||
|
||||
lastTargetAddress = target.Address;
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Branch(label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -123,7 +123,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
{
|
||||
InstSuldB op = context.GetOp<InstSuldB>();
|
||||
|
||||
EmitSuld(context, op.CacheOp, op.Dim, 0, 0, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: true);
|
||||
EmitSuld(context, op.CacheOp, op.Dim, 0, 0, op.Rgba, op.SrcA, op.Dest, op.SrcC, useComponents: true, false, isBindless: true);
|
||||
}
|
||||
|
||||
public static void Suld(EmitterContext context)
|
||||
|
@@ -97,7 +97,15 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||
if (src1.Type == OperandType.Constant && src2.Type == OperandType.Constant)
|
||||
{
|
||||
int attrOffset = (src1.Value & AttributeConsts.Mask) + (src2.Value << 2);
|
||||
context.Info.Inputs.Add(attrOffset);
|
||||
|
||||
if ((src1.Value & AttributeConsts.LoadOutputMask) != 0)
|
||||
{
|
||||
context.Info.Outputs.Add(attrOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Info.Inputs.Add(attrOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -54,6 +54,9 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
public const int UserAttributeBase = 0x80;
|
||||
public const int UserAttributeEnd = UserAttributeBase + UserAttributesCount * 16;
|
||||
|
||||
public const int UserAttributePerPatchBase = 0x18;
|
||||
public const int UserAttributePerPatchEnd = 0x200;
|
||||
|
||||
public const int LoadOutputMask = 1 << 30;
|
||||
public const int Mask = 0x3fffffff;
|
||||
|
||||
|
@@ -4,36 +4,30 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
{
|
||||
struct AttributeInfo
|
||||
{
|
||||
private static readonly Dictionary<int, AttributeInfo> BuiltInAttributes = new Dictionary<int, AttributeInfo>()
|
||||
private static readonly Dictionary<int, AttributeInfo> _builtInAttributes = new Dictionary<int, AttributeInfo>()
|
||||
{
|
||||
{ AttributeConsts.TessLevelOuter0, new AttributeInfo(AttributeConsts.TessLevelOuter0, 0, 4, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.TessLevelOuter1, new AttributeInfo(AttributeConsts.TessLevelOuter0, 1, 4, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.TessLevelOuter2, new AttributeInfo(AttributeConsts.TessLevelOuter0, 2, 4, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.TessLevelOuter3, new AttributeInfo(AttributeConsts.TessLevelOuter0, 3, 4, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.TessLevelInner0, new AttributeInfo(AttributeConsts.TessLevelInner0, 0, 2, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.TessLevelInner1, new AttributeInfo(AttributeConsts.TessLevelInner0, 1, 2, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.Layer, new AttributeInfo(AttributeConsts.Layer, 0, 1, AggregateType.S32) },
|
||||
{ AttributeConsts.ViewportIndex, new AttributeInfo(AttributeConsts.ViewportIndex, 0, 1, AggregateType.S32) },
|
||||
{ AttributeConsts.PointSize, new AttributeInfo(AttributeConsts.PointSize, 0, 1, AggregateType.FP32) },
|
||||
{ AttributeConsts.PositionX, new AttributeInfo(AttributeConsts.PositionX, 0, 4, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.PositionY, new AttributeInfo(AttributeConsts.PositionX, 1, 4, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.PositionZ, new AttributeInfo(AttributeConsts.PositionX, 2, 4, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.PositionW, new AttributeInfo(AttributeConsts.PositionX, 3, 4, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance0, new AttributeInfo(AttributeConsts.ClipDistance0, 0, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance1, new AttributeInfo(AttributeConsts.ClipDistance0, 1, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance2, new AttributeInfo(AttributeConsts.ClipDistance0, 2, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance3, new AttributeInfo(AttributeConsts.ClipDistance0, 3, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance4, new AttributeInfo(AttributeConsts.ClipDistance0, 4, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance5, new AttributeInfo(AttributeConsts.ClipDistance0, 5, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance6, new AttributeInfo(AttributeConsts.ClipDistance0, 6, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance7, new AttributeInfo(AttributeConsts.ClipDistance0, 7, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.PointCoordX, new AttributeInfo(AttributeConsts.PointCoordX, 0, 2, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.PointCoordY, new AttributeInfo(AttributeConsts.PointCoordX, 1, 2, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.TessCoordX, new AttributeInfo(AttributeConsts.TessCoordX, 0, 2, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.TessCoordY, new AttributeInfo(AttributeConsts.TessCoordX, 1, 2, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.InstanceId, new AttributeInfo(AttributeConsts.InstanceId, 0, 1, AggregateType.S32) },
|
||||
{ AttributeConsts.VertexId, new AttributeInfo(AttributeConsts.VertexId, 0, 1, AggregateType.S32) },
|
||||
{ AttributeConsts.FrontFacing, new AttributeInfo(AttributeConsts.FrontFacing, 0, 1, AggregateType.Bool) },
|
||||
{ AttributeConsts.Layer, new AttributeInfo(AttributeConsts.Layer, 0, 1, AggregateType.S32) },
|
||||
{ AttributeConsts.ViewportIndex, new AttributeInfo(AttributeConsts.ViewportIndex, 0, 1, AggregateType.S32) },
|
||||
{ AttributeConsts.PointSize, new AttributeInfo(AttributeConsts.PointSize, 0, 1, AggregateType.FP32) },
|
||||
{ AttributeConsts.PositionX, new AttributeInfo(AttributeConsts.PositionX, 0, 4, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.PositionY, new AttributeInfo(AttributeConsts.PositionX, 1, 4, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.PositionZ, new AttributeInfo(AttributeConsts.PositionX, 2, 4, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.PositionW, new AttributeInfo(AttributeConsts.PositionX, 3, 4, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance0, new AttributeInfo(AttributeConsts.ClipDistance0, 0, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance1, new AttributeInfo(AttributeConsts.ClipDistance0, 1, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance2, new AttributeInfo(AttributeConsts.ClipDistance0, 2, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance3, new AttributeInfo(AttributeConsts.ClipDistance0, 3, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance4, new AttributeInfo(AttributeConsts.ClipDistance0, 4, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance5, new AttributeInfo(AttributeConsts.ClipDistance0, 5, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance6, new AttributeInfo(AttributeConsts.ClipDistance0, 6, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.ClipDistance7, new AttributeInfo(AttributeConsts.ClipDistance0, 7, 8, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.PointCoordX, new AttributeInfo(AttributeConsts.PointCoordX, 0, 2, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.PointCoordY, new AttributeInfo(AttributeConsts.PointCoordX, 1, 2, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.TessCoordX, new AttributeInfo(AttributeConsts.TessCoordX, 0, 3, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.TessCoordY, new AttributeInfo(AttributeConsts.TessCoordX, 1, 3, AggregateType.Vector | AggregateType.FP32) },
|
||||
{ AttributeConsts.InstanceId, new AttributeInfo(AttributeConsts.InstanceId, 0, 1, AggregateType.S32) },
|
||||
{ AttributeConsts.VertexId, new AttributeInfo(AttributeConsts.VertexId, 0, 1, AggregateType.S32) },
|
||||
{ AttributeConsts.FrontFacing, new AttributeInfo(AttributeConsts.FrontFacing, 0, 1, AggregateType.Bool) },
|
||||
|
||||
// Special.
|
||||
{ AttributeConsts.FragmentOutputDepth, new AttributeInfo(AttributeConsts.FragmentOutputDepth, 0, 1, AggregateType.FP32) },
|
||||
@@ -55,6 +49,16 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
{ AttributeConsts.LtMask, new AttributeInfo(AttributeConsts.LtMask, 0, 4, AggregateType.Vector | AggregateType.U32) },
|
||||
};
|
||||
|
||||
private static readonly Dictionary<int, AttributeInfo> _builtInAttributesPerPatch = new Dictionary<int, AttributeInfo>()
|
||||
{
|
||||
{ AttributeConsts.TessLevelOuter0, new AttributeInfo(AttributeConsts.TessLevelOuter0, 0, 4, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.TessLevelOuter1, new AttributeInfo(AttributeConsts.TessLevelOuter0, 1, 4, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.TessLevelOuter2, new AttributeInfo(AttributeConsts.TessLevelOuter0, 2, 4, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.TessLevelOuter3, new AttributeInfo(AttributeConsts.TessLevelOuter0, 3, 4, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.TessLevelInner0, new AttributeInfo(AttributeConsts.TessLevelInner0, 0, 2, AggregateType.Array | AggregateType.FP32) },
|
||||
{ AttributeConsts.TessLevelInner1, new AttributeInfo(AttributeConsts.TessLevelInner0, 1, 2, AggregateType.Array | AggregateType.FP32) },
|
||||
};
|
||||
|
||||
public int BaseValue { get; }
|
||||
public int Value { get; }
|
||||
public int Length { get; }
|
||||
@@ -76,6 +80,11 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
return (Value - BaseValue) / 4;
|
||||
}
|
||||
|
||||
public static bool Validate(ShaderConfig config, int value, bool isOutAttr, bool perPatch)
|
||||
{
|
||||
return perPatch ? ValidatePerPatch(config, value, isOutAttr) : Validate(config, value, isOutAttr);
|
||||
}
|
||||
|
||||
public static bool Validate(ShaderConfig config, int value, bool isOutAttr)
|
||||
{
|
||||
if (value == AttributeConsts.ViewportIndex && !config.GpuAccessor.QueryHostSupportsViewportIndex())
|
||||
@@ -86,6 +95,11 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
return From(config, value, isOutAttr).IsValid;
|
||||
}
|
||||
|
||||
public static bool ValidatePerPatch(ShaderConfig config, int value, bool isOutAttr)
|
||||
{
|
||||
return FromPatch(config, value, isOutAttr).IsValid;
|
||||
}
|
||||
|
||||
public static AttributeInfo From(ShaderConfig config, int value, bool isOutAttr)
|
||||
{
|
||||
value &= ~3;
|
||||
@@ -115,7 +129,24 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
{
|
||||
return new AttributeInfo(value, 0, 1, AggregateType.FP32);
|
||||
}
|
||||
else if (BuiltInAttributes.TryGetValue(value, out AttributeInfo info))
|
||||
else if (_builtInAttributes.TryGetValue(value, out AttributeInfo info))
|
||||
{
|
||||
return info;
|
||||
}
|
||||
|
||||
return new AttributeInfo(value, 0, 0, AggregateType.Invalid);
|
||||
}
|
||||
|
||||
public static AttributeInfo FromPatch(ShaderConfig config, int value, bool isOutAttr)
|
||||
{
|
||||
value &= ~3;
|
||||
|
||||
if (value >= AttributeConsts.UserAttributePerPatchBase && value < AttributeConsts.UserAttributePerPatchEnd)
|
||||
{
|
||||
int offset = (value - AttributeConsts.UserAttributePerPatchBase) & 0xf;
|
||||
return new AttributeInfo(value - offset, offset >> 2, 4, AggregateType.Vector | AggregateType.FP32, false);
|
||||
}
|
||||
else if (_builtInAttributesPerPatch.TryGetValue(value, out AttributeInfo info))
|
||||
{
|
||||
return info;
|
||||
}
|
||||
|
@@ -21,8 +21,33 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
|
||||
public int OperationsCount => _operations.Count;
|
||||
|
||||
private struct BrxTarget
|
||||
{
|
||||
public readonly Operand Selector;
|
||||
public readonly int ExpectedValue;
|
||||
public readonly ulong NextTargetAddress;
|
||||
|
||||
public BrxTarget(Operand selector, int expectedValue, ulong nextTargetAddress)
|
||||
{
|
||||
Selector = selector;
|
||||
ExpectedValue = expectedValue;
|
||||
NextTargetAddress = nextTargetAddress;
|
||||
}
|
||||
}
|
||||
|
||||
private class BlockLabel
|
||||
{
|
||||
public readonly Operand Label;
|
||||
public BrxTarget BrxTarget;
|
||||
|
||||
public BlockLabel(Operand label)
|
||||
{
|
||||
Label = label;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<Operation> _operations;
|
||||
private readonly Dictionary<ulong, Operand> _labels;
|
||||
private readonly Dictionary<ulong, BlockLabel> _labels;
|
||||
|
||||
public EmitterContext(DecodedProgram program, ShaderConfig config, bool isNonMain)
|
||||
{
|
||||
@@ -30,7 +55,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
Config = config;
|
||||
IsNonMain = isNonMain;
|
||||
_operations = new List<Operation>();
|
||||
_labels = new Dictionary<ulong, Operand>();
|
||||
_labels = new Dictionary<ulong, BlockLabel>();
|
||||
|
||||
EmitStart();
|
||||
}
|
||||
@@ -158,14 +183,40 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
|
||||
public Operand GetLabel(ulong address)
|
||||
{
|
||||
if (!_labels.TryGetValue(address, out Operand label))
|
||||
{
|
||||
label = Label();
|
||||
return EnsureBlockLabel(address).Label;
|
||||
}
|
||||
|
||||
_labels.Add(address, label);
|
||||
public void SetBrxTarget(ulong address, Operand selector, int targetValue, ulong nextTargetAddress)
|
||||
{
|
||||
BlockLabel blockLabel = EnsureBlockLabel(address);
|
||||
Debug.Assert(blockLabel.BrxTarget.Selector == null);
|
||||
blockLabel.BrxTarget = new BrxTarget(selector, targetValue, nextTargetAddress);
|
||||
}
|
||||
|
||||
public void EnterBlock(ulong address)
|
||||
{
|
||||
BlockLabel blockLabel = EnsureBlockLabel(address);
|
||||
|
||||
MarkLabel(blockLabel.Label);
|
||||
|
||||
BrxTarget brxTarget = blockLabel.BrxTarget;
|
||||
|
||||
if (brxTarget.Selector != null)
|
||||
{
|
||||
this.BranchIfFalse(GetLabel(brxTarget.NextTargetAddress), this.ICompareEqual(brxTarget.Selector, Const(brxTarget.ExpectedValue)));
|
||||
}
|
||||
}
|
||||
|
||||
private BlockLabel EnsureBlockLabel(ulong address)
|
||||
{
|
||||
if (!_labels.TryGetValue(address, out BlockLabel blockLabel))
|
||||
{
|
||||
blockLabel = new BlockLabel(Label());
|
||||
|
||||
_labels.Add(address, blockLabel);
|
||||
}
|
||||
|
||||
return label;
|
||||
return blockLabel;
|
||||
}
|
||||
|
||||
public void PrepareForVertexReturn()
|
||||
@@ -261,7 +312,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
{
|
||||
int index = BitOperations.TrailingZeroCount(passthroughAttributes);
|
||||
WriteOutput(AttributeConsts.UserAttributeBase + index * 16, primIndex);
|
||||
Config.SetOutputUserAttribute(index, perPatch: false);
|
||||
Config.SetOutputUserAttribute(index);
|
||||
passthroughAttributes &= ~(1 << index);
|
||||
}
|
||||
|
||||
@@ -364,7 +415,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
bool targetEnabled = (Config.OmapTargets & (0xf << (rtIndex * 4))) != 0;
|
||||
if (targetEnabled)
|
||||
{
|
||||
Config.SetOutputUserAttribute(rtIndex, perPatch: false);
|
||||
Config.SetOutputUserAttribute(rtIndex);
|
||||
regIndexBase += 4;
|
||||
}
|
||||
}
|
||||
|
@@ -50,16 +50,16 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
public bool NextUsesFixedFuncAttributes { get; private set; }
|
||||
public int UsedInputAttributes { get; private set; }
|
||||
public int UsedOutputAttributes { get; private set; }
|
||||
public int UsedInputAttributesPerPatch { get; private set; }
|
||||
public int UsedOutputAttributesPerPatch { get; private set; }
|
||||
public HashSet<int> UsedInputAttributesPerPatch { get; }
|
||||
public HashSet<int> UsedOutputAttributesPerPatch { get; }
|
||||
public HashSet<int> NextUsedInputAttributesPerPatch { get; private set; }
|
||||
public int PassthroughAttributes { get; private set; }
|
||||
private int _nextUsedInputAttributes;
|
||||
private int _thisUsedInputAttributes;
|
||||
private Dictionary<int, int> _perPatchAttributeLocations;
|
||||
|
||||
public UInt128 NextInputAttributesComponents { get; private set; }
|
||||
public UInt128 ThisInputAttributesComponents { get; private set; }
|
||||
public UInt128 NextInputAttributesPerPatchComponents { get; private set; }
|
||||
public UInt128 ThisInputAttributesPerPatchComponents { get; private set; }
|
||||
|
||||
private int _usedConstantBuffers;
|
||||
private int _usedStorageBuffers;
|
||||
@@ -119,9 +119,13 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
|
||||
public ShaderConfig(IGpuAccessor gpuAccessor, TranslationOptions options)
|
||||
{
|
||||
Stage = ShaderStage.Compute;
|
||||
GpuAccessor = gpuAccessor;
|
||||
Options = options;
|
||||
Stage = ShaderStage.Compute;
|
||||
GpuAccessor = gpuAccessor;
|
||||
Options = options;
|
||||
|
||||
UsedInputAttributesPerPatch = new HashSet<int>();
|
||||
UsedOutputAttributesPerPatch = new HashSet<int>();
|
||||
|
||||
_usedTextures = new Dictionary<TextureInfo, TextureMeta>();
|
||||
_usedImages = new Dictionary<TextureInfo, TextureMeta>();
|
||||
}
|
||||
@@ -244,49 +248,74 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
UsedOutputAttributes |= 1 << index;
|
||||
}
|
||||
|
||||
public void SetInputUserAttribute(int index, int component, bool perPatch)
|
||||
public void SetInputUserAttribute(int index, int component)
|
||||
{
|
||||
if (perPatch)
|
||||
{
|
||||
UsedInputAttributesPerPatch |= 1 << index;
|
||||
ThisInputAttributesPerPatchComponents |= UInt128.Pow2(index * 4 + component);
|
||||
}
|
||||
else
|
||||
{
|
||||
int mask = 1 << index;
|
||||
int mask = 1 << index;
|
||||
|
||||
UsedInputAttributes |= mask;
|
||||
_thisUsedInputAttributes |= mask;
|
||||
ThisInputAttributesComponents |= UInt128.Pow2(index * 4 + component);
|
||||
}
|
||||
UsedInputAttributes |= mask;
|
||||
_thisUsedInputAttributes |= mask;
|
||||
ThisInputAttributesComponents |= UInt128.Pow2(index * 4 + component);
|
||||
}
|
||||
|
||||
public void SetOutputUserAttribute(int index, bool perPatch)
|
||||
public void SetInputUserAttributePerPatch(int index)
|
||||
{
|
||||
if (perPatch)
|
||||
{
|
||||
UsedOutputAttributesPerPatch |= 1 << index;
|
||||
}
|
||||
else
|
||||
{
|
||||
UsedOutputAttributes |= 1 << index;
|
||||
}
|
||||
UsedInputAttributesPerPatch.Add(index);
|
||||
}
|
||||
|
||||
public void SetOutputUserAttribute(int index)
|
||||
{
|
||||
UsedOutputAttributes |= 1 << index;
|
||||
}
|
||||
|
||||
public void SetOutputUserAttributePerPatch(int index)
|
||||
{
|
||||
UsedOutputAttributesPerPatch.Add(index);
|
||||
}
|
||||
|
||||
public void MergeFromtNextStage(ShaderConfig config)
|
||||
{
|
||||
NextInputAttributesComponents = config.ThisInputAttributesComponents;
|
||||
NextInputAttributesPerPatchComponents = config.ThisInputAttributesPerPatchComponents;
|
||||
NextUsedInputAttributesPerPatch = config.UsedInputAttributesPerPatch;
|
||||
NextUsesFixedFuncAttributes = config.UsedFeatures.HasFlag(FeatureFlags.FixedFuncAttr);
|
||||
MergeOutputUserAttributes(config.UsedInputAttributes, config.UsedInputAttributesPerPatch);
|
||||
|
||||
if (config.Stage != ShaderStage.Fragment)
|
||||
if (UsedOutputAttributesPerPatch.Count != 0)
|
||||
{
|
||||
// Regular and per-patch input/output locations can't overlap,
|
||||
// so we must assign on our location using unused regular input/output locations.
|
||||
|
||||
Dictionary<int, int> locationsMap = new Dictionary<int, int>();
|
||||
|
||||
int freeMask = ~UsedOutputAttributes;
|
||||
|
||||
foreach (int attr in UsedOutputAttributesPerPatch)
|
||||
{
|
||||
int location = BitOperations.TrailingZeroCount(freeMask);
|
||||
if (location == 32)
|
||||
{
|
||||
config.GpuAccessor.Log($"No enough free locations for patch input/output 0x{attr:X}.");
|
||||
break;
|
||||
}
|
||||
|
||||
locationsMap.Add(attr, location);
|
||||
freeMask &= ~(1 << location);
|
||||
}
|
||||
|
||||
// Both stages must agree on the locations, so use the same "map" for both.
|
||||
_perPatchAttributeLocations = locationsMap;
|
||||
config._perPatchAttributeLocations = locationsMap;
|
||||
}
|
||||
|
||||
// We don't consider geometry shaders using the geometry shader passthrough feature
|
||||
// as being the last because when this feature is used, it can't actually modify any of the outputs,
|
||||
// so the stage that comes before it is the last one that can do modifications.
|
||||
if (config.Stage != ShaderStage.Fragment && (config.Stage != ShaderStage.Geometry || !config.GpPassthrough))
|
||||
{
|
||||
LastInVertexPipeline = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void MergeOutputUserAttributes(int mask, int maskPerPatch)
|
||||
public void MergeOutputUserAttributes(int mask, IEnumerable<int> perPatch)
|
||||
{
|
||||
_nextUsedInputAttributes = mask;
|
||||
|
||||
@@ -297,10 +326,20 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
else
|
||||
{
|
||||
UsedOutputAttributes |= mask;
|
||||
UsedOutputAttributesPerPatch |= maskPerPatch;
|
||||
UsedOutputAttributesPerPatch.UnionWith(perPatch);
|
||||
}
|
||||
}
|
||||
|
||||
public int GetPerPatchAttributeLocation(int index)
|
||||
{
|
||||
if (_perPatchAttributeLocations == null || !_perPatchAttributeLocations.TryGetValue(index, out int location))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
public bool IsUsedOutputAttribute(int attr)
|
||||
{
|
||||
// The check for fixed function attributes on the next stage is conservative,
|
||||
|
@@ -162,7 +162,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
{
|
||||
context.CurrBlock = block;
|
||||
|
||||
context.MarkLabel(context.GetLabel(block.Address));
|
||||
context.EnterBlock(block.Address);
|
||||
|
||||
EmitOps(context, block);
|
||||
}
|
||||
@@ -204,14 +204,12 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
InitializeOutputComponent(context, AttributeConsts.UserAttributeBase + index * 4, perPatch: false);
|
||||
}
|
||||
|
||||
UInt128 usedAttributesPerPatch = context.Config.NextInputAttributesPerPatchComponents;
|
||||
while (usedAttributesPerPatch != UInt128.Zero)
|
||||
if (context.Config.NextUsedInputAttributesPerPatch != null)
|
||||
{
|
||||
int index = usedAttributesPerPatch.TrailingZeroCount();
|
||||
|
||||
InitializeOutputComponent(context, AttributeConsts.UserAttributeBase + index * 4, perPatch: true);
|
||||
|
||||
usedAttributesPerPatch &= ~UInt128.Pow2(index);
|
||||
foreach (int vecIndex in context.Config.NextUsedInputAttributesPerPatch.OrderBy(x => x))
|
||||
{
|
||||
InitializeOutput(context, AttributeConsts.UserAttributePerPatchBase + vecIndex * 16, perPatch: true);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.NextUsesFixedFuncAttributes)
|
||||
@@ -236,7 +234,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
for (int c = 0; c < 4; c++)
|
||||
{
|
||||
int attrOffset = baseAttr + c * 4;
|
||||
context.Copy(perPatch ? AttributePerPatch(attrOffset) : Attribute(attrOffset), ConstF(c == 3 ? 1f : 0f));
|
||||
InitializeOutputComponent(context, attrOffset, perPatch);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using Ryujinx.Graphics.Shader.Decoders;
|
||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||
using static Ryujinx.Graphics.Shader.Translation.Translator;
|
||||
@@ -137,7 +138,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
|
||||
if (other != null)
|
||||
{
|
||||
other._config.MergeOutputUserAttributes(_config.UsedOutputAttributes, 0);
|
||||
other._config.MergeOutputUserAttributes(_config.UsedOutputAttributes, Enumerable.Empty<int>());
|
||||
|
||||
FunctionCode[] otherCode = EmitShader(other._program, other._config, initializeOutputs: true, out int aStart);
|
||||
|
||||
|
@@ -93,7 +93,7 @@ namespace Ryujinx.Graphics.Texture
|
||||
};
|
||||
}
|
||||
|
||||
public static Span<byte> ConvertBlockLinearToLinear(
|
||||
public static byte[] ConvertBlockLinearToLinear(
|
||||
int width,
|
||||
int height,
|
||||
int depth,
|
||||
@@ -119,7 +119,7 @@ namespace Ryujinx.Graphics.Texture
|
||||
blockHeight,
|
||||
bytesPerPixel);
|
||||
|
||||
Span<byte> output = new byte[outSize];
|
||||
byte[] output = new byte[outSize];
|
||||
|
||||
int outOffs = 0;
|
||||
|
||||
@@ -246,7 +246,7 @@ namespace Ryujinx.Graphics.Texture
|
||||
return output;
|
||||
}
|
||||
|
||||
public static Span<byte> ConvertLinearStridedToLinear(
|
||||
public static byte[] ConvertLinearStridedToLinear(
|
||||
int width,
|
||||
int height,
|
||||
int blockWidth,
|
||||
@@ -262,14 +262,15 @@ namespace Ryujinx.Graphics.Texture
|
||||
int outStride = BitUtils.AlignUp(w * bytesPerPixel, HostStrideAlignment);
|
||||
lineSize = Math.Min(lineSize, outStride);
|
||||
|
||||
Span<byte> output = new byte[h * outStride];
|
||||
byte[] output = new byte[h * outStride];
|
||||
Span<byte> outSpan = output;
|
||||
|
||||
int outOffs = 0;
|
||||
int inOffs = 0;
|
||||
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
data.Slice(inOffs, lineSize).CopyTo(output.Slice(outOffs, lineSize));
|
||||
data.Slice(inOffs, lineSize).CopyTo(outSpan.Slice(outOffs, lineSize));
|
||||
|
||||
inOffs += stride;
|
||||
outOffs += outStride;
|
||||
|
@@ -109,12 +109,34 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
if (isWrite)
|
||||
{
|
||||
_cachedConvertedBuffers.Clear();
|
||||
SignalWrite(0, Size);
|
||||
}
|
||||
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
public Auto<DisposableBuffer> GetBuffer(CommandBuffer commandBuffer, int offset, int size, bool isWrite = false)
|
||||
{
|
||||
if (isWrite)
|
||||
{
|
||||
SignalWrite(offset, size);
|
||||
}
|
||||
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
public void SignalWrite(int offset, int size)
|
||||
{
|
||||
if (offset == 0 && size == Size)
|
||||
{
|
||||
_cachedConvertedBuffers.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
_cachedConvertedBuffers.ClearRange(offset, size);
|
||||
}
|
||||
}
|
||||
|
||||
public BufferHandle GetHandle()
|
||||
{
|
||||
var handle = _bufferHandle;
|
||||
@@ -183,6 +205,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
data.Slice(0, dataSize).CopyTo(new Span<byte>((void*)(_map + offset), dataSize));
|
||||
|
||||
SignalWrite(offset, dataSize);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -240,7 +264,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
endRenderPass?.Invoke();
|
||||
|
||||
var dstBuffer = GetBuffer(cbs.CommandBuffer, true).Get(cbs, dstOffset, data.Length).Value;
|
||||
var dstBuffer = GetBuffer(cbs.CommandBuffer, dstOffset, data.Length, true).Get(cbs, dstOffset, data.Length).Value;
|
||||
|
||||
InsertBufferBarrier(
|
||||
_gd,
|
||||
@@ -362,9 +386,26 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_waitable.WaitForFences(_gd.Api, _device, offset, size);
|
||||
}
|
||||
|
||||
private bool BoundToRange(int offset, ref int size)
|
||||
{
|
||||
if (offset >= Size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size = Math.Min(Size - offset, size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Auto<DisposableBuffer> GetBufferI8ToI16(CommandBufferScoped cbs, int offset, int size)
|
||||
{
|
||||
var key = new I8ToI16CacheKey();
|
||||
if (!BoundToRange(offset, ref size))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var key = new I8ToI16CacheKey(_gd);
|
||||
|
||||
if (!_cachedConvertedBuffers.TryGetValue(offset, size, key, out var holder))
|
||||
{
|
||||
@@ -373,6 +414,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_gd.PipelineInternal.EndRenderPass();
|
||||
_gd.HelperShader.ConvertI8ToI16(_gd, cbs, this, holder, offset, size);
|
||||
|
||||
key.SetBuffer(holder.GetBuffer());
|
||||
|
||||
_cachedConvertedBuffers.Add(offset, size, key, holder);
|
||||
}
|
||||
|
||||
@@ -381,6 +424,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public Auto<DisposableBuffer> GetAlignedVertexBuffer(CommandBufferScoped cbs, int offset, int size, int stride, int alignment)
|
||||
{
|
||||
if (!BoundToRange(offset, ref size))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var key = new AlignedVertexBufferCacheKey(_gd, stride, alignment);
|
||||
|
||||
if (!_cachedConvertedBuffers.TryGetValue(offset, size, key, out var holder))
|
||||
@@ -402,6 +450,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public Auto<DisposableBuffer> GetBufferTopologyConversion(CommandBufferScoped cbs, int offset, int size, IndexBufferPattern pattern, int indexSize)
|
||||
{
|
||||
if (!BoundToRange(offset, ref size))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var key = new TopologyConversionCacheKey(_gd, pattern, indexSize);
|
||||
|
||||
if (!_cachedConvertedBuffers.TryGetValue(offset, size, key, out var holder))
|
||||
@@ -417,6 +470,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_gd.PipelineInternal.EndRenderPass();
|
||||
_gd.HelperShader.ConvertIndexBuffer(_gd, cbs, this, holder, pattern, indexSize, offset, indexCount);
|
||||
|
||||
key.SetBuffer(holder.GetBuffer());
|
||||
|
||||
_cachedConvertedBuffers.Add(offset, size, key, holder);
|
||||
}
|
||||
|
||||
|
@@ -38,6 +38,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
private readonly IdList<BufferHolder> _buffers;
|
||||
|
||||
public int BufferCount { get; private set; }
|
||||
|
||||
public StagingBuffer StagingBuffer { get; }
|
||||
|
||||
public BufferManager(VulkanRenderer gd, PhysicalDevice physicalDevice, Device device)
|
||||
@@ -56,6 +58,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return BufferHandle.Null;
|
||||
}
|
||||
|
||||
BufferCount++;
|
||||
|
||||
ulong handle64 = (uint)_buffers.Add(holder);
|
||||
|
||||
return Unsafe.As<ulong, BufferHandle>(ref handle64);
|
||||
@@ -120,6 +124,16 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return null;
|
||||
}
|
||||
|
||||
public Auto<DisposableBuffer> GetBuffer(CommandBuffer commandBuffer, BufferHandle handle, int offset, int size, bool isWrite)
|
||||
{
|
||||
if (TryGetBuffer(handle, out var holder))
|
||||
{
|
||||
return holder.GetBuffer(commandBuffer, offset, size, isWrite);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Auto<DisposableBuffer> GetBufferI8ToI16(CommandBufferScoped cbs, BufferHandle handle, int offset, int size)
|
||||
{
|
||||
if (TryGetBuffer(handle, out var holder))
|
||||
|
@@ -24,6 +24,11 @@
|
||||
|
||||
public void Add(int cbIndex, int offset, int size)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Some usages can be out of bounds (vertex buffer on amd), so bound if necessary.
|
||||
if (offset + size > _size)
|
||||
{
|
||||
@@ -39,6 +44,11 @@
|
||||
|
||||
public bool OverlapsWith(int cbIndex, int offset, int size)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int cbBase = cbIndex * _bitsPerCb;
|
||||
int start = cbBase + offset / _granularity;
|
||||
int end = cbBase + (offset + size - 1) / _granularity;
|
||||
|
@@ -25,6 +25,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return other is I8ToI16CacheKey;
|
||||
}
|
||||
|
||||
public void SetBuffer(Auto<DisposableBuffer> buffer)
|
||||
{
|
||||
_buffer = buffer;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_gd.PipelineInternal.DirtyIndexBuffer(_buffer);
|
||||
@@ -160,6 +165,44 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearRange(int offset, int size)
|
||||
{
|
||||
if (_ranges != null && _ranges.Count > 0)
|
||||
{
|
||||
int end = offset + size;
|
||||
|
||||
List<ulong> toRemove = null;
|
||||
|
||||
foreach (KeyValuePair<ulong, List<Entry>> range in _ranges)
|
||||
{
|
||||
(int rOffset, int rSize) = UnpackRange(range.Key);
|
||||
|
||||
int rEnd = rOffset + rSize;
|
||||
|
||||
if (rEnd > offset && rOffset < end)
|
||||
{
|
||||
List<Entry> entries = range.Value;
|
||||
|
||||
foreach (Entry entry in entries)
|
||||
{
|
||||
entry.Key.Dispose();
|
||||
entry.Value.Dispose();
|
||||
}
|
||||
|
||||
(toRemove ??= new List<ulong>()).Add(range.Key);
|
||||
}
|
||||
}
|
||||
|
||||
if (toRemove != null)
|
||||
{
|
||||
foreach (ulong range in toRemove)
|
||||
{
|
||||
_ranges.Remove(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<Entry> GetEntries(int offset, int size)
|
||||
{
|
||||
if (_ranges == null)
|
||||
@@ -184,6 +227,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return (uint)offset | ((ulong)size << 32);
|
||||
}
|
||||
|
||||
private static (int offset, int size) UnpackRange(ulong range)
|
||||
{
|
||||
return ((int)range, (int)(range >> 32));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Clear();
|
||||
|
@@ -38,7 +38,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public int GetPrimitiveCount(int vertexCount)
|
||||
{
|
||||
return Math.Max(0, ((vertexCount - BaseIndex) + IndexStride - 1) / IndexStride);
|
||||
return Math.Max(0, (vertexCount - BaseIndex) / IndexStride);
|
||||
}
|
||||
|
||||
public int GetConvertedCount(int indexCount)
|
||||
|
@@ -49,7 +49,12 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
else
|
||||
{
|
||||
autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int _);
|
||||
autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int bufferSize);
|
||||
|
||||
if (_offset >= bufferSize)
|
||||
{
|
||||
autoBuffer = null;
|
||||
}
|
||||
|
||||
offset = _offset;
|
||||
size = _size;
|
||||
|
@@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
protected readonly AutoFlushCounter AutoFlush;
|
||||
|
||||
private PipelineDynamicState _dynamicState;
|
||||
protected PipelineDynamicState DynamicState;
|
||||
private PipelineState _newState;
|
||||
private bool _stateDirty;
|
||||
private GAL.PrimitiveTopology _topology;
|
||||
@@ -95,7 +95,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
using var emptyVb = gd.BufferManager.Create(gd, EmptyVbSize);
|
||||
emptyVb.SetData(0, new byte[EmptyVbSize]);
|
||||
_vertexBuffers[0] = new VertexBufferState(emptyVb.GetBuffer(), 0, EmptyVbSize, 0);
|
||||
_vertexBuffers[0] = new VertexBufferState(emptyVb.GetBuffer(), 0, 0, EmptyVbSize, 0);
|
||||
_vertexBuffersDirty = ulong.MaxValue >> (64 - _vertexBuffers.Length);
|
||||
|
||||
ClearScissor = new Rectangle<int>(0, 0, 0xffff, 0xffff);
|
||||
@@ -150,7 +150,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
EndRenderPass();
|
||||
|
||||
var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, true).Get(Cbs, offset, size).Value;
|
||||
var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, offset, size, true).Get(Cbs, offset, size).Value;
|
||||
|
||||
BufferHolder.InsertBufferBarrier(
|
||||
Gd,
|
||||
@@ -238,8 +238,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
EndRenderPass();
|
||||
|
||||
var src = Gd.BufferManager.GetBuffer(CommandBuffer, source, false);
|
||||
var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, true);
|
||||
var src = Gd.BufferManager.GetBuffer(CommandBuffer, source, srcOffset, size, false);
|
||||
var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, dstOffset, size, true);
|
||||
|
||||
BufferHolder.Copy(Gd, Cbs, src, dst, srcOffset, dstOffset, size);
|
||||
}
|
||||
@@ -388,7 +388,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
var oldDepthTestEnable = _newState.DepthTestEnable;
|
||||
var oldDepthWriteEnable = _newState.DepthWriteEnable;
|
||||
var oldTopology = _newState.Topology;
|
||||
var oldViewports = _dynamicState.Viewports;
|
||||
var oldViewports = DynamicState.Viewports;
|
||||
var oldViewportsCount = _newState.ViewportsCount;
|
||||
|
||||
_newState.CullMode = CullModeFlags.CullModeNone;
|
||||
@@ -411,9 +411,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_newState.DepthWriteEnable = oldDepthWriteEnable;
|
||||
_newState.Topology = oldTopology;
|
||||
|
||||
_dynamicState.Viewports = oldViewports;
|
||||
_dynamicState.ViewportsCount = (int)oldViewportsCount;
|
||||
_dynamicState.SetViewportsDirty();
|
||||
DynamicState.Viewports = oldViewports;
|
||||
DynamicState.ViewportsCount = (int)oldViewportsCount;
|
||||
DynamicState.SetViewportsDirty();
|
||||
|
||||
_newState.ViewportsCount = oldViewportsCount;
|
||||
SignalStateChange();
|
||||
@@ -448,8 +448,13 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
ResumeTransformFeedbackInternal();
|
||||
DrawCount++;
|
||||
|
||||
var buffer = Gd.BufferManager.GetBuffer(CommandBuffer, indirectBuffer.Handle, true).Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
|
||||
var countBuffer = Gd.BufferManager.GetBuffer(CommandBuffer, parameterBuffer.Handle, true).Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value;
|
||||
var buffer = Gd.BufferManager
|
||||
.GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, true)
|
||||
.Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
|
||||
|
||||
var countBuffer = Gd.BufferManager
|
||||
.GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, true)
|
||||
.Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value;
|
||||
|
||||
Gd.DrawIndirectCountApi.CmdDrawIndirectCount(
|
||||
CommandBuffer,
|
||||
@@ -478,8 +483,13 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
ResumeTransformFeedbackInternal();
|
||||
DrawCount++;
|
||||
|
||||
var buffer = Gd.BufferManager.GetBuffer(CommandBuffer, indirectBuffer.Handle, true).Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
|
||||
var countBuffer = Gd.BufferManager.GetBuffer(CommandBuffer, parameterBuffer.Handle, true).Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value;
|
||||
var buffer = Gd.BufferManager
|
||||
.GetBuffer(CommandBuffer, indirectBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, true)
|
||||
.Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
|
||||
|
||||
var countBuffer = Gd.BufferManager
|
||||
.GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, true)
|
||||
.Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value;
|
||||
|
||||
Gd.DrawIndirectCountApi.CmdDrawIndexedIndirectCount(
|
||||
CommandBuffer,
|
||||
@@ -525,17 +535,18 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
vkBlend = new PipelineColorBlendAttachmentState();
|
||||
}
|
||||
|
||||
_newState.BlendConstantR = blend.BlendConstant.Red;
|
||||
_newState.BlendConstantG = blend.BlendConstant.Green;
|
||||
_newState.BlendConstantB = blend.BlendConstant.Blue;
|
||||
_newState.BlendConstantA = blend.BlendConstant.Alpha;
|
||||
DynamicState.SetBlendConstants(
|
||||
blend.BlendConstant.Red,
|
||||
blend.BlendConstant.Green,
|
||||
blend.BlendConstant.Blue,
|
||||
blend.BlendConstant.Alpha);
|
||||
|
||||
SignalStateChange();
|
||||
}
|
||||
|
||||
public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp)
|
||||
{
|
||||
_dynamicState.SetDepthBias(factor, units, clamp);
|
||||
DynamicState.SetDepthBias(factor, units, clamp);
|
||||
|
||||
_newState.DepthBiasEnable = enables != 0;
|
||||
SignalStateChange();
|
||||
@@ -753,10 +764,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
var offset = new Offset2D(region.X, region.Y);
|
||||
var extent = new Extent2D((uint)region.Width, (uint)region.Height);
|
||||
|
||||
_dynamicState.SetScissor(i, new Rect2D(offset, extent));
|
||||
DynamicState.SetScissor(i, new Rect2D(offset, extent));
|
||||
}
|
||||
|
||||
_dynamicState.ScissorsCount = count;
|
||||
DynamicState.ScissorsCount = count;
|
||||
|
||||
_newState.ScissorsCount = (uint)count;
|
||||
SignalStateChange();
|
||||
@@ -764,7 +775,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public void SetStencilTest(StencilTestDescriptor stencilTest)
|
||||
{
|
||||
_dynamicState.SetStencilMasks(
|
||||
DynamicState.SetStencilMasks(
|
||||
(uint)stencilTest.BackFuncMask,
|
||||
(uint)stencilTest.BackMask,
|
||||
(uint)stencilTest.BackFuncRef,
|
||||
@@ -813,7 +824,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
if (range.Handle != BufferHandle.Null)
|
||||
{
|
||||
_transformFeedbackBuffers[i] = new BufferState(Gd.BufferManager.GetBuffer(CommandBuffer, range.Handle, true), range.Offset, range.Size);
|
||||
_transformFeedbackBuffers[i] =
|
||||
new BufferState(Gd.BufferManager.GetBuffer(CommandBuffer, range.Handle, range.Offset, range.Size, true), range.Offset, range.Size);
|
||||
_transformFeedbackBuffers[i].BindTransformFeedbackBuffer(Gd, Cbs, (uint)i);
|
||||
}
|
||||
else
|
||||
@@ -975,7 +987,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
var viewport = viewports[i];
|
||||
|
||||
_dynamicState.SetViewport(i, new Silk.NET.Vulkan.Viewport(
|
||||
DynamicState.SetViewport(i, new Silk.NET.Vulkan.Viewport(
|
||||
viewport.Region.X,
|
||||
viewport.Region.Y,
|
||||
viewport.Region.Width == 0f ? 1f : viewport.Region.Width,
|
||||
@@ -984,7 +996,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
Clamp(viewport.DepthFar)));
|
||||
}
|
||||
|
||||
_dynamicState.ViewportsCount = count;
|
||||
DynamicState.ViewportsCount = count;
|
||||
|
||||
float disableTransformF = disableTransform ? 1.0f : 0.0f;
|
||||
if (SupportBufferUpdater.Data.ViewportInverse.W != disableTransformF || disableTransform)
|
||||
@@ -1063,7 +1075,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_vertexBuffersDirty = ulong.MaxValue >> (64 - _vertexBuffers.Length);
|
||||
|
||||
_descriptorSetUpdater.SignalCommandBufferChange();
|
||||
_dynamicState.ForceAllDirty();
|
||||
DynamicState.ForceAllDirty();
|
||||
_currentPipelineHandle = 0;
|
||||
}
|
||||
|
||||
@@ -1201,7 +1213,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
private void RecreatePipelineIfNeeded(PipelineBindPoint pbp)
|
||||
{
|
||||
_dynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
|
||||
DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
|
||||
|
||||
// Commit changes to the support buffer before drawing.
|
||||
SupportBufferUpdater.Commit();
|
||||
@@ -1232,7 +1244,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
_vertexBuffers[i].BindVertexBuffer(Gd, Cbs, (uint)i, ref _newState);
|
||||
|
||||
_vertexBuffersDirty &= ~(1u << i);
|
||||
_vertexBuffersDirty &= ~(1UL << i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -135,11 +135,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
// It is assumed that Dynamic State is enabled when this conversion is used.
|
||||
|
||||
pipeline.BlendConstantA = state.BlendDescriptors[0].BlendConstant.Alpha;
|
||||
pipeline.BlendConstantB = state.BlendDescriptors[0].BlendConstant.Blue;
|
||||
pipeline.BlendConstantG = state.BlendDescriptors[0].BlendConstant.Green;
|
||||
pipeline.BlendConstantR = state.BlendDescriptors[0].BlendConstant.Red;
|
||||
|
||||
pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.CullModeNone;
|
||||
|
||||
pipeline.DepthBoundsTestEnable = false; // Not implemented.
|
||||
|
@@ -19,21 +19,34 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
private uint _frontWriteMask;
|
||||
private uint _frontReference;
|
||||
|
||||
private Array4<float> _blendConstants;
|
||||
|
||||
public int ViewportsCount;
|
||||
public Array16<Viewport> Viewports;
|
||||
|
||||
private enum DirtyFlags
|
||||
{
|
||||
None = 0,
|
||||
DepthBias = 1 << 0,
|
||||
Scissor = 1 << 1,
|
||||
Stencil = 1 << 2,
|
||||
Viewport = 1 << 3,
|
||||
All = DepthBias | Scissor | Stencil | Viewport
|
||||
Blend = 1 << 0,
|
||||
DepthBias = 1 << 1,
|
||||
Scissor = 1 << 2,
|
||||
Stencil = 1 << 3,
|
||||
Viewport = 1 << 4,
|
||||
All = Blend | DepthBias | Scissor | Stencil | Viewport
|
||||
}
|
||||
|
||||
private DirtyFlags _dirty;
|
||||
|
||||
public void SetBlendConstants(float r, float g, float b, float a)
|
||||
{
|
||||
_blendConstants[0] = r;
|
||||
_blendConstants[1] = g;
|
||||
_blendConstants[2] = b;
|
||||
_blendConstants[3] = a;
|
||||
|
||||
_dirty |= DirtyFlags.Blend;
|
||||
}
|
||||
|
||||
public void SetDepthBias(float slopeFactor, float constantFactor, float clamp)
|
||||
{
|
||||
_depthBiasSlopeFactor = slopeFactor;
|
||||
@@ -87,6 +100,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public void ReplayIfDirty(Vk api, CommandBuffer commandBuffer)
|
||||
{
|
||||
if (_dirty.HasFlag(DirtyFlags.Blend))
|
||||
{
|
||||
RecordBlend(api, commandBuffer);
|
||||
}
|
||||
|
||||
if (_dirty.HasFlag(DirtyFlags.DepthBias))
|
||||
{
|
||||
RecordDepthBias(api, commandBuffer);
|
||||
@@ -110,6 +128,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_dirty = DirtyFlags.None;
|
||||
}
|
||||
|
||||
private void RecordBlend(Vk api, CommandBuffer commandBuffer)
|
||||
{
|
||||
api.CmdSetBlendConstants(commandBuffer, _blendConstants.AsSpan());
|
||||
}
|
||||
|
||||
private void RecordDepthBias(Vk api, CommandBuffer commandBuffer)
|
||||
{
|
||||
api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor);
|
||||
|
@@ -204,6 +204,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
|
||||
SignalCommandBufferChange();
|
||||
|
||||
DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
|
||||
}
|
||||
|
||||
public void FlushCommandsImpl()
|
||||
|
@@ -499,7 +499,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
colorBlendState.BlendConstants[3] = BlendConstantA;
|
||||
|
||||
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
|
||||
int dynamicStatesCount = supportsExtDynamicState ? 8 : 7;
|
||||
int dynamicStatesCount = supportsExtDynamicState ? 9 : 8;
|
||||
|
||||
DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount];
|
||||
|
||||
@@ -510,10 +510,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
dynamicStates[4] = DynamicState.StencilCompareMask;
|
||||
dynamicStates[5] = DynamicState.StencilWriteMask;
|
||||
dynamicStates[6] = DynamicState.StencilReference;
|
||||
dynamicStates[7] = DynamicState.BlendConstants;
|
||||
|
||||
if (supportsExtDynamicState)
|
||||
{
|
||||
dynamicStates[7] = DynamicState.VertexInputBindingStrideExt;
|
||||
dynamicStates[8] = DynamicState.VertexInputBindingStrideExt;
|
||||
}
|
||||
|
||||
var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo()
|
||||
|
@@ -64,6 +64,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
};
|
||||
|
||||
samplerCreateInfo.PNext = &customBorderColor;
|
||||
samplerCreateInfo.BorderColor = BorderColor.FloatCustomExt;
|
||||
}
|
||||
|
||||
gd.Api.CreateSampler(device, samplerCreateInfo, null, out var sampler).ThrowOnError();
|
||||
|
@@ -9,17 +9,19 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
class Shader
|
||||
class Shader : IDisposable
|
||||
{
|
||||
// The shaderc.net dependency's Options constructor and dispose are not thread safe.
|
||||
// Take this lock when using them.
|
||||
private static object _shaderOptionsLock = new object();
|
||||
|
||||
private static readonly IntPtr _ptrMainEntryPointName = Marshal.StringToHGlobalAnsi("main");
|
||||
|
||||
private readonly Vk _api;
|
||||
private readonly Device _device;
|
||||
private readonly ShaderStageFlags _stage;
|
||||
|
||||
private IntPtr _entryPointName;
|
||||
private bool _disposed;
|
||||
private ShaderModule _module;
|
||||
|
||||
public ShaderStageFlags StageFlags => _stage;
|
||||
@@ -39,7 +41,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
CompileStatus = ProgramLinkStatus.Incomplete;
|
||||
|
||||
_stage = shaderSource.Stage.Convert();
|
||||
_entryPointName = Marshal.StringToHGlobalAnsi("main");
|
||||
|
||||
CompileTask = Task.Run(() =>
|
||||
{
|
||||
@@ -145,7 +146,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
SType = StructureType.PipelineShaderStageCreateInfo,
|
||||
Stage = _stage,
|
||||
Module = _module,
|
||||
PName = (byte*)_entryPointName
|
||||
PName = (byte*)_ptrMainEntryPointName
|
||||
};
|
||||
}
|
||||
|
||||
@@ -156,11 +157,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
if (_entryPointName != IntPtr.Zero)
|
||||
if (!_disposed)
|
||||
{
|
||||
_api.DestroyShaderModule(_device, _module, null);
|
||||
Marshal.FreeHGlobal(_entryPointName);
|
||||
_entryPointName = IntPtr.Zero;
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -87,7 +87,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
private void PushDataImpl(CommandBufferScoped cbs, BufferHolder dst, int dstOffset, ReadOnlySpan<byte> data)
|
||||
{
|
||||
var srcBuffer = _buffer.GetBuffer();
|
||||
var dstBuffer = dst.GetBuffer();
|
||||
var dstBuffer = dst.GetBuffer(cbs.CommandBuffer, dstOffset, data.Length, true);
|
||||
|
||||
int offset = _freeOffset;
|
||||
int capacity = BufferSize - offset;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Silk.NET.Vulkan;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -16,6 +17,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
private Auto<DisposableBufferView> _bufferView;
|
||||
private Dictionary<GAL.Format, Auto<DisposableBufferView>> _selfManagedViews;
|
||||
|
||||
private int _bufferCount;
|
||||
|
||||
public int Width { get; }
|
||||
public int Height { get; }
|
||||
|
||||
@@ -88,17 +91,17 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_bufferView = null;
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data)
|
||||
public void SetData(SpanOrArray<byte> data)
|
||||
{
|
||||
_gd.SetBufferData(_bufferHandle, _offset, data);
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level)
|
||||
public void SetData(SpanOrArray<byte> data, int layer, int level)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
|
||||
public void SetData(SpanOrArray<byte> data, int layer, int level, Rectangle<int> region)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
@@ -107,7 +110,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
if (_bufferHandle == buffer.Handle &&
|
||||
_offset == buffer.Offset &&
|
||||
_size == buffer.Size)
|
||||
_size == buffer.Size &&
|
||||
_bufferCount == _gd.BufferManager.BufferCount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -115,6 +119,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_bufferHandle = buffer.Handle;
|
||||
_offset = buffer.Offset;
|
||||
_size = buffer.Size;
|
||||
_bufferCount = _gd.BufferManager.BufferCount;
|
||||
|
||||
ReleaseImpl();
|
||||
}
|
||||
|
@@ -480,6 +480,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
if (--_viewsCount == 0)
|
||||
{
|
||||
_gd.PipelineInternal?.FlushCommandsIfWeightExceeding(_imageAuto, _size);
|
||||
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Silk.NET.Vulkan;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -514,10 +515,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
dst.Info,
|
||||
srcRegion,
|
||||
dstRegion,
|
||||
src.FirstLevel,
|
||||
dst.FirstLevel,
|
||||
src.FirstLayer,
|
||||
dst.FirstLayer,
|
||||
src.FirstLevel,
|
||||
dst.FirstLevel,
|
||||
layers,
|
||||
levels,
|
||||
linearFilter,
|
||||
@@ -873,17 +874,17 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return GetDataFromBuffer(result, size, result);
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data)
|
||||
public void SetData(SpanOrArray<byte> data)
|
||||
{
|
||||
SetData(data, 0, 0, Info.GetLayers(), Info.Levels, singleSlice: false);
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level)
|
||||
public void SetData(SpanOrArray<byte> data, int layer, int level)
|
||||
{
|
||||
SetData(data, layer, level, 1, 1, singleSlice: true);
|
||||
}
|
||||
|
||||
public void SetData(ReadOnlySpan<byte> data, int layer, int level, Rectangle<int> region)
|
||||
public void SetData(SpanOrArray<byte> data, int layer, int level, Rectangle<int> region)
|
||||
{
|
||||
SetData(data, layer, level, 1, 1, singleSlice: true, region);
|
||||
}
|
||||
|
@@ -57,37 +57,48 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
if (gd.NeedsVertexBufferAlignment(AttributeScalarAlignment, out int alignment) && (_stride % alignment) != 0)
|
||||
{
|
||||
autoBuffer = gd.BufferManager.GetAlignedVertexBuffer(cbs, _handle, _offset, _size, _stride, alignment);
|
||||
int stride = (_stride + (alignment - 1)) & -alignment;
|
||||
|
||||
var buffer = autoBuffer.Get(cbs, _offset, _size).Value;
|
||||
if (autoBuffer != null)
|
||||
{
|
||||
int stride = (_stride + (alignment - 1)) & -alignment;
|
||||
int newSize = (_size / _stride) * stride;
|
||||
|
||||
if (gd.Capabilities.SupportsExtendedDynamicState)
|
||||
{
|
||||
gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2(
|
||||
cbs.CommandBuffer,
|
||||
binding,
|
||||
1,
|
||||
buffer,
|
||||
0,
|
||||
(ulong)(_size / _stride) * (ulong)stride,
|
||||
(ulong)stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
gd.Api.CmdBindVertexBuffers(cbs.CommandBuffer, binding, 1, buffer, 0);
|
||||
var buffer = autoBuffer.Get(cbs, 0, newSize).Value;
|
||||
|
||||
if (gd.Capabilities.SupportsExtendedDynamicState)
|
||||
{
|
||||
gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2(
|
||||
cbs.CommandBuffer,
|
||||
binding,
|
||||
1,
|
||||
buffer,
|
||||
0,
|
||||
(ulong)newSize,
|
||||
(ulong)stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
gd.Api.CmdBindVertexBuffers(cbs.CommandBuffer, binding, 1, buffer, 0);
|
||||
}
|
||||
|
||||
_buffer = autoBuffer;
|
||||
}
|
||||
|
||||
_buffer = autoBuffer;
|
||||
state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)stride;
|
||||
state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)_stride;
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int _);
|
||||
autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int size);
|
||||
|
||||
// The original stride must be reapplied in case it was rewritten.
|
||||
state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)_stride;
|
||||
|
||||
if (_offset >= size)
|
||||
{
|
||||
autoBuffer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -310,7 +310,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
internal TextureView CreateTextureView(TextureCreateInfo info, float scale)
|
||||
{
|
||||
// This should be disposed when all views are destroyed.
|
||||
using var storage = CreateTextureStorage(info, scale);
|
||||
var storage = CreateTextureStorage(info, scale);
|
||||
return storage.CreateView(info, 0, 0);
|
||||
}
|
||||
|
||||
|
@@ -918,7 +918,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
|
||||
return -1;
|
||||
}
|
||||
|
||||
return int.Parse(part.Substring(0, numberLength));
|
||||
return int.Parse(part.AsSpan(0, numberLength));
|
||||
}
|
||||
|
||||
private string ParseNumber(bool isSigned = false)
|
||||
|
@@ -2540,11 +2540,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||
|
||||
for (int attempt = 0; attempt < 8; attempt++)
|
||||
{
|
||||
address = BitUtils.AlignDown(regionStart + GetRandomValue(0, aslrMaxOffset) * (ulong)alignment, alignment);
|
||||
ulong aslrAddress = BitUtils.AlignDown(regionStart + GetRandomValue(0, aslrMaxOffset) * (ulong)alignment, alignment);
|
||||
ulong aslrEndAddr = aslrAddress + totalNeededSize;
|
||||
|
||||
ulong endAddr = address + totalNeededSize;
|
||||
|
||||
KMemoryInfo info = _blockManager.FindBlock(address).GetInfo();
|
||||
KMemoryInfo info = _blockManager.FindBlock(aslrAddress).GetInfo();
|
||||
|
||||
if (info.State != MemoryState.Unmapped)
|
||||
{
|
||||
@@ -2554,11 +2553,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||
ulong currBaseAddr = info.Address + reservedPagesCount * PageSize;
|
||||
ulong currEndAddr = info.Address + info.Size;
|
||||
|
||||
if (address >= regionStart &&
|
||||
address >= currBaseAddr &&
|
||||
endAddr - 1 <= regionEndAddr - 1 &&
|
||||
endAddr - 1 <= currEndAddr - 1)
|
||||
if (aslrAddress >= regionStart &&
|
||||
aslrAddress >= currBaseAddr &&
|
||||
aslrEndAddr - 1 <= regionEndAddr - 1 &&
|
||||
aslrEndAddr - 1 <= currEndAddr - 1)
|
||||
{
|
||||
address = aslrAddress;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2603,7 +2603,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||
|
||||
ulong totalNeededSize = reservedSize + neededPagesCount * PageSize;
|
||||
|
||||
ulong regionEndAddr = regionStart + regionPagesCount * PageSize;
|
||||
ulong regionEndAddr = (regionStart + regionPagesCount * PageSize) - 1;
|
||||
|
||||
KMemoryBlock currBlock = _blockManager.FindBlock(regionStart);
|
||||
|
||||
|
@@ -38,18 +38,17 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
|
||||
// Read() -> (u32, buffer<nn::bcat::DeliveryCacheDirectoryEntry, 6>)
|
||||
public ResultCode Read(ServiceCtx context)
|
||||
{
|
||||
ulong position = context.Request.ReceiveBuff[0].Position;
|
||||
ulong size = context.Request.ReceiveBuff[0].Size;
|
||||
ulong bufferAddress = context.Request.ReceiveBuff[0].Position;
|
||||
ulong bufferLen = context.Request.ReceiveBuff[0].Size;
|
||||
|
||||
byte[] data = new byte[size];
|
||||
using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true))
|
||||
{
|
||||
Result result = _base.Get.Read(out int entriesRead, MemoryMarshal.Cast<byte, DeliveryCacheDirectoryEntry>(region.Memory.Span));
|
||||
|
||||
Result result = _base.Get.Read(out int entriesRead, MemoryMarshal.Cast<byte, DeliveryCacheDirectoryEntry>(data));
|
||||
context.ResponseData.Write(entriesRead);
|
||||
|
||||
context.Memory.Write(position, data);
|
||||
|
||||
context.ResponseData.Write(entriesRead);
|
||||
|
||||
return (ResultCode)result.Value;
|
||||
return (ResultCode)result.Value;
|
||||
}
|
||||
}
|
||||
|
||||
[CommandHipc(2)]
|
||||
|
@@ -38,20 +38,19 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
|
||||
// Read(u64) -> (u64, buffer<bytes, 6>)
|
||||
public ResultCode Read(ServiceCtx context)
|
||||
{
|
||||
ulong position = context.Request.ReceiveBuff[0].Position;
|
||||
ulong size = context.Request.ReceiveBuff[0].Size;
|
||||
ulong bufferAddress = context.Request.ReceiveBuff[0].Position;
|
||||
ulong bufferLen = context.Request.ReceiveBuff[0].Size;
|
||||
|
||||
long offset = context.RequestData.ReadInt64();
|
||||
|
||||
byte[] data = new byte[size];
|
||||
using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true))
|
||||
{
|
||||
Result result = _base.Get.Read(out long bytesRead, offset, region.Memory.Span);
|
||||
|
||||
Result result = _base.Get.Read(out long bytesRead, offset, data);
|
||||
context.ResponseData.Write(bytesRead);
|
||||
|
||||
context.Memory.Write(position, data);
|
||||
|
||||
context.ResponseData.Write(bytesRead);
|
||||
|
||||
return (ResultCode)result.Value;
|
||||
return (ResultCode)result.Value;
|
||||
}
|
||||
}
|
||||
|
||||
[CommandHipc(2)]
|
||||
|
@@ -50,18 +50,17 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
|
||||
// EnumerateDeliveryCacheDirectory() -> (u32, buffer<nn::bcat::DirectoryName, 6>)
|
||||
public ResultCode EnumerateDeliveryCacheDirectory(ServiceCtx context)
|
||||
{
|
||||
ulong position = context.Request.ReceiveBuff[0].Position;
|
||||
ulong size = context.Request.ReceiveBuff[0].Size;
|
||||
ulong bufferAddress = context.Request.ReceiveBuff[0].Position;
|
||||
ulong bufferLen = context.Request.ReceiveBuff[0].Size;
|
||||
|
||||
byte[] data = new byte[size];
|
||||
using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true))
|
||||
{
|
||||
Result result = _base.Get.EnumerateDeliveryCacheDirectory(out int count, MemoryMarshal.Cast<byte, DirectoryName>(region.Memory.Span));
|
||||
|
||||
Result result = _base.Get.EnumerateDeliveryCacheDirectory(out int count, MemoryMarshal.Cast<byte, DirectoryName>(data));
|
||||
context.ResponseData.Write(count);
|
||||
|
||||
context.Memory.Write(position, data);
|
||||
|
||||
context.ResponseData.Write(count);
|
||||
|
||||
return (ResultCode)result.Value;
|
||||
return (ResultCode)result.Value;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
|
@@ -1,8 +1,147 @@
|
||||
namespace Ryujinx.HLE.HOS.Services.Fatal
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.HOS.Services.Fatal.Types;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Fatal
|
||||
{
|
||||
[Service("fatal:u")]
|
||||
class IService : IpcService
|
||||
{
|
||||
public IService(ServiceCtx context) { }
|
||||
|
||||
[CommandHipc(0)]
|
||||
// ThrowFatal(u64 result_code, u64 pid)
|
||||
public ResultCode ThrowFatal(ServiceCtx context)
|
||||
{
|
||||
ResultCode resultCode = (ResultCode)context.RequestData.ReadUInt64();
|
||||
ulong pid = context.Request.HandleDesc.PId;
|
||||
|
||||
return ThrowFatalWithCpuContextImpl(context, resultCode, pid, FatalPolicy.ErrorReportAndErrorScreen, null);
|
||||
}
|
||||
|
||||
[CommandHipc(1)]
|
||||
// ThrowFatalWithPolicy(u64 result_code, u32 fatal_policy, u64 pid)
|
||||
public ResultCode ThrowFatalWithPolicy(ServiceCtx context)
|
||||
{
|
||||
ResultCode resultCode = (ResultCode)context.RequestData.ReadUInt64();
|
||||
FatalPolicy fatalPolicy = (FatalPolicy)context.RequestData.ReadUInt32();
|
||||
ulong pid = context.Request.HandleDesc.PId;
|
||||
|
||||
return ThrowFatalWithCpuContextImpl(context, resultCode, pid, fatalPolicy, null);
|
||||
}
|
||||
|
||||
[CommandHipc(2)]
|
||||
// ThrowFatalWithCpuContext(u64 result_code, u32 fatal_policy, u64 pid, buffer<bytes, 0x15> cpu_context)
|
||||
public ResultCode ThrowFatalWithCpuContext(ServiceCtx context)
|
||||
{
|
||||
ResultCode resultCode = (ResultCode)context.RequestData.ReadUInt64();
|
||||
FatalPolicy fatalPolicy = (FatalPolicy)context.RequestData.ReadUInt32();
|
||||
ulong pid = context.Request.HandleDesc.PId;
|
||||
|
||||
ulong cpuContextPosition = context.Request.SendBuff[0].Position;
|
||||
ulong cpuContextSize = context.Request.SendBuff[0].Size;
|
||||
|
||||
ReadOnlySpan<byte> cpuContextData = context.Memory.GetSpan(cpuContextPosition, (int)cpuContextSize);
|
||||
|
||||
return ThrowFatalWithCpuContextImpl(context, resultCode, pid, fatalPolicy, cpuContextData);
|
||||
}
|
||||
|
||||
private ResultCode ThrowFatalWithCpuContextImpl(ServiceCtx context, ResultCode resultCode, ulong pid, FatalPolicy fatalPolicy, ReadOnlySpan<byte> cpuContext)
|
||||
{
|
||||
StringBuilder errorReport = new StringBuilder();
|
||||
|
||||
errorReport.AppendLine();
|
||||
errorReport.AppendLine("ErrorReport log:");
|
||||
|
||||
errorReport.AppendLine($"\tTitleId: {context.Device.Application.TitleId:x16}");
|
||||
errorReport.AppendLine($"\tPid: {pid}");
|
||||
errorReport.AppendLine($"\tResultCode: {((int)resultCode & 0x1FF) + 2000}-{((int)resultCode >> 9) & 0x3FFF:d4}");
|
||||
errorReport.AppendLine($"\tFatalPolicy: {fatalPolicy}");
|
||||
|
||||
if (cpuContext != null)
|
||||
{
|
||||
errorReport.AppendLine("CPU Context:");
|
||||
|
||||
if (context.Device.Application.TitleIs64Bit)
|
||||
{
|
||||
CpuContext64 cpuContext64 = MemoryMarshal.Cast<byte, CpuContext64>(cpuContext)[0];
|
||||
|
||||
errorReport.AppendLine($"\tStartAddress: 0x{cpuContext64.StartAddress:x16}");
|
||||
errorReport.AppendLine($"\tRegisterSetFlags: {cpuContext64.RegisterSetFlags}");
|
||||
|
||||
if (cpuContext64.StackTraceSize > 0)
|
||||
{
|
||||
errorReport.AppendLine("\tStackTrace:");
|
||||
|
||||
for (int i = 0; i < cpuContext64.StackTraceSize; i++)
|
||||
{
|
||||
errorReport.AppendLine($"\t\t0x{cpuContext64.StackTrace[i]:x16}");
|
||||
}
|
||||
}
|
||||
|
||||
errorReport.AppendLine("\tRegisters:");
|
||||
|
||||
for (int i = 0; i < cpuContext64.X.Length; i++)
|
||||
{
|
||||
errorReport.AppendLine($"\t\tX[{i:d2}]:\t0x{cpuContext64.X[i]:x16}");
|
||||
}
|
||||
|
||||
errorReport.AppendLine();
|
||||
errorReport.AppendLine($"\t\tFP:\t0x{cpuContext64.FP:x16}");
|
||||
errorReport.AppendLine($"\t\tLR:\t0x{cpuContext64.LR:x16}");
|
||||
errorReport.AppendLine($"\t\tSP:\t0x{cpuContext64.SP:x16}");
|
||||
errorReport.AppendLine($"\t\tPC:\t0x{cpuContext64.PC:x16}");
|
||||
errorReport.AppendLine($"\t\tPState:\t0x{cpuContext64.PState:x16}");
|
||||
errorReport.AppendLine($"\t\tAfsr0:\t0x{cpuContext64.Afsr0:x16}");
|
||||
errorReport.AppendLine($"\t\tAfsr1:\t0x{cpuContext64.Afsr1:x16}");
|
||||
errorReport.AppendLine($"\t\tEsr:\t0x{cpuContext64.Esr:x16}");
|
||||
errorReport.AppendLine($"\t\tFar:\t0x{cpuContext64.Far:x16}");
|
||||
}
|
||||
else
|
||||
{
|
||||
CpuContext32 cpuContext32 = MemoryMarshal.Cast<byte, CpuContext32>(cpuContext)[0];
|
||||
|
||||
errorReport.AppendLine($"\tStartAddress: 0x{cpuContext32.StartAddress:16}");
|
||||
errorReport.AppendLine($"\tRegisterSetFlags: {cpuContext32.RegisterSetFlags}");
|
||||
|
||||
if (cpuContext32.StackTraceSize > 0)
|
||||
{
|
||||
errorReport.AppendLine("\tStackTrace:");
|
||||
|
||||
for (int i = 0; i < cpuContext32.StackTraceSize; i++)
|
||||
{
|
||||
errorReport.AppendLine($"\t\t0x{cpuContext32.StackTrace[i]:x16}");
|
||||
}
|
||||
}
|
||||
|
||||
errorReport.AppendLine("\tRegisters:");
|
||||
|
||||
for (int i = 0; i < cpuContext32.X.Length; i++)
|
||||
{
|
||||
errorReport.AppendLine($"\t\tX[{i:d2}]:\t0x{cpuContext32.X[i]:x16}");
|
||||
}
|
||||
|
||||
errorReport.AppendLine();
|
||||
errorReport.AppendLine($"\t\tFP:\t0x{cpuContext32.FP:x16}");
|
||||
errorReport.AppendLine($"\t\tFP:\t0x{cpuContext32.IP:x16}");
|
||||
errorReport.AppendLine($"\t\tSP:\t0x{cpuContext32.SP:x16}");
|
||||
errorReport.AppendLine($"\t\tLR:\t0x{cpuContext32.LR:x16}");
|
||||
errorReport.AppendLine($"\t\tPC:\t0x{cpuContext32.PC:x16}");
|
||||
errorReport.AppendLine($"\t\tPState:\t0x{cpuContext32.PState:x16}");
|
||||
errorReport.AppendLine($"\t\tAfsr0:\t0x{cpuContext32.Afsr0:x16}");
|
||||
errorReport.AppendLine($"\t\tAfsr1:\t0x{cpuContext32.Afsr1:x16}");
|
||||
errorReport.AppendLine($"\t\tEsr:\t0x{cpuContext32.Esr:x16}");
|
||||
errorReport.AppendLine($"\t\tFar:\t0x{cpuContext32.Far:x16}");
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Info?.Print(LogClass.ServiceFatal, errorReport.ToString());
|
||||
|
||||
context.Device.System.KernelContext.Syscall.Break((ulong)resultCode);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
}
|
||||
}
|
25
Ryujinx.HLE/HOS/Services/Fatal/Types/CpuContext32.cs
Normal file
25
Ryujinx.HLE/HOS/Services/Fatal/Types/CpuContext32.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Fatal.Types
|
||||
{
|
||||
public struct CpuContext32
|
||||
{
|
||||
public Array11<uint> X;
|
||||
public uint FP;
|
||||
public uint IP;
|
||||
public uint SP;
|
||||
public uint LR;
|
||||
public uint PC;
|
||||
|
||||
public uint PState;
|
||||
public uint Afsr0;
|
||||
public uint Afsr1;
|
||||
public uint Esr;
|
||||
public uint Far;
|
||||
|
||||
public Array32<uint> StackTrace;
|
||||
public uint StackTraceSize;
|
||||
public uint StartAddress;
|
||||
public uint RegisterSetFlags;
|
||||
}
|
||||
}
|
24
Ryujinx.HLE/HOS/Services/Fatal/Types/CpuContext64.cs
Normal file
24
Ryujinx.HLE/HOS/Services/Fatal/Types/CpuContext64.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Fatal.Types
|
||||
{
|
||||
public struct CpuContext64
|
||||
{
|
||||
public Array29<ulong> X;
|
||||
public ulong FP;
|
||||
public ulong LR;
|
||||
public ulong SP;
|
||||
public ulong PC;
|
||||
|
||||
public ulong PState;
|
||||
public ulong Afsr0;
|
||||
public ulong Afsr1;
|
||||
public ulong Esr;
|
||||
public ulong Far;
|
||||
|
||||
public Array32<ulong> StackTrace;
|
||||
public ulong StartAddress;
|
||||
public ulong RegisterSetFlags;
|
||||
public uint StackTraceSize;
|
||||
}
|
||||
}
|
9
Ryujinx.HLE/HOS/Services/Fatal/Types/FatalPolicy.cs
Normal file
9
Ryujinx.HLE/HOS/Services/Fatal/Types/FatalPolicy.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Ryujinx.HLE.HOS.Services.Fatal.Types
|
||||
{
|
||||
enum FatalPolicy
|
||||
{
|
||||
ErrorReportAndErrorScreen,
|
||||
ErrorReport,
|
||||
ErrorScreen
|
||||
}
|
||||
}
|
@@ -17,17 +17,17 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
||||
// Read() -> (u64 count, buffer<nn::fssrv::sf::IDirectoryEntry, 6, 0> entries)
|
||||
public ResultCode Read(ServiceCtx context)
|
||||
{
|
||||
ulong bufferPosition = context.Request.ReceiveBuff[0].Position;
|
||||
ulong bufferAddress = context.Request.ReceiveBuff[0].Position;
|
||||
ulong bufferLen = context.Request.ReceiveBuff[0].Size;
|
||||
|
||||
byte[] entryBuffer = new byte[bufferLen];
|
||||
using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true))
|
||||
{
|
||||
Result result = _baseDirectory.Get.Read(out long entriesRead, new OutBuffer(region.Memory.Span));
|
||||
|
||||
Result result = _baseDirectory.Get.Read(out long entriesRead, new OutBuffer(entryBuffer));
|
||||
context.ResponseData.Write(entriesRead);
|
||||
|
||||
context.Memory.Write(bufferPosition, entryBuffer);
|
||||
context.ResponseData.Write(entriesRead);
|
||||
|
||||
return (ResultCode)result.Value;
|
||||
return (ResultCode)result.Value;
|
||||
}
|
||||
}
|
||||
|
||||
[CommandHipc(1)]
|
||||
|
@@ -19,7 +19,8 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
||||
// Read(u32 readOption, u64 offset, u64 size) -> (u64 out_size, buffer<u8, 0x46, 0> out_buf)
|
||||
public ResultCode Read(ServiceCtx context)
|
||||
{
|
||||
ulong position = context.Request.ReceiveBuff[0].Position;
|
||||
ulong bufferAddress = context.Request.ReceiveBuff[0].Position;
|
||||
ulong bufferLen = context.Request.ReceiveBuff[0].Size;
|
||||
|
||||
ReadOption readOption = context.RequestData.ReadStruct<ReadOption>();
|
||||
context.RequestData.BaseStream.Position += 4;
|
||||
@@ -27,15 +28,14 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
|
||||
long offset = context.RequestData.ReadInt64();
|
||||
long size = context.RequestData.ReadInt64();
|
||||
|
||||
byte[] data = new byte[context.Request.ReceiveBuff[0].Size];
|
||||
using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true))
|
||||
{
|
||||
Result result = _baseFile.Get.Read(out long bytesRead, offset, new OutBuffer(region.Memory.Span), size, readOption);
|
||||
|
||||
Result result = _baseFile.Get.Read(out long bytesRead, offset, new OutBuffer(data), size, readOption);
|
||||
context.ResponseData.Write(bytesRead);
|
||||
|
||||
context.Memory.Write(position, data);
|
||||
|
||||
context.ResponseData.Write(bytesRead);
|
||||
|
||||
return (ResultCode)result.Value;
|
||||
return (ResultCode)result.Value;
|
||||
}
|
||||
}
|
||||
|
||||
[CommandHipc(1)]
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user