Compare commits
174 Commits
Author | SHA1 | Date | |
---|---|---|---|
d3709a753f | |||
ab676d58ea | |||
2372c194f1 | |||
40311310d1 | |||
dde9bb5c69 | |||
266338a7c9 | |||
90156eea4c | |||
071c01c235 | |||
de06ffb0f7 | |||
8a7de35e3f | |||
121296834a | |||
bbb24d8c7e | |||
4da44e09cb | |||
ae13f0ab4d | |||
a2a35f1be6 | |||
aedfadaaf7 | |||
5c0fb0cec3 | |||
17a1cab5d2 | |||
73aed239c3 | |||
9ac66336a2 | |||
4965681e06 | |||
3868a00206 | |||
933e5144a9 | |||
73a42c85c4 | |||
39ba11054b | |||
c250e3392c | |||
e56b069081 | |||
204c031fef | |||
d9053bbe37 | |||
c25e8427aa | |||
21a081b185 | |||
b540ea80d1 | |||
d692a9b83e | |||
9677ddaa5d | |||
ce92e8cd04 | |||
456fc04007 | |||
458452279c | |||
817b89767a | |||
3fb583c98c | |||
d2686e0a5b | |||
4905101df1 | |||
8750b90a7f | |||
af01100050 | |||
c0821fee1f | |||
a5c2aead67 | |||
d41c95dcff | |||
fbf2b09706 | |||
1fc0f569de | |||
dff138229c | |||
472119c8da | |||
1865ea87e5 | |||
18b61aff59 | |||
cb22629ac1 | |||
6f0f99ee2b | |||
70f2da8fdf | |||
5d3ef7761b | |||
476b4683cf | |||
5fb5079730 | |||
3fbacd0f49 | |||
7aa6abc120 | |||
548bfd60a2 | |||
65778a6b78 | |||
f4e879a1e6 | |||
a1ddaa2736 | |||
008286b79f | |||
a0c77f8d11 | |||
ece36b274d | |||
f3cc2e5703 | |||
5a39d3c4a1 | |||
cc51a03af9 | |||
567c64e149 | |||
36f00985d3 | |||
748d87adcc | |||
0fd47ff490 | |||
f088c3d344 | |||
905a191e28 | |||
ab0491817e | |||
5de6ae426e | |||
69ced3a6e8 | |||
2e43d01d36 | |||
7373ec5792 | |||
de162a648b | |||
131baebe2a | |||
187372cbde | |||
022d495335 | |||
c1372ed775 | |||
a16682cfd3 | |||
7c53b69c30 | |||
33a4d7d1ba | |||
391e08dd27 | |||
b5cf8b8af9 | |||
55043c8afc | |||
5d73a9f5fc | |||
2c9ab5e45f | |||
d536cc8ae6 | |||
d751da84f9 | |||
11aae9cfbc | |||
b96794e72b | |||
f1d1670b0b | |||
b8de72de8f | |||
eebc39228d | |||
9daf029f35 | |||
51a27032f0 | |||
a6a67a2b7a | |||
c6d05301aa | |||
647de4cd31 | |||
f82309fa2d | |||
7d8e198c33 | |||
3d98e1361b | |||
141cf61ff7 | |||
3fe3598d41 | |||
59cdf310bd | |||
4e34170a84 | |||
d540af5dc0 | |||
f7c7b66fc0 | |||
28ba55598d | |||
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 | |||
dbe43c1719 | |||
f502cfaf62 | |||
1fd5cf2b4a | |||
814f75142e | |||
4c0eb91d7e | |||
da75a9a6ea | |||
41790aa743 | |||
0cb1e926b5 | |||
6f0395538b |
@ -89,6 +89,7 @@ csharp_style_conditional_delegate_call = true:suggestion
|
||||
# Modifier preferences
|
||||
csharp_prefer_static_local_function = true:suggestion
|
||||
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent
|
||||
csharp_style_prefer_readonly_struct = true
|
||||
|
||||
# Code-block preferences
|
||||
csharp_prefer_braces = true:silent
|
||||
|
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Something doesn't work correctly in Ryujinx. Note that game-specific issues should be instead posted on the Game Compatibility List at https://github.com/Ryujinx/Ryujinx-Games-List, unless it is a provable regression.
|
||||
about: Something doesn't work correctly in Ryujinx. Game-specific issues should be posted at https://github.com/Ryujinx/Ryujinx-Games-List instead, unless it is a provable regression.
|
||||
#assignees:
|
||||
---
|
||||
|
||||
@ -34,7 +34,7 @@ about: Something doesn't work correctly in Ryujinx. Note that game-specific issu
|
||||
- OS: *(e.g. Windows 10)*
|
||||
- CPU: *(e.g. i7-6700)*
|
||||
- GPU: *(e.g. NVIDIA RTX 2070)*
|
||||
- RAM: *(e.g. 16GB)*
|
||||
- RAM: *(e.g. 16GiB)*
|
||||
- Applied Mods : [ Yes (Which ones) / No ]
|
||||
|
||||
### Additional context?
|
||||
|
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
|
29
.github/workflows/build.yml
vendored
29
.github/workflows/build.yml
vendored
@ -48,44 +48,41 @@ 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
|
||||
dotnet-version: 7.0.x
|
||||
- name: Get git short hash
|
||||
id: git_short_hash
|
||||
run: echo "::set-output name=result::$(git rev-parse --short "${{ github.sha }}")"
|
||||
- name: Clear
|
||||
run: dotnet clean && dotnet nuget locals all --clear
|
||||
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
- 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
|
||||
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
|
||||
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 true
|
||||
if: github.event_name == 'pull_request'
|
||||
- name: Publish Ryujinx.Headless.SDL2
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless /p:Version="${{ env.RYUJINX_BASE_VERSION }}" /p:DebugType=embedded /p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" /p:ExtraDefineConstants=DISABLE_UPDATER Ryujinx.Headless.SDL2 --self-contained
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER Ryujinx.Headless.SDL2 --self-contained true
|
||||
if: github.event_name == 'pull_request'
|
||||
- name: Publish Ryujinx.Ava
|
||||
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
|
||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER Ryujinx.Ava --self-contained true
|
||||
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});
|
||||
}
|
||||
|
26
.github/workflows/release.yml
vendored
26
.github/workflows/release.yml
vendored
@ -25,19 +25,15 @@ 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
|
||||
uses: fabriciomurta/ensure-nuget-source@v1
|
||||
- name: Clear
|
||||
run: dotnet clean && dotnet nuget locals all --clear
|
||||
dotnet-version: 7.0.x
|
||||
- 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: |
|
||||
@ -51,9 +47,9 @@ jobs:
|
||||
run: "mkdir release_output"
|
||||
- name: Publish Windows
|
||||
run: |
|
||||
dotnet publish -c Release -r win10-x64 -o ./publish_windows/publish /p:Version="${{ steps.version_info.outputs.build_version }}" /p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" /p:DebugType=embedded Ryujinx --self-contained
|
||||
dotnet publish -c Release -r win10-x64 -o ./publish_windows_sdl2_headless/publish /p:Version="${{ steps.version_info.outputs.build_version }}" /p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" /p:DebugType=embedded Ryujinx.Headless.SDL2 --self-contained
|
||||
dotnet publish -c Release -r win10-x64 -o ./publish_windows_ava/publish /p:Version="${{ steps.version_info.outputs.build_version }}" /p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" /p:DebugType=embedded Ryujinx.Ava --self-contained
|
||||
dotnet publish -c Release -r win10-x64 -o ./publish_windows/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx --self-contained true
|
||||
dotnet publish -c Release -r win10-x64 -o ./publish_windows_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx.Headless.SDL2 --self-contained true
|
||||
dotnet publish -c Release -r win10-x64 -o ./publish_windows_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx.Ava --self-contained true
|
||||
- name: Packing Windows builds
|
||||
run: |
|
||||
pushd publish_windows
|
||||
@ -71,9 +67,9 @@ jobs:
|
||||
|
||||
- name: Publish Linux
|
||||
run: |
|
||||
dotnet publish -c Release -r linux-x64 -o ./publish_linux/publish /p:Version="${{ steps.version_info.outputs.build_version }}" /p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" /p:DebugType=embedded Ryujinx --self-contained
|
||||
dotnet publish -c Release -r linux-x64 -o ./publish_linux_sdl2_headless/publish /p:Version="${{ steps.version_info.outputs.build_version }}" /p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" /p:DebugType=embedded Ryujinx.Headless.SDL2 --self-contained
|
||||
dotnet publish -c Release -r linux-x64 -o ./publish_linux_ava/publish /p:Version="${{ steps.version_info.outputs.build_version }}" /p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" /p:DebugType=embedded Ryujinx.Ava --self-contained
|
||||
dotnet publish -c Release -r linux-x64 -o ./publish_linux/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx --self-contained true
|
||||
dotnet publish -c Release -r linux-x64 -o ./publish_linux_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx.Headless.SDL2 --self-contained true
|
||||
dotnet publish -c Release -r linux-x64 -o ./publish_linux_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded Ryujinx.Ava --self-contained true
|
||||
|
||||
- name: Packing Linux builds
|
||||
run: |
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
{
|
||||
struct AllocationResult
|
||||
readonly struct AllocationResult
|
||||
{
|
||||
public int IntUsedRegisters { get; }
|
||||
public int VecUsedRegisters { get; }
|
||||
|
@ -11,7 +11,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
{
|
||||
private class ParallelCopy
|
||||
{
|
||||
private struct Copy
|
||||
private readonly struct Copy
|
||||
{
|
||||
public Register Dest { get; }
|
||||
public Register Source { get; }
|
||||
|
@ -11,7 +11,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
{
|
||||
class HybridAllocator : IRegisterAllocator
|
||||
{
|
||||
private struct BlockInfo
|
||||
private readonly struct BlockInfo
|
||||
{
|
||||
public bool HasCall { get; }
|
||||
|
||||
|
@ -3,7 +3,7 @@ using System;
|
||||
|
||||
namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
{
|
||||
struct RegisterMasks
|
||||
readonly struct RegisterMasks
|
||||
{
|
||||
public int IntAvailableRegisters { get; }
|
||||
public int VecAvailableRegisters { get; }
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
struct IntrinsicInfo
|
||||
readonly struct IntrinsicInfo
|
||||
{
|
||||
public X86Instruction Inst { get; }
|
||||
public IntrinsicType Type { get; }
|
||||
|
@ -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,
|
||||
|
@ -1,15 +1,11 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace ARMeilleure.Common
|
||||
{
|
||||
static class BitUtils
|
||||
{
|
||||
private static readonly sbyte[] HbsNibbleLut;
|
||||
|
||||
static BitUtils()
|
||||
{
|
||||
HbsNibbleLut = new sbyte[] { -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 };
|
||||
}
|
||||
private static ReadOnlySpan<sbyte> HbsNibbleLut => new sbyte[] { -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 };
|
||||
|
||||
public static long FillWithOnes(int bits)
|
||||
{
|
||||
|
@ -2,7 +2,7 @@ using ARMeilleure.Instructions;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
struct InstDescriptor
|
||||
readonly struct InstDescriptor
|
||||
{
|
||||
public static InstDescriptor Undefined => new InstDescriptor(InstName.Und, InstEmit.Und);
|
||||
|
||||
|
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ namespace ARMeilleure.Decoders
|
||||
|
||||
private const int FastLookupSize = 0x1000;
|
||||
|
||||
private struct InstInfo
|
||||
private readonly struct InstInfo
|
||||
{
|
||||
public int Mask { get; }
|
||||
public int Value { get; }
|
||||
@ -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);
|
||||
|
@ -6,7 +6,7 @@ namespace ARMeilleure.Diagnostics
|
||||
{
|
||||
static class Symbols
|
||||
{
|
||||
private struct RangedSymbol
|
||||
private readonly struct RangedSymbol
|
||||
{
|
||||
public readonly ulong Start;
|
||||
public readonly ulong End;
|
||||
|
@ -25,13 +25,13 @@ namespace ARMeilleure.Diagnostics
|
||||
_funcTabSizeCounter = new PollingCounter("addr-tab-alloc", this, () => _funcTabSize / 1024d / 1024d)
|
||||
{
|
||||
DisplayName = "AddressTable Total Bytes Allocated",
|
||||
DisplayUnits = "MB"
|
||||
DisplayUnits = "MiB"
|
||||
};
|
||||
|
||||
_funcTabLeafSizeCounter = new PollingCounter("addr-tab-leaf-alloc", this, () => _funcTabLeafSize / 1024d / 1024d)
|
||||
{
|
||||
DisplayName = "AddressTable Total Leaf Bytes Allocated",
|
||||
DisplayUnits = "MB"
|
||||
DisplayUnits = "MiB"
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -726,7 +726,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||
{
|
||||
return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNum)), op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMaxNum), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -774,7 +774,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||
{
|
||||
return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMax)), op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMax), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -900,7 +900,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||
{
|
||||
return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNum)), op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMinNum), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -948,7 +948,7 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||
{
|
||||
return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMin)), op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMin), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1617,53 +1617,47 @@ 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)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
if (op.Size == 0)
|
||||
{
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
||||
}
|
||||
else /* if (op.Size == 1) */
|
||||
{
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
||||
}
|
||||
return EmitRoundByRMode(context, op1);
|
||||
});
|
||||
}
|
||||
|
||||
public static void Frinti_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
int sizeF = op.Size & 1;
|
||||
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
if (sizeF == 0)
|
||||
{
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
||||
}
|
||||
else /* if (sizeF == 1) */
|
||||
{
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
||||
}
|
||||
return EmitRoundByRMode(context, op1);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1759,37 +1753,17 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Frintx_S(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
if (op.Size == 0)
|
||||
{
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
||||
}
|
||||
else /* if (op.Size == 1) */
|
||||
{
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
||||
}
|
||||
return EmitRoundByRMode(context, op1);
|
||||
});
|
||||
}
|
||||
|
||||
public static void Frintx_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
int sizeF = op.Size & 1;
|
||||
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
if (sizeF == 0)
|
||||
{
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
||||
}
|
||||
else /* if (sizeF == 1) */
|
||||
{
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
||||
}
|
||||
return EmitRoundByRMode(context, op1);
|
||||
});
|
||||
}
|
||||
|
||||
@ -3556,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)
|
||||
{
|
||||
@ -3578,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)
|
||||
{
|
||||
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
@ -178,37 +177,20 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
private static void EmitCmpOpF32(ArmEmitterContext context, string name, bool zero)
|
||||
{
|
||||
Operand one = Const(1);
|
||||
if (zero)
|
||||
{
|
||||
EmitVectorUnaryOpF32(context, (m) =>
|
||||
{
|
||||
OperandType type = m.Type;
|
||||
Operand zeroOp = m.Type == OperandType.FP64 ? ConstF(0.0d) : ConstF(0.0f);
|
||||
|
||||
if (type == OperandType.FP64)
|
||||
{
|
||||
return context.Call(typeof(SoftFloat64).GetMethod(name), m, ConstF(0.0d), one);
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.Call(typeof(SoftFloat32).GetMethod(name), m, ConstF(0.0f), one);
|
||||
}
|
||||
return EmitSoftFloatCallDefaultFpscr(context, name, m, zeroOp);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitVectorBinaryOpF32(context, (n, m) =>
|
||||
{
|
||||
OperandType type = n.Type;
|
||||
|
||||
if (type == OperandType.FP64)
|
||||
{
|
||||
return context.Call(typeof(SoftFloat64).GetMethod(name), n, m, one);
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.Call(typeof(SoftFloat32).GetMethod(name), n, m, one);
|
||||
}
|
||||
return EmitSoftFloatCallDefaultFpscr(context, name, n, m);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -357,11 +339,7 @@ namespace ARMeilleure.Instructions
|
||||
me = ExtractScalar(context, type, op.Vm);
|
||||
}
|
||||
|
||||
MethodInfo info = sizeF != 0
|
||||
? typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompare))
|
||||
: typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompare));
|
||||
|
||||
Operand nzcv = context.Call(info, ne, me, Const(signalNaNs));
|
||||
Operand nzcv = EmitSoftFloatCall(context, nameof(SoftFloat32.FPCompare), ne, me, Const(signalNaNs));
|
||||
|
||||
EmitSetFpscrNzcv(context, nzcv);
|
||||
}
|
||||
|
@ -76,7 +76,9 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
Operand ne = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), 0);
|
||||
|
||||
context.StoreToContext();
|
||||
Operand res = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
|
||||
context.LoadFromContext();
|
||||
|
||||
res = context.ZeroExtend16(OperandType.I64, res);
|
||||
|
||||
@ -98,7 +100,9 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1);
|
||||
|
||||
context.StoreToContext();
|
||||
Operand res = context.Call(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)), ne);
|
||||
context.LoadFromContext();
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||
}
|
||||
@ -120,7 +124,9 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
Operand ne = context.VectorExtract(OperandType.FP64, GetVec(op.Rn), 0);
|
||||
|
||||
context.StoreToContext();
|
||||
Operand res = context.Call(typeof(SoftFloat64_16).GetMethod(nameof(SoftFloat64_16.FPConvert)), ne);
|
||||
context.LoadFromContext();
|
||||
|
||||
res = context.ZeroExtend16(OperandType.I64, res);
|
||||
|
||||
@ -143,7 +149,9 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1);
|
||||
|
||||
context.StoreToContext();
|
||||
Operand res = context.Call(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)), ne);
|
||||
context.LoadFromContext();
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||
}
|
||||
@ -156,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)
|
||||
@ -224,7 +274,9 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
Operand ne = EmitVectorExtractZx(context, op.Rn, part + index, 1);
|
||||
|
||||
context.StoreToContext();
|
||||
Operand e = context.Call(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)), ne);
|
||||
context.LoadFromContext();
|
||||
|
||||
res = context.VectorInsert(res, e, index);
|
||||
}
|
||||
@ -333,7 +385,9 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
if (sizeF == 0)
|
||||
{
|
||||
context.StoreToContext();
|
||||
Operand e = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
|
||||
context.LoadFromContext();
|
||||
|
||||
e = context.ZeroExtend16(OperandType.I64, e);
|
||||
|
||||
@ -1211,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);
|
||||
|
||||
@ -1253,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);
|
||||
|
||||
@ -1302,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();
|
||||
|
||||
@ -1357,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();
|
||||
|
||||
@ -1412,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)
|
||||
@ -1452,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)
|
||||
@ -1500,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();
|
||||
|
||||
@ -1555,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();
|
||||
|
||||
|
@ -161,34 +161,15 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
Operand toConvert = ExtractScalar(context, floatSize, op.Vm);
|
||||
|
||||
Operand asInteger;
|
||||
|
||||
// TODO: Fast Path.
|
||||
if (roundWithFpscr)
|
||||
{
|
||||
MethodInfo info;
|
||||
|
||||
if (floatSize == OperandType.FP64)
|
||||
{
|
||||
info = unsigned
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToUInt32))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToInt32));
|
||||
}
|
||||
else
|
||||
{
|
||||
info = unsigned
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToUInt32))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToInt32));
|
||||
}
|
||||
|
||||
asInteger = context.Call(info, toConvert);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Round towards zero.
|
||||
asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
|
||||
toConvert = EmitRoundByRMode(context, toConvert);
|
||||
}
|
||||
|
||||
// Round towards zero.
|
||||
Operand asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
|
||||
|
||||
InsertScalar(context, op.Vd, asInteger);
|
||||
}
|
||||
}
|
||||
@ -222,6 +203,9 @@ namespace ARMeilleure.Instructions
|
||||
FPRoundingMode roundMode;
|
||||
switch (rm)
|
||||
{
|
||||
case 0b00:
|
||||
roundMode = FPRoundingMode.ToNearestAway;
|
||||
break;
|
||||
case 0b01:
|
||||
roundMode = FPRoundingMode.ToNearest;
|
||||
break;
|
||||
@ -247,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);
|
||||
}
|
||||
@ -271,14 +255,80 @@ namespace ARMeilleure.Instructions
|
||||
break;
|
||||
}
|
||||
|
||||
Operand asInteger;
|
||||
|
||||
asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
|
||||
Operand asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
|
||||
|
||||
InsertScalar(context, op.Vd, asInteger);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -288,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
|
||||
@ -326,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).
|
||||
@ -399,15 +465,9 @@ namespace ARMeilleure.Instructions
|
||||
// VRINTX (floating-point).
|
||||
public static void Vrintx_S(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
|
||||
|
||||
bool doubleSize = (op.Size & 1) == 1;
|
||||
string methodName = doubleSize ? nameof(SoftFallback.Round) : nameof(SoftFallback.RoundF);
|
||||
|
||||
EmitScalarUnaryOpF32(context, (op1) =>
|
||||
{
|
||||
MethodInfo info = typeof(SoftFallback).GetMethod(methodName);
|
||||
return context.Call(info, op1);
|
||||
return EmitRoundByRMode(context, op1);
|
||||
});
|
||||
}
|
||||
|
||||
@ -440,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();
|
||||
|
||||
@ -491,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);
|
||||
@ -361,6 +409,54 @@ namespace ARMeilleure.Instructions
|
||||
return context.Call(info, n, Const((int)roundMode));
|
||||
}
|
||||
|
||||
public static Operand EmitGetRoundingMode(ArmEmitterContext context)
|
||||
{
|
||||
Operand rMode = context.ShiftLeft(GetFpFlag(FPState.RMode1Flag), Const(1));
|
||||
rMode = context.BitwiseOr(rMode, GetFpFlag(FPState.RMode0Flag));
|
||||
|
||||
return rMode;
|
||||
}
|
||||
|
||||
public static Operand EmitRoundByRMode(ArmEmitterContext context, Operand op)
|
||||
{
|
||||
Debug.Assert(op.Type == OperandType.FP32 || op.Type == OperandType.FP64);
|
||||
|
||||
Operand lbl1 = Label();
|
||||
Operand lbl2 = Label();
|
||||
Operand lbl3 = Label();
|
||||
Operand lblEnd = Label();
|
||||
|
||||
Operand rN = Const((int)FPRoundingMode.ToNearest);
|
||||
Operand rP = Const((int)FPRoundingMode.TowardsPlusInfinity);
|
||||
Operand rM = Const((int)FPRoundingMode.TowardsMinusInfinity);
|
||||
|
||||
Operand res = context.AllocateLocal(op.Type);
|
||||
|
||||
Operand rMode = EmitGetRoundingMode(context);
|
||||
|
||||
context.BranchIf(lbl1, rMode, rN, Comparison.NotEqual);
|
||||
context.Copy(res, EmitRoundMathCall(context, MidpointRounding.ToEven, op));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lbl1);
|
||||
context.BranchIf(lbl2, rMode, rP, Comparison.NotEqual);
|
||||
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Ceiling), op));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lbl2);
|
||||
context.BranchIf(lbl3, rMode, rM, Comparison.NotEqual);
|
||||
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Floor), op));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lbl3);
|
||||
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Truncate), op));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static Operand EmitSoftFloatCall(ArmEmitterContext context, string name, params Operand[] callArgs)
|
||||
{
|
||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||
@ -369,7 +465,11 @@ namespace ARMeilleure.Instructions
|
||||
? typeof(SoftFloat32).GetMethod(name)
|
||||
: typeof(SoftFloat64).GetMethod(name);
|
||||
|
||||
return context.Call(info, callArgs);
|
||||
context.StoreToContext();
|
||||
Operand res = context.Call(info, callArgs);
|
||||
context.LoadFromContext();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static void EmitScalarBinaryOpByElemF(ArmEmitterContext context, Func2I emit)
|
||||
@ -1269,7 +1369,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void EmitSseOrAvxEnterFtzAndDazModesOpF(ArmEmitterContext context, out Operand isTrue)
|
||||
{
|
||||
isTrue = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)));
|
||||
isTrue = GetFpFlag(FPState.FzFlag);
|
||||
|
||||
Operand lblTrue = Label();
|
||||
context.BranchIfFalse(lblTrue, isTrue);
|
||||
@ -1281,9 +1381,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void EmitSseOrAvxExitFtzAndDazModesOpF(ArmEmitterContext context, Operand isTrue = default)
|
||||
{
|
||||
isTrue = isTrue == default
|
||||
? context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)))
|
||||
: isTrue;
|
||||
isTrue = isTrue == default ? GetFpFlag(FPState.FzFlag) : isTrue;
|
||||
|
||||
Operand lblTrue = Label();
|
||||
context.BranchIfFalse(lblTrue, isTrue);
|
||||
@ -1552,13 +1650,13 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.BranchIf(lbl1, op, zeroL, Comparison.LessOrEqual);
|
||||
context.Copy(res, maxT);
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lbl1);
|
||||
context.BranchIf(lblEnd, op, zeroL, Comparison.GreaterOrEqual);
|
||||
context.Copy(res, minT);
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
@ -1583,7 +1681,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.BranchIf(lblEnd, op, zeroUL, Comparison.LessOrEqualUI);
|
||||
context.Copy(res, maxT);
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
@ -1610,13 +1708,13 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.BranchIf(lbl1, op, maxT, Comparison.LessOrEqual);
|
||||
context.Copy(res, maxT);
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lbl1);
|
||||
context.BranchIf(lblEnd, op, minT, Comparison.GreaterOrEqual);
|
||||
context.Copy(res, minT);
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
@ -1641,7 +1739,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.BranchIf(lblEnd, op, maxT, Comparison.LessOrEqualUI);
|
||||
context.Copy(res, maxT);
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
@ -1663,7 +1761,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.BranchIf(lblEnd, op, minL, Comparison.NotEqual);
|
||||
context.Copy(res, maxL);
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
@ -1691,7 +1789,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
|
||||
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
@ -1713,7 +1811,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
|
||||
context.Copy(res, maxUL);
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
@ -1741,7 +1839,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
|
||||
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
@ -1763,7 +1861,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.BranchIf(lblEnd, op1, op2, Comparison.GreaterOrEqualUI);
|
||||
context.Copy(res, zeroL);
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
@ -1790,19 +1888,19 @@ namespace ARMeilleure.Instructions
|
||||
Operand notOp2AndRes = context.BitwiseAnd(context.BitwiseNot(op2), add);
|
||||
context.BranchIf(lblEnd, notOp2AndRes, zeroL, Comparison.GreaterOrEqual);
|
||||
context.Copy(res, maxL);
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lbl1);
|
||||
context.BranchIf(lbl2, op2, zeroL, Comparison.Less);
|
||||
context.Copy(res, maxL);
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lbl2);
|
||||
context.BranchIf(lblEnd, add, maxL, Comparison.LessOrEqualUI);
|
||||
context.Copy(res, maxL);
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
@ -1828,14 +1926,14 @@ namespace ARMeilleure.Instructions
|
||||
context.BranchIf(lbl1, op1, zeroL, Comparison.Less);
|
||||
context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
|
||||
context.Copy(res, maxUL);
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lbl1);
|
||||
context.BranchIf(lblEnd, op2, maxL, Comparison.GreaterUI);
|
||||
context.BranchIf(lblEnd, add, zeroL, Comparison.GreaterOrEqual);
|
||||
context.Copy(res, zeroL);
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
context.Branch(lblEnd);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
|
@ -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);
|
||||
@ -1181,7 +1197,11 @@ namespace ARMeilleure.Instructions
|
||||
Array.Resize(ref callArgs, callArgs.Length + 1);
|
||||
callArgs[callArgs.Length - 1] = Const(1);
|
||||
|
||||
return context.Call(info, callArgs);
|
||||
context.StoreToContext();
|
||||
Operand res = context.Call(info, callArgs);
|
||||
context.LoadFromContext();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static Operand EmitVectorExtractSx32(ArmEmitterContext context, int reg, int index, int size)
|
||||
|
@ -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);
|
||||
|
@ -1,5 +1,6 @@
|
||||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
@ -378,7 +379,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
context.BranchIfFalse(lblNoSat, context.BitwiseOr(gt, lt));
|
||||
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||
|
||||
context.MarkLabel(lblNoSat);
|
||||
|
||||
|
@ -31,8 +31,8 @@ namespace ARMeilleure.Instructions
|
||||
case 0b11_011_0000_0000_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)); break;
|
||||
case 0b11_011_0000_0000_111: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)); break;
|
||||
case 0b11_011_0100_0010_000: EmitGetNzcv(context); return;
|
||||
case 0b11_011_0100_0100_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcr)); break;
|
||||
case 0b11_011_0100_0100_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpsr)); break;
|
||||
case 0b11_011_0100_0100_000: EmitGetFpcr(context); return;
|
||||
case 0b11_011_0100_0100_001: EmitGetFpsr(context); return;
|
||||
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl0)); break;
|
||||
case 0b11_011_1101_0000_011: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)); break;
|
||||
case 0b11_011_1110_0000_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)); break;
|
||||
@ -53,9 +53,9 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
switch (GetPackedId(op))
|
||||
{
|
||||
case 0b11_011_0100_0010_000: EmitSetNzcv(context); return;
|
||||
case 0b11_011_0100_0100_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpcr)); break;
|
||||
case 0b11_011_0100_0100_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsr)); break;
|
||||
case 0b11_011_0100_0010_000: EmitSetNzcv(context); return;
|
||||
case 0b11_011_0100_0100_000: EmitSetFpcr(context); return;
|
||||
case 0b11_011_0100_0100_001: EmitSetFpsr(context); return;
|
||||
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)); break;
|
||||
|
||||
default: throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
@ -121,39 +121,91 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
Operand vSh = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
|
||||
Operand cSh = context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag));
|
||||
Operand zSh = context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag));
|
||||
Operand nSh = context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag));
|
||||
Operand nzcv = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
|
||||
nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag)));
|
||||
nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag)));
|
||||
nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag)));
|
||||
|
||||
Operand nzcvSh = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
|
||||
SetIntOrZR(context, op.Rt, nzcv);
|
||||
}
|
||||
|
||||
SetIntOrZR(context, op.Rt, nzcvSh);
|
||||
private static void EmitGetFpcr(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
Operand fpcr = Const(0);
|
||||
|
||||
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||
{
|
||||
if (FPCR.Mask.HasFlag((FPCR)(1u << flag)))
|
||||
{
|
||||
fpcr = context.BitwiseOr(fpcr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
|
||||
}
|
||||
}
|
||||
|
||||
SetIntOrZR(context, op.Rt, fpcr);
|
||||
}
|
||||
|
||||
private static void EmitGetFpsr(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
Operand fpsr = Const(0);
|
||||
|
||||
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||
{
|
||||
if (FPSR.Mask.HasFlag((FPSR)(1u << flag)))
|
||||
{
|
||||
fpsr = context.BitwiseOr(fpsr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
|
||||
}
|
||||
}
|
||||
|
||||
SetIntOrZR(context, op.Rt, fpsr);
|
||||
}
|
||||
|
||||
private static void EmitSetNzcv(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
Operand t = GetIntOrZR(context, op.Rt);
|
||||
t = context.ConvertI64ToI32(t);
|
||||
Operand nzcv = GetIntOrZR(context, op.Rt);
|
||||
nzcv = context.ConvertI64ToI32(nzcv);
|
||||
|
||||
Operand v = context.ShiftRightUI(t, Const((int)PState.VFlag));
|
||||
v = context.BitwiseAnd (v, Const(1));
|
||||
SetFlag(context, PState.VFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.VFlag)), Const(1)));
|
||||
SetFlag(context, PState.CFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.CFlag)), Const(1)));
|
||||
SetFlag(context, PState.ZFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.ZFlag)), Const(1)));
|
||||
SetFlag(context, PState.NFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.NFlag)), Const(1)));
|
||||
}
|
||||
|
||||
Operand c = context.ShiftRightUI(t, Const((int)PState.CFlag));
|
||||
c = context.BitwiseAnd (c, Const(1));
|
||||
private static void EmitSetFpcr(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
Operand z = context.ShiftRightUI(t, Const((int)PState.ZFlag));
|
||||
z = context.BitwiseAnd (z, Const(1));
|
||||
Operand fpcr = GetIntOrZR(context, op.Rt);
|
||||
fpcr = context.ConvertI64ToI32(fpcr);
|
||||
|
||||
Operand n = context.ShiftRightUI(t, Const((int)PState.NFlag));
|
||||
n = context.BitwiseAnd (n, Const(1));
|
||||
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||
{
|
||||
if (FPCR.Mask.HasFlag((FPCR)(1u << flag)))
|
||||
{
|
||||
SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpcr, Const(flag)), Const(1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetFlag(context, PState.VFlag, v);
|
||||
SetFlag(context, PState.CFlag, c);
|
||||
SetFlag(context, PState.ZFlag, z);
|
||||
SetFlag(context, PState.NFlag, n);
|
||||
private static void EmitSetFpsr(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
Operand fpsr = GetIntOrZR(context, op.Rt);
|
||||
fpsr = context.ConvertI64ToI32(fpsr);
|
||||
|
||||
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||
{
|
||||
if (FPSR.Mask.HasFlag((FPSR)(1u << flag)))
|
||||
{
|
||||
SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpsr, Const(flag)), Const(1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -169,14 +169,11 @@ namespace ARMeilleure.Instructions
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand vSh = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
|
||||
Operand cSh = context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag));
|
||||
Operand zSh = context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag));
|
||||
Operand nSh = context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag));
|
||||
Operand qSh = context.ShiftLeft(GetFlag(PState.QFlag), Const((int)PState.QFlag));
|
||||
|
||||
Operand spsr = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
|
||||
spsr = context.BitwiseOr(spsr, qSh);
|
||||
Operand spsr = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
|
||||
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag)));
|
||||
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag)));
|
||||
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag)));
|
||||
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.QFlag), Const((int)PState.QFlag)));
|
||||
|
||||
// TODO: Remaining flags.
|
||||
|
||||
@ -200,8 +197,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
EmitSetNzcv(context, value);
|
||||
|
||||
Operand q = context.ShiftRightUI(value, Const((int)PState.QFlag));
|
||||
q = context.BitwiseAnd(q, Const(1));
|
||||
Operand q = context.BitwiseAnd(context.ShiftRightUI(value, Const((int)PState.QFlag)), Const(1));
|
||||
|
||||
SetFlag(context, PState.QFlag, q);
|
||||
}
|
||||
@ -284,17 +280,10 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
private static void EmitSetNzcv(ArmEmitterContext context, Operand t)
|
||||
{
|
||||
Operand v = context.ShiftRightUI(t, Const((int)PState.VFlag));
|
||||
v = context.BitwiseAnd(v, Const(1));
|
||||
|
||||
Operand c = context.ShiftRightUI(t, Const((int)PState.CFlag));
|
||||
c = context.BitwiseAnd(c, Const(1));
|
||||
|
||||
Operand z = context.ShiftRightUI(t, Const((int)PState.ZFlag));
|
||||
z = context.BitwiseAnd(z, Const(1));
|
||||
|
||||
Operand n = context.ShiftRightUI(t, Const((int)PState.NFlag));
|
||||
n = context.BitwiseAnd(n, Const(1));
|
||||
Operand v = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.VFlag)), Const(1));
|
||||
Operand c = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.CFlag)), Const(1));
|
||||
Operand z = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.ZFlag)), Const(1));
|
||||
Operand n = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.NFlag)), Const(1));
|
||||
|
||||
SetFlag(context, PState.VFlag, v);
|
||||
SetFlag(context, PState.CFlag, c);
|
||||
@ -306,42 +295,32 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
|
||||
|
||||
Operand vSh = context.ShiftLeft(GetFpFlag(FPState.VFlag), Const((int)FPState.VFlag));
|
||||
Operand cSh = context.ShiftLeft(GetFpFlag(FPState.CFlag), Const((int)FPState.CFlag));
|
||||
Operand zSh = context.ShiftLeft(GetFpFlag(FPState.ZFlag), Const((int)FPState.ZFlag));
|
||||
Operand nSh = context.ShiftLeft(GetFpFlag(FPState.NFlag), Const((int)FPState.NFlag));
|
||||
Operand fpscr = Const(0);
|
||||
|
||||
Operand nzcvSh = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
|
||||
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||
{
|
||||
if (FPSCR.Mask.HasFlag((FPSCR)(1u << flag)))
|
||||
{
|
||||
fpscr = context.BitwiseOr(fpscr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
|
||||
}
|
||||
}
|
||||
|
||||
Operand fpscr = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpscr)));
|
||||
|
||||
SetIntA32(context, op.Rt, context.BitwiseOr(nzcvSh, fpscr));
|
||||
SetIntA32(context, op.Rt, fpscr);
|
||||
}
|
||||
|
||||
private static void EmitSetFpscr(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
|
||||
|
||||
Operand t = GetIntA32(context, op.Rt);
|
||||
Operand fpscr = GetIntA32(context, op.Rt);
|
||||
|
||||
Operand v = context.ShiftRightUI(t, Const((int)FPState.VFlag));
|
||||
v = context.BitwiseAnd(v, Const(1));
|
||||
|
||||
Operand c = context.ShiftRightUI(t, Const((int)FPState.CFlag));
|
||||
c = context.BitwiseAnd(c, Const(1));
|
||||
|
||||
Operand z = context.ShiftRightUI(t, Const((int)FPState.ZFlag));
|
||||
z = context.BitwiseAnd(z, Const(1));
|
||||
|
||||
Operand n = context.ShiftRightUI(t, Const((int)FPState.NFlag));
|
||||
n = context.BitwiseAnd(n, Const(1));
|
||||
|
||||
SetFpFlag(context, FPState.VFlag, v);
|
||||
SetFpFlag(context, FPState.CFlag, c);
|
||||
SetFpFlag(context, FPState.ZFlag, z);
|
||||
SetFpFlag(context, FPState.NFlag, n);
|
||||
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr)), t);
|
||||
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||
{
|
||||
if (FPSCR.Mask.HasFlag((FPSCR)(1u << flag)))
|
||||
{
|
||||
SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpscr, Const(flag)), Const(1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,29 +72,6 @@ namespace ARMeilleure.Instructions
|
||||
return (ulong)GetContext().DczidEl0;
|
||||
}
|
||||
|
||||
public static ulong GetFpcr()
|
||||
{
|
||||
return (ulong)GetContext().Fpcr;
|
||||
}
|
||||
|
||||
public static bool GetFpcrFz()
|
||||
{
|
||||
return (GetContext().Fpcr & FPCR.Fz) != 0;
|
||||
}
|
||||
|
||||
public static ulong GetFpsr()
|
||||
{
|
||||
return (ulong)GetContext().Fpsr;
|
||||
}
|
||||
|
||||
public static uint GetFpscr()
|
||||
{
|
||||
ExecutionContext context = GetContext();
|
||||
|
||||
return (uint)(context.Fpsr & FPSR.A32Mask & ~FPSR.Nzcv) |
|
||||
(uint)(context.Fpcr & FPCR.A32Mask);
|
||||
}
|
||||
|
||||
public static ulong GetTpidrEl0()
|
||||
{
|
||||
return (ulong)GetContext().TpidrEl0;
|
||||
@ -130,29 +107,6 @@ namespace ARMeilleure.Instructions
|
||||
return GetContext().CntvctEl0;
|
||||
}
|
||||
|
||||
public static void SetFpcr(ulong value)
|
||||
{
|
||||
GetContext().Fpcr = (FPCR)value;
|
||||
}
|
||||
|
||||
public static void SetFpsr(ulong value)
|
||||
{
|
||||
GetContext().Fpsr = (FPSR)value;
|
||||
}
|
||||
|
||||
public static void SetFpsrQc()
|
||||
{
|
||||
GetContext().Fpsr |= FPSR.Qc;
|
||||
}
|
||||
|
||||
public static void SetFpscr(uint fpscr)
|
||||
{
|
||||
ExecutionContext context = GetContext();
|
||||
|
||||
context.Fpsr = FPSR.A32Mask & (FPSR)fpscr;
|
||||
context.Fpcr = FPCR.A32Mask & (FPCR)fpscr;
|
||||
}
|
||||
|
||||
public static void SetTpidrEl0(ulong value)
|
||||
{
|
||||
GetContext().TpidrEl0 = (long)value;
|
||||
|
@ -91,76 +91,6 @@ namespace ARMeilleure.Instructions
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region "Rounding"
|
||||
public static double Round(double value)
|
||||
{
|
||||
ExecutionContext context = NativeInterface.GetContext();
|
||||
|
||||
FPRoundingMode roundMode = context.Fpcr.GetRoundingMode();
|
||||
|
||||
if (roundMode == FPRoundingMode.ToNearest)
|
||||
{
|
||||
return Math.Round(value); // even
|
||||
}
|
||||
else if (roundMode == FPRoundingMode.TowardsPlusInfinity)
|
||||
{
|
||||
return Math.Ceiling(value);
|
||||
}
|
||||
else if (roundMode == FPRoundingMode.TowardsMinusInfinity)
|
||||
{
|
||||
return Math.Floor(value);
|
||||
}
|
||||
else /* if (roundMode == FPRoundingMode.TowardsZero) */
|
||||
{
|
||||
return Math.Truncate(value);
|
||||
}
|
||||
}
|
||||
|
||||
public static float RoundF(float value)
|
||||
{
|
||||
ExecutionContext context = NativeInterface.GetContext();
|
||||
|
||||
FPRoundingMode roundMode = context.Fpcr.GetRoundingMode();
|
||||
|
||||
if (roundMode == FPRoundingMode.ToNearest)
|
||||
{
|
||||
return MathF.Round(value); // even
|
||||
}
|
||||
else if (roundMode == FPRoundingMode.TowardsPlusInfinity)
|
||||
{
|
||||
return MathF.Ceiling(value);
|
||||
}
|
||||
else if (roundMode == FPRoundingMode.TowardsMinusInfinity)
|
||||
{
|
||||
return MathF.Floor(value);
|
||||
}
|
||||
else /* if (roundMode == FPRoundingMode.TowardsZero) */
|
||||
{
|
||||
return MathF.Truncate(value);
|
||||
}
|
||||
}
|
||||
|
||||
public static int FloatToInt32(float value)
|
||||
{
|
||||
return SatF32ToS32(RoundF(value));
|
||||
}
|
||||
|
||||
public static int DoubleToInt32(double value)
|
||||
{
|
||||
return SatF64ToS32(Round(value));
|
||||
}
|
||||
|
||||
public static uint FloatToUInt32(float value)
|
||||
{
|
||||
return SatF32ToU32(RoundF(value));
|
||||
}
|
||||
|
||||
public static uint DoubleToUInt32(double value)
|
||||
{
|
||||
return SatF64ToU32(Round(value));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region "Saturation"
|
||||
public static int SatF32ToS32(float value)
|
||||
{
|
||||
|
@ -12,8 +12,8 @@ namespace ARMeilleure.Instructions
|
||||
RecipSqrtEstimateTable = BuildRecipSqrtEstimateTable();
|
||||
}
|
||||
|
||||
internal static readonly byte[] RecipEstimateTable;
|
||||
internal static readonly byte[] RecipSqrtEstimateTable;
|
||||
public static readonly byte[] RecipEstimateTable;
|
||||
public static readonly byte[] RecipSqrtEstimateTable;
|
||||
|
||||
private static byte[] BuildRecipEstimateTable()
|
||||
{
|
||||
@ -94,6 +94,13 @@ namespace ARMeilleure.Instructions
|
||||
context.Fpsr |= (FPSR)(1 << (int)exc);
|
||||
}
|
||||
}
|
||||
|
||||
public static FPRoundingMode GetRoundingMode(this FPCR fpcr)
|
||||
{
|
||||
const int RModeShift = 22;
|
||||
|
||||
return (FPRoundingMode)(((uint)fpcr >> RModeShift) & 3u);
|
||||
}
|
||||
}
|
||||
|
||||
static class SoftFloat16
|
||||
|
@ -47,6 +47,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
X86Divps,
|
||||
X86Divsd,
|
||||
X86Divss,
|
||||
X86Gf2p8affineqb,
|
||||
X86Haddpd,
|
||||
X86Haddps,
|
||||
X86Insertps,
|
||||
|
@ -3,7 +3,7 @@ using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
namespace ARMeilleure.IntermediateRepresentation
|
||||
{
|
||||
struct PhiOperation
|
||||
readonly struct PhiOperation
|
||||
{
|
||||
private readonly Operation _operation;
|
||||
|
||||
|
@ -2,7 +2,7 @@ using System;
|
||||
|
||||
namespace ARMeilleure.IntermediateRepresentation
|
||||
{
|
||||
struct Register : IEquatable<Register>
|
||||
readonly struct Register : IEquatable<Register>
|
||||
{
|
||||
public int Index { get; }
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -36,10 +36,25 @@ namespace ARMeilleure.State
|
||||
set => _nativeContext.SetPstate(value);
|
||||
}
|
||||
|
||||
public FPCR Fpcr { get; set; }
|
||||
public FPSR Fpsr { get; set; }
|
||||
public FPSR Fpsr
|
||||
{
|
||||
get => (FPSR)_nativeContext.GetFPState((uint)FPSR.Mask);
|
||||
set => _nativeContext.SetFPState((uint)value, (uint)FPSR.Mask);
|
||||
}
|
||||
|
||||
public FPCR Fpcr
|
||||
{
|
||||
get => (FPCR)_nativeContext.GetFPState((uint)FPCR.Mask);
|
||||
set => _nativeContext.SetFPState((uint)value, (uint)FPCR.Mask);
|
||||
}
|
||||
public FPCR StandardFpcrValue => (Fpcr & (FPCR.Ahp)) | FPCR.Dn | FPCR.Fz;
|
||||
|
||||
public FPSCR Fpscr
|
||||
{
|
||||
get => (FPSCR)_nativeContext.GetFPState((uint)FPSCR.Mask);
|
||||
set => _nativeContext.SetFPState((uint)value, (uint)FPSCR.Mask);
|
||||
}
|
||||
|
||||
public bool IsAarch32 { get; set; }
|
||||
|
||||
internal ExecutionMode ExecutionMode
|
||||
|
@ -5,21 +5,18 @@ namespace ARMeilleure.State
|
||||
[Flags]
|
||||
public enum FPCR : uint
|
||||
{
|
||||
Ioe = 1u << 8,
|
||||
Dze = 1u << 9,
|
||||
Ofe = 1u << 10,
|
||||
Ufe = 1u << 11,
|
||||
Ixe = 1u << 12,
|
||||
Ide = 1u << 15,
|
||||
RMode0 = 1u << 22,
|
||||
RMode1 = 1u << 23,
|
||||
Fz = 1u << 24,
|
||||
Dn = 1u << 25,
|
||||
Ahp = 1u << 26,
|
||||
|
||||
A32Mask = 0x07FF9F00u
|
||||
}
|
||||
|
||||
public static class FPCRExtensions
|
||||
{
|
||||
private const int RModeShift = 22;
|
||||
|
||||
public static FPRoundingMode GetRoundingMode(this FPCR fpcr)
|
||||
{
|
||||
return (FPRoundingMode)(((int)fpcr >> RModeShift) & 3);
|
||||
}
|
||||
Mask = Ahp | Dn | Fz | RMode1 | RMode0 | Ide | Ixe | Ufe | Ofe | Dze | Ioe // 0x07C09F00u
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
}
|
||||
}
|
||||
|
15
ARMeilleure/State/FPSCR.cs
Normal file
15
ARMeilleure/State/FPSCR.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace ARMeilleure.State
|
||||
{
|
||||
[Flags]
|
||||
public enum FPSCR : uint
|
||||
{
|
||||
V = 1u << 28,
|
||||
C = 1u << 29,
|
||||
Z = 1u << 30,
|
||||
N = 1u << 31,
|
||||
|
||||
Mask = N | Z | C | V | FPSR.Mask | FPCR.Mask // 0xFFC09F9Fu
|
||||
}
|
||||
}
|
@ -5,11 +5,14 @@ namespace ARMeilleure.State
|
||||
[Flags]
|
||||
public enum FPSR : uint
|
||||
{
|
||||
Ioc = 1u << 0,
|
||||
Dzc = 1u << 1,
|
||||
Ofc = 1u << 2,
|
||||
Ufc = 1u << 3,
|
||||
Qc = 1u << 27,
|
||||
Ixc = 1u << 4,
|
||||
Idc = 1u << 7,
|
||||
Qc = 1u << 27,
|
||||
|
||||
Nzcv = (1u << 31) | (1u << 30) | (1u << 29) | (1u << 28),
|
||||
|
||||
A32Mask = 0xF800009Fu
|
||||
Mask = Qc | Idc | Ixc | Ufc | Ofc | Dzc | Ioc // 0x0800009Fu
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,30 @@
|
||||
{
|
||||
public enum FPState
|
||||
{
|
||||
// FPSR Flags.
|
||||
IocFlag = 0,
|
||||
DzcFlag = 1,
|
||||
OfcFlag = 2,
|
||||
UfcFlag = 3,
|
||||
IxcFlag = 4,
|
||||
IdcFlag = 7,
|
||||
QcFlag = 27,
|
||||
VFlag = 28,
|
||||
CFlag = 29,
|
||||
ZFlag = 30,
|
||||
NFlag = 31
|
||||
NFlag = 31,
|
||||
|
||||
// FPCR Flags.
|
||||
IoeFlag = 8,
|
||||
DzeFlag = 9,
|
||||
OfeFlag = 10,
|
||||
UfeFlag = 11,
|
||||
IxeFlag = 12,
|
||||
IdeFlag = 15,
|
||||
RMode0Flag = 22,
|
||||
RMode1Flag = 23,
|
||||
FzFlag = 24,
|
||||
DnFlag = 25,
|
||||
AhpFlag = 26
|
||||
}
|
||||
}
|
||||
|
@ -140,6 +140,34 @@ namespace ARMeilleure.State
|
||||
GetStorage().FpFlags[(int)flag] = value ? 1u : 0u;
|
||||
}
|
||||
|
||||
public unsafe uint GetFPState(uint mask = uint.MaxValue)
|
||||
{
|
||||
uint value = 0;
|
||||
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||
{
|
||||
uint bit = 1u << flag;
|
||||
|
||||
if ((mask & bit) == bit)
|
||||
{
|
||||
value |= GetStorage().FpFlags[flag] != 0 ? bit : 0u;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public unsafe void SetFPState(uint value, uint mask = uint.MaxValue)
|
||||
{
|
||||
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||
{
|
||||
uint bit = 1u << flag;
|
||||
|
||||
if ((mask & bit) == bit)
|
||||
{
|
||||
GetStorage().FpFlags[flag] = (value & bit) == bit ? 1u : 0u;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int GetCounter() => GetStorage().Counter;
|
||||
public void SetCounter(int value) => GetStorage().Counter = value;
|
||||
|
||||
|
@ -4,7 +4,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace ARMeilleure.Translation.Cache
|
||||
{
|
||||
struct CacheEntry : IComparable<CacheEntry>
|
||||
readonly struct CacheEntry : IComparable<CacheEntry>
|
||||
{
|
||||
public int Offset { get; }
|
||||
public int Size { get; }
|
||||
|
@ -6,7 +6,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
{
|
||||
class CacheMemoryAllocator
|
||||
{
|
||||
private struct MemoryBlock : IComparable<MemoryBlock>
|
||||
private readonly struct MemoryBlock : IComparable<MemoryBlock>
|
||||
{
|
||||
public int Offset { get; }
|
||||
public int Size { get; }
|
||||
|
@ -2,7 +2,7 @@ using ARMeilleure.IntermediateRepresentation;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
struct CompilerContext
|
||||
readonly struct CompilerContext
|
||||
{
|
||||
public ControlFlowGraph Cfg { get; }
|
||||
|
||||
|
@ -109,10 +109,6 @@ namespace ARMeilleure.Translation
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcr)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpsr)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.InvalidateCacheLine)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)));
|
||||
@ -124,10 +120,6 @@ namespace ARMeilleure.Translation
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpcr)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr))); // A32 only.
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsr)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)));
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032))); // A32 only.
|
||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking)));
|
||||
@ -151,12 +143,8 @@ namespace ARMeilleure.Translation
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32w)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32x)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Decrypt)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToInt32))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToUInt32))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Encrypt)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FixedRotate)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToInt32))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToUInt32))); // A32 only.
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashChoose)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashMajority)));
|
||||
@ -165,8 +153,6 @@ namespace ARMeilleure.Translation
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.InverseMixColumns)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.MixColumns)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.PolynomialMult64_128)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS64)));
|
||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)));
|
||||
|
@ -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 = 3700; //! 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
|
||||
|
@ -14,7 +14,7 @@ namespace ARMeilleure.Translation
|
||||
private const int RegsCount = 32;
|
||||
private const int RegsMask = RegsCount - 1;
|
||||
|
||||
private struct RegisterMask : IEquatable<RegisterMask>
|
||||
private readonly struct RegisterMask : IEquatable<RegisterMask>
|
||||
{
|
||||
public long IntMask => Mask.GetElement(0);
|
||||
public long VecMask => Mask.GetElement(1);
|
||||
|
@ -293,7 +293,7 @@ namespace ARMeilleure.Translation
|
||||
}
|
||||
}
|
||||
|
||||
private struct Range
|
||||
private readonly struct Range
|
||||
{
|
||||
public ulong Start { get; }
|
||||
public ulong End { get; }
|
||||
@ -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];
|
||||
|
16
README.md
16
README.md
@ -21,6 +21,10 @@
|
||||
<img src="https://github.com/Ryujinx/Ryujinx/actions/workflows/release.yml/badge.svg"
|
||||
alt="">
|
||||
</a>
|
||||
<a href="https://crwd.in/ryujinx">
|
||||
<img src="https://badges.crowdin.net/ryujinx/localized.svg"
|
||||
alt="">
|
||||
</a>
|
||||
<a href="https://discord.com/invite/VkQYXAZ">
|
||||
<img src="https://img.shields.io/discord/410208534861447168?color=5865F2&label=Ryujinx&logo=discord&logoColor=white"
|
||||
alt="Discord">
|
||||
@ -36,18 +40,20 @@
|
||||
|
||||
## 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 November 2022, Ryujinx has been tested on approximately 3,800 titles; over 3,600 boot past menus and into gameplay, with roughly 3,200 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
|
||||
|
||||
To run this emulator, your PC must be equipped with at least 8GB of RAM; failing to meet this requirement may result in a poor gameplay experience or unexpected crashes.
|
||||
To run this emulator, your PC must be equipped with at least 8GiB of RAM; failing to meet this requirement may result in a poor gameplay experience or unexpected crashes.
|
||||
|
||||
See our [Setup & Configuration Guide](https://github.com/Ryujinx/Ryujinx/wiki/Ryujinx-Setup-&-Configuration-Guide) on how to set up the emulator.
|
||||
|
||||
For our Local Wireless and LAN builds, see our [Multiplayer: Local Play/Local Wireless Guide
|
||||
](https://github.com/Ryujinx/Ryujinx/wiki/Multiplayer-(LDN-Local-Wireless)-Guide).
|
||||
|
||||
Avalonia UI comes with translations for various languages. See [Crowdin](https://crwd.in/ryujinx) for more information.
|
||||
|
||||
## Latest build
|
||||
|
||||
These builds are compiled automatically for each commit on the master branch. While we strive to ensure optimal stability and performance prior to pushing an update, our automated builds **may be unstable or completely broken.**
|
||||
@ -62,7 +68,7 @@ The latest automatic build for Windows, macOS, and Linux can be found on the [Of
|
||||
If you wish to build the emulator yourself, follow these steps:
|
||||
|
||||
### Step 1
|
||||
Install the X64 version of [.NET 6.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/6.0).
|
||||
Install the X64 version of [.NET 7.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/7.0).
|
||||
|
||||
### Step 2
|
||||
Either use `git clone https://github.com/Ryujinx/Ryujinx` on the command line to clone the repository or use Code --> Download zip button to get the files.
|
||||
@ -90,7 +96,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), Vulkan, or Metal (via MoltenVK) 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**
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTK.OpenAL" Version="4.7.2" />
|
||||
<PackageReference Include="OpenTK.OpenAL" Version="4.7.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using Ryujinx.Audio.Common;
|
||||
using Ryujinx.Audio.Integration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Memory;
|
||||
using Ryujinx.SDL2.Common;
|
||||
using System;
|
||||
@ -112,6 +113,9 @@ namespace Ryujinx.Audio.Backends.SDL2
|
||||
|
||||
if (device == 0)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application,
|
||||
$"SDL2 open audio device initialization failed with error \"{SDL_GetError()}\"");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -119,6 +123,7 @@ namespace Ryujinx.Audio.Backends.SDL2
|
||||
|
||||
if (!isValid)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, "SDL2 open audio device is not valid");
|
||||
SDL_CloseAudioDevice(device);
|
||||
|
||||
return 0;
|
||||
|
@ -4,7 +4,7 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace SoundIOSharp
|
||||
{
|
||||
public struct SoundIOChannelLayout
|
||||
public readonly struct SoundIOChannelLayout
|
||||
{
|
||||
public static int BuiltInCount
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace SoundIOSharp
|
||||
{
|
||||
public struct SoundIOSampleRateRange
|
||||
public readonly struct SoundIOSampleRateRange
|
||||
{
|
||||
internal SoundIOSampleRateRange(int min, int max)
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<RuntimeIdentifiers>win10-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
|
@ -48,6 +48,11 @@ namespace Ryujinx.Audio.Renderer.Common
|
||||
/// <summary>
|
||||
/// Effect to capture mixes (via auxiliary buffers).
|
||||
/// </summary>
|
||||
CaptureBuffer
|
||||
CaptureBuffer,
|
||||
|
||||
/// <summary>
|
||||
/// Effect applying a compressor filter (DRC).
|
||||
/// </summary>
|
||||
Compressor,
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ namespace Ryujinx.Audio.Renderer.Common
|
||||
Reverb3d,
|
||||
PcmFloat,
|
||||
Limiter,
|
||||
CaptureBuffer
|
||||
CaptureBuffer,
|
||||
Compressor
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using Ryujinx.Audio.Renderer.Dsp.State;
|
||||
using Ryujinx.Common.Logging;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
@ -71,6 +72,19 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
return (short)value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static short GetCoefficientAtIndex(ReadOnlySpan<short> coefficients, int index)
|
||||
{
|
||||
if ((uint)index > (uint)coefficients.Length)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.AudioRenderer, $"Out of bound read for coefficient at index {index}");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return coefficients[index];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int Decode(Span<short> output, ReadOnlySpan<byte> input, int startSampleOffset, int endSampleOffset, int offset, int count, ReadOnlySpan<short> coefficients, ref AdpcmLoopContext loopContext)
|
||||
{
|
||||
@ -84,8 +98,8 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
byte coefficientIndex = (byte)((predScale >> 4) & 0xF);
|
||||
short history0 = loopContext.History0;
|
||||
short history1 = loopContext.History1;
|
||||
short coefficient0 = coefficients[coefficientIndex * 2 + 0];
|
||||
short coefficient1 = coefficients[coefficientIndex * 2 + 1];
|
||||
short coefficient0 = GetCoefficientAtIndex(coefficients, coefficientIndex * 2 + 0);
|
||||
short coefficient1 = GetCoefficientAtIndex(coefficients, coefficientIndex * 2 + 1);
|
||||
|
||||
int decodedCount = Math.Min(count, endSampleOffset - startSampleOffset - offset);
|
||||
int nibbles = GetNibblesFromSampleCount(offset + startSampleOffset);
|
||||
@ -109,8 +123,8 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
|
||||
coefficientIndex = (byte)((predScale >> 4) & 0xF);
|
||||
|
||||
coefficient0 = coefficients[coefficientIndex * 2 + 0];
|
||||
coefficient1 = coefficients[coefficientIndex * 2 + 1];
|
||||
coefficient0 = GetCoefficientAtIndex(coefficients, coefficientIndex * 2);
|
||||
coefficient1 = GetCoefficientAtIndex(coefficients, coefficientIndex * 2 + 1);
|
||||
|
||||
nibbles += 2;
|
||||
|
||||
|
@ -116,6 +116,11 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
};
|
||||
}
|
||||
|
||||
public bool HasRemainingCommands(int sessionId)
|
||||
{
|
||||
return _sessionCommandList[sessionId] != null;
|
||||
}
|
||||
|
||||
public void Signal()
|
||||
{
|
||||
_mailbox.SendMessage(MailboxMessage.RenderStart);
|
||||
|
@ -13,7 +13,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.AdpcmDataSourceVersion1;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public ushort OutputBufferIndex { get; }
|
||||
public uint SampleRate { get; }
|
||||
|
@ -16,7 +16,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.AuxiliaryBuffer;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public uint InputBufferIndex { get; }
|
||||
public uint OutputBufferIndex { get; }
|
||||
|
@ -12,7 +12,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.BiquadFilter;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public Memory<BiquadFilterState> BiquadFilterState { get; }
|
||||
public int InputBufferIndex { get; }
|
||||
|
@ -16,7 +16,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.CaptureBuffer;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public uint InputBufferIndex { get; }
|
||||
|
||||
|
@ -12,7 +12,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.CircularBufferSink;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public ushort[] Input { get; }
|
||||
public uint InputCount { get; }
|
||||
|
@ -8,7 +8,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.ClearMixBuffer;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public ClearMixBufferCommand(int nodeId)
|
||||
{
|
||||
|
@ -31,6 +31,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
LimiterVersion1,
|
||||
LimiterVersion2,
|
||||
GroupedBiquadFilter,
|
||||
CaptureBuffer
|
||||
CaptureBuffer,
|
||||
Compressor
|
||||
}
|
||||
}
|
173
Ryujinx.Audio/Renderer/Dsp/Command/CompressorCommand.cs
Normal file
173
Ryujinx.Audio/Renderer/Dsp/Command/CompressorCommand.cs
Normal file
@ -0,0 +1,173 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Ryujinx.Audio.Renderer.Dsp.Effect;
|
||||
using Ryujinx.Audio.Renderer.Dsp.State;
|
||||
using Ryujinx.Audio.Renderer.Parameter.Effect;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
{
|
||||
public class CompressorCommand : ICommand
|
||||
{
|
||||
private const int FixedPointPrecision = 15;
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public int NodeId { get; }
|
||||
|
||||
public CommandType CommandType => CommandType.Compressor;
|
||||
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public CompressorParameter Parameter => _parameter;
|
||||
public Memory<CompressorState> State { get; }
|
||||
public ushort[] OutputBufferIndices { get; }
|
||||
public ushort[] InputBufferIndices { get; }
|
||||
public bool IsEffectEnabled { get; }
|
||||
|
||||
private CompressorParameter _parameter;
|
||||
|
||||
public CompressorCommand(uint bufferOffset, CompressorParameter parameter, Memory<CompressorState> state, bool isEnabled, int nodeId)
|
||||
{
|
||||
Enabled = true;
|
||||
NodeId = nodeId;
|
||||
_parameter = parameter;
|
||||
State = state;
|
||||
|
||||
IsEffectEnabled = isEnabled;
|
||||
|
||||
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
|
||||
|
||||
for (int i = 0; i < _parameter.ChannelCount; i++)
|
||||
{
|
||||
InputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Input[i]);
|
||||
OutputBufferIndices[i] = (ushort)(bufferOffset + _parameter.Output[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void Process(CommandList context)
|
||||
{
|
||||
ref CompressorState state = ref State.Span[0];
|
||||
|
||||
if (IsEffectEnabled)
|
||||
{
|
||||
if (_parameter.Status == Server.Effect.UsageState.Invalid)
|
||||
{
|
||||
state = new CompressorState(ref _parameter);
|
||||
}
|
||||
else if (_parameter.Status == Server.Effect.UsageState.New)
|
||||
{
|
||||
state.UpdateParameter(ref _parameter);
|
||||
}
|
||||
}
|
||||
|
||||
ProcessCompressor(context, ref state);
|
||||
}
|
||||
|
||||
private unsafe void ProcessCompressor(CommandList context, ref CompressorState state)
|
||||
{
|
||||
Debug.Assert(_parameter.IsChannelCountValid());
|
||||
|
||||
if (IsEffectEnabled && _parameter.IsChannelCountValid())
|
||||
{
|
||||
Span<IntPtr> inputBuffers = stackalloc IntPtr[Parameter.ChannelCount];
|
||||
Span<IntPtr> outputBuffers = stackalloc IntPtr[Parameter.ChannelCount];
|
||||
Span<float> channelInput = stackalloc float[Parameter.ChannelCount];
|
||||
ExponentialMovingAverage inputMovingAverage = state.InputMovingAverage;
|
||||
float unknown4 = state.Unknown4;
|
||||
ExponentialMovingAverage compressionGainAverage = state.CompressionGainAverage;
|
||||
float previousCompressionEmaAlpha = state.PreviousCompressionEmaAlpha;
|
||||
|
||||
for (int i = 0; i < _parameter.ChannelCount; i++)
|
||||
{
|
||||
inputBuffers[i] = context.GetBufferPointer(InputBufferIndices[i]);
|
||||
outputBuffers[i] = context.GetBufferPointer(OutputBufferIndices[i]);
|
||||
}
|
||||
|
||||
for (int sampleIndex = 0; sampleIndex < context.SampleCount; sampleIndex++)
|
||||
{
|
||||
for (int channelIndex = 0; channelIndex < _parameter.ChannelCount; channelIndex++)
|
||||
{
|
||||
channelInput[channelIndex] = *((float*)inputBuffers[channelIndex] + sampleIndex);
|
||||
}
|
||||
|
||||
float newMean = inputMovingAverage.Update(FloatingPointHelper.MeanSquare(channelInput), _parameter.InputGain);
|
||||
float y = FloatingPointHelper.Log10(newMean) * 10.0f;
|
||||
float z = 0.0f;
|
||||
|
||||
bool unknown10OutOfRange = false;
|
||||
|
||||
if (newMean < 1.0e-10f)
|
||||
{
|
||||
z = 1.0f;
|
||||
|
||||
unknown10OutOfRange = state.Unknown10 < -100.0f;
|
||||
}
|
||||
|
||||
if (y >= state.Unknown10 || unknown10OutOfRange)
|
||||
{
|
||||
float tmpGain;
|
||||
|
||||
if (y >= state.Unknown14)
|
||||
{
|
||||
tmpGain = ((1.0f / Parameter.Ratio) - 1.0f) * (y - Parameter.Threshold);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpGain = (y - state.Unknown10) * ((y - state.Unknown10) * -state.CompressorGainReduction);
|
||||
}
|
||||
|
||||
z = FloatingPointHelper.DecibelToLinearExtended(tmpGain);
|
||||
}
|
||||
|
||||
float unknown4New = z;
|
||||
float compressionEmaAlpha;
|
||||
|
||||
if ((unknown4 - z) <= 0.08f)
|
||||
{
|
||||
compressionEmaAlpha = Parameter.ReleaseCoefficient;
|
||||
|
||||
if ((unknown4 - z) >= -0.08f)
|
||||
{
|
||||
if (MathF.Abs(compressionGainAverage.Read() - z) >= 0.001f)
|
||||
{
|
||||
unknown4New = unknown4;
|
||||
}
|
||||
|
||||
compressionEmaAlpha = previousCompressionEmaAlpha;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
compressionEmaAlpha = Parameter.AttackCoefficient;
|
||||
}
|
||||
|
||||
float compressionGain = compressionGainAverage.Update(z, compressionEmaAlpha);
|
||||
|
||||
for (int channelIndex = 0; channelIndex < Parameter.ChannelCount; channelIndex++)
|
||||
{
|
||||
*((float*)outputBuffers[channelIndex] + sampleIndex) = channelInput[channelIndex] * compressionGain * state.OutputGain;
|
||||
}
|
||||
|
||||
unknown4 = unknown4New;
|
||||
previousCompressionEmaAlpha = compressionEmaAlpha;
|
||||
}
|
||||
|
||||
state.InputMovingAverage = inputMovingAverage;
|
||||
state.Unknown4 = unknown4;
|
||||
state.CompressionGainAverage = compressionGainAverage;
|
||||
state.PreviousCompressionEmaAlpha = previousCompressionEmaAlpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < Parameter.ChannelCount; i++)
|
||||
{
|
||||
if (InputBufferIndices[i] != OutputBufferIndices[i])
|
||||
{
|
||||
context.CopyBuffer(OutputBufferIndices[i], InputBufferIndices[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.CopyMixBuffer;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public ushort InputBufferIndex { get; }
|
||||
public ushort OutputBufferIndex { get; }
|
||||
|
@ -13,7 +13,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType { get; }
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public ushort OutputBufferIndex { get; }
|
||||
public uint SampleRate { get; }
|
||||
|
@ -17,7 +17,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.Delay;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public DelayParameter Parameter => _parameter;
|
||||
public Memory<DelayState> State { get; }
|
||||
@ -49,15 +49,15 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
OutputBufferIndices[i] = (ushort)(bufferOffset + Parameter.Output[i]);
|
||||
}
|
||||
|
||||
// NOTE: We do the opposite as Nintendo here for now to restore previous behaviour
|
||||
// TODO: Update delay processing and remove this to use RemapLegacyChannelEffectMappingToChannelResourceMapping.
|
||||
DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, InputBufferIndices);
|
||||
DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, OutputBufferIndices);
|
||||
DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, InputBufferIndices);
|
||||
DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, OutputBufferIndices);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
private unsafe void ProcessDelayMono(ref DelayState state, float* outputBuffer, float* inputBuffer, uint sampleCount)
|
||||
{
|
||||
const ushort channelCount = 1;
|
||||
|
||||
float feedbackGain = FixedPointHelper.ToFloat(Parameter.FeedbackGain, FixedPointPrecision);
|
||||
float inGain = FixedPointHelper.ToFloat(Parameter.InGain, FixedPointPrecision);
|
||||
float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision);
|
||||
@ -70,7 +70,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
float temp = input * inGain + delayLineValue * feedbackGain;
|
||||
|
||||
state.UpdateLowPassFilter(ref temp, 1);
|
||||
state.UpdateLowPassFilter(ref temp, channelCount);
|
||||
|
||||
outputBuffer[i] = (input * dryGain + delayLineValue * outGain) / 64;
|
||||
}
|
||||
@ -104,7 +104,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
Y = state.DelayLines[1].Read(),
|
||||
};
|
||||
|
||||
Vector2 temp = MatrixHelper.Transform(ref channelInput, ref delayFeedback) + channelInput * inGain;
|
||||
Vector2 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain;
|
||||
|
||||
state.UpdateLowPassFilter(ref Unsafe.As<Vector2, float>(ref temp), channelCount);
|
||||
|
||||
@ -148,7 +148,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
W = state.DelayLines[3].Read()
|
||||
};
|
||||
|
||||
Vector4 temp = MatrixHelper.Transform(ref channelInput, ref delayFeedback) + channelInput * inGain;
|
||||
Vector4 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain;
|
||||
|
||||
state.UpdateLowPassFilter(ref Unsafe.As<Vector4, float>(ref temp), channelCount);
|
||||
|
||||
@ -171,12 +171,12 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision);
|
||||
float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision);
|
||||
|
||||
Matrix6x6 delayFeedback = new Matrix6x6(delayFeedbackBaseGain, 0.0f, 0.0f, 0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain,
|
||||
0.0f, delayFeedbackBaseGain, 0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain, 0.0f,
|
||||
delayFeedbackCrossGain, 0.0f, delayFeedbackBaseGain, delayFeedbackCrossGain, 0.0f, 0.0f,
|
||||
0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain, delayFeedbackBaseGain, 0.0f, 0.0f,
|
||||
delayFeedbackCrossGain, delayFeedbackCrossGain, 0.0f, 0.0f, delayFeedbackBaseGain, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, feedbackGain);
|
||||
Matrix6x6 delayFeedback = new Matrix6x6(delayFeedbackBaseGain, 0.0f, delayFeedbackCrossGain, 0.0f, delayFeedbackCrossGain, 0.0f,
|
||||
0.0f, delayFeedbackBaseGain, delayFeedbackCrossGain, 0.0f, 0.0f, delayFeedbackCrossGain,
|
||||
delayFeedbackCrossGain, delayFeedbackCrossGain, delayFeedbackBaseGain, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, feedbackGain, 0.0f, 0.0f,
|
||||
delayFeedbackCrossGain, 0.0f, 0.0f, 0.0f, delayFeedbackBaseGain, delayFeedbackCrossGain,
|
||||
0.0f, delayFeedbackCrossGain, 0.0f, 0.0f, delayFeedbackCrossGain, delayFeedbackBaseGain);
|
||||
|
||||
for (int i = 0; i < sampleCount; i++)
|
||||
{
|
||||
@ -200,7 +200,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
U = state.DelayLines[5].Read()
|
||||
};
|
||||
|
||||
Vector6 temp = MatrixHelper.Transform(ref channelInput, ref delayFeedback) + channelInput * inGain;
|
||||
Vector6 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain;
|
||||
|
||||
state.UpdateLowPassFilter(ref Unsafe.As<Vector6, float>(ref temp), channelCount);
|
||||
|
||||
|
@ -11,7 +11,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.DepopForMixBuffers;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public uint MixBufferOffset { get; }
|
||||
|
||||
|
@ -11,7 +11,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.DepopPrepare;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public uint MixBufferCount { get; }
|
||||
|
||||
|
@ -14,7 +14,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.DeviceSink;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public string DeviceName { get; }
|
||||
|
||||
|
@ -11,7 +11,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.DownMixSurroundToStereo;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public ushort[] InputBufferIndices { get; }
|
||||
public ushort[] OutputBufferIndices { get; }
|
||||
|
@ -12,7 +12,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.GroupedBiquadFilter;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
private BiquadFilterParameter[] _parameters;
|
||||
private Memory<BiquadFilterState> _biquadFilterStates;
|
||||
@ -47,9 +47,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Nintendo also implements a hot path for double biquad filters, but no generic path when the command definition suggests it could be done.
|
||||
// As such we currently only implement a generic path for simplicity.
|
||||
// TODO: Implement double biquad filters fast path.
|
||||
// NOTE: Nintendo only implement single and double biquad filters but no generic path when the command definition suggests it could be done.
|
||||
// As such we currently only implement a generic path for simplicity for double biquad.
|
||||
if (_parameters.Length == 1)
|
||||
{
|
||||
BiquadFilterHelper.ProcessBiquadFilter(ref _parameters[0], ref states[0], outputBuffer, inputBuffer, context.SampleCount);
|
||||
|
@ -8,7 +8,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType { get; }
|
||||
|
||||
public ulong EstimatedProcessingTime { get; }
|
||||
public uint EstimatedProcessingTime { get; }
|
||||
|
||||
public void Process(CommandList context);
|
||||
|
||||
|
@ -13,7 +13,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.LimiterVersion1;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public LimiterParameter Parameter => _parameter;
|
||||
public Memory<LimiterState> State { get; }
|
||||
@ -90,32 +90,31 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
float inputCoefficient = Parameter.ReleaseCoefficient;
|
||||
|
||||
if (sampleInputMax > state.DectectorAverage[channelIndex])
|
||||
if (sampleInputMax > state.DetectorAverage[channelIndex].Read())
|
||||
{
|
||||
inputCoefficient = Parameter.AttackCoefficient;
|
||||
}
|
||||
|
||||
state.DectectorAverage[channelIndex] += inputCoefficient * (sampleInputMax - state.DectectorAverage[channelIndex]);
|
||||
|
||||
float detectorValue = state.DetectorAverage[channelIndex].Update(sampleInputMax, inputCoefficient);
|
||||
float attenuation = 1.0f;
|
||||
|
||||
if (state.DectectorAverage[channelIndex] > Parameter.Threshold)
|
||||
if (detectorValue > Parameter.Threshold)
|
||||
{
|
||||
attenuation = Parameter.Threshold / state.DectectorAverage[channelIndex];
|
||||
attenuation = Parameter.Threshold / detectorValue;
|
||||
}
|
||||
|
||||
float outputCoefficient = Parameter.ReleaseCoefficient;
|
||||
|
||||
if (state.CompressionGain[channelIndex] > attenuation)
|
||||
if (state.CompressionGainAverage[channelIndex].Read() > attenuation)
|
||||
{
|
||||
outputCoefficient = Parameter.AttackCoefficient;
|
||||
}
|
||||
|
||||
state.CompressionGain[channelIndex] += outputCoefficient * (attenuation - state.CompressionGain[channelIndex]);
|
||||
float compressionGain = state.CompressionGainAverage[channelIndex].Update(attenuation, outputCoefficient);
|
||||
|
||||
ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * Parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]];
|
||||
|
||||
float outputSample = delayedSample * state.CompressionGain[channelIndex] * Parameter.OutputGain;
|
||||
float outputSample = delayedSample * compressionGain * Parameter.OutputGain;
|
||||
|
||||
*((float*)outputBuffers[channelIndex] + sampleIndex) = outputSample * short.MaxValue;
|
||||
|
||||
|
@ -15,7 +15,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.LimiterVersion2;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public LimiterParameter Parameter => _parameter;
|
||||
public Memory<LimiterState> State { get; }
|
||||
@ -101,32 +101,31 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
float inputCoefficient = Parameter.ReleaseCoefficient;
|
||||
|
||||
if (sampleInputMax > state.DectectorAverage[channelIndex])
|
||||
if (sampleInputMax > state.DetectorAverage[channelIndex].Read())
|
||||
{
|
||||
inputCoefficient = Parameter.AttackCoefficient;
|
||||
}
|
||||
|
||||
state.DectectorAverage[channelIndex] += inputCoefficient * (sampleInputMax - state.DectectorAverage[channelIndex]);
|
||||
|
||||
float detectorValue = state.DetectorAverage[channelIndex].Update(sampleInputMax, inputCoefficient);
|
||||
float attenuation = 1.0f;
|
||||
|
||||
if (state.DectectorAverage[channelIndex] > Parameter.Threshold)
|
||||
if (detectorValue > Parameter.Threshold)
|
||||
{
|
||||
attenuation = Parameter.Threshold / state.DectectorAverage[channelIndex];
|
||||
attenuation = Parameter.Threshold / detectorValue;
|
||||
}
|
||||
|
||||
float outputCoefficient = Parameter.ReleaseCoefficient;
|
||||
|
||||
if (state.CompressionGain[channelIndex] > attenuation)
|
||||
if (state.CompressionGainAverage[channelIndex].Read() > attenuation)
|
||||
{
|
||||
outputCoefficient = Parameter.AttackCoefficient;
|
||||
}
|
||||
|
||||
state.CompressionGain[channelIndex] += outputCoefficient * (attenuation - state.CompressionGain[channelIndex]);
|
||||
float compressionGain = state.CompressionGainAverage[channelIndex].Update(attenuation, outputCoefficient);
|
||||
|
||||
ref float delayedSample = ref state.DelayedSampleBuffer[channelIndex * Parameter.DelayBufferSampleCountMax + state.DelayedSampleBufferPosition[channelIndex]];
|
||||
|
||||
float outputSample = delayedSample * state.CompressionGain[channelIndex] * Parameter.OutputGain;
|
||||
float outputSample = delayedSample * compressionGain * Parameter.OutputGain;
|
||||
|
||||
*((float*)outputBuffers[channelIndex] + sampleIndex) = outputSample * short.MaxValue;
|
||||
|
||||
@ -144,7 +143,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
ref LimiterStatistics statistics = ref MemoryMarshal.Cast<byte, LimiterStatistics>(ResultState.Span[0].SpecificData)[0];
|
||||
|
||||
statistics.InputMax[channelIndex] = Math.Max(statistics.InputMax[channelIndex], sampleInputMax);
|
||||
statistics.CompressionGainMin[channelIndex] = Math.Min(statistics.CompressionGainMin[channelIndex], state.CompressionGain[channelIndex]);
|
||||
statistics.CompressionGainMin[channelIndex] = Math.Min(statistics.CompressionGainMin[channelIndex], compressionGain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.Mix;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public ushort InputBufferIndex { get; }
|
||||
public ushort OutputBufferIndex { get; }
|
||||
|
@ -12,7 +12,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.MixRamp;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public ushort InputBufferIndex { get; }
|
||||
public ushort OutputBufferIndex { get; }
|
||||
|
@ -12,7 +12,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.MixRampGrouped;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public uint MixBufferCount { get; }
|
||||
|
||||
|
@ -13,7 +13,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.PcmFloatDataSourceVersion1;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public ushort OutputBufferIndex { get; }
|
||||
public uint SampleRate { get; }
|
||||
|
@ -13,7 +13,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.PcmInt16DataSourceVersion1;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public ushort OutputBufferIndex { get; }
|
||||
public uint SampleRate { get; }
|
||||
|
@ -17,7 +17,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.Performance;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public PerformanceEntryAddresses PerformanceEntryAddresses { get; }
|
||||
|
||||
|
@ -31,7 +31,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.Reverb3d;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public ushort InputBufferIndex { get; }
|
||||
public ushort OutputBufferIndex { get; }
|
||||
|
@ -34,7 +34,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.Reverb;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public ReverbParameter Parameter => _parameter;
|
||||
public Memory<ReverbState> State { get; }
|
||||
|
@ -11,7 +11,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.Upsample;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public uint BufferCount { get; }
|
||||
public uint InputBufferIndex { get; }
|
||||
|
@ -15,7 +15,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.Volume;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public ushort InputBufferIndex { get; }
|
||||
public ushort OutputBufferIndex { get; }
|
||||
|
@ -11,7 +11,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public CommandType CommandType => CommandType.VolumeRamp;
|
||||
|
||||
public ulong EstimatedProcessingTime { get; set; }
|
||||
public uint EstimatedProcessingTime { get; set; }
|
||||
|
||||
public ushort InputBufferIndex { get; }
|
||||
public ushort OutputBufferIndex { get; }
|
||||
|
@ -0,0 +1,26 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.Effect
|
||||
{
|
||||
public struct ExponentialMovingAverage
|
||||
{
|
||||
private float _mean;
|
||||
|
||||
public ExponentialMovingAverage(float mean)
|
||||
{
|
||||
_mean = mean;
|
||||
}
|
||||
|
||||
public float Read()
|
||||
{
|
||||
return _mean;
|
||||
}
|
||||
|
||||
public float Update(float value, float alpha)
|
||||
{
|
||||
_mean += alpha * (value - _mean);
|
||||
|
||||
return _mean;
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,12 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
return (float)value / (1 << qBits);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float ConvertFloat(float value, int qBits)
|
||||
{
|
||||
return value / (1 << qBits);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int ToFixed(float value, int qBits)
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp
|
||||
@ -46,6 +47,53 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
return MathF.Pow(10, x);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float Log10(float x)
|
||||
{
|
||||
// NOTE: Nintendo uses an approximation of log10, we don't.
|
||||
// As such, we support the same ranges as Nintendo to avoid unexpected behaviours.
|
||||
return MathF.Pow(10, MathF.Max(x, 1.0e-10f));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float MeanSquare(ReadOnlySpan<float> inputs)
|
||||
{
|
||||
float res = 0.0f;
|
||||
|
||||
foreach (float input in inputs)
|
||||
{
|
||||
res += (input * input);
|
||||
}
|
||||
|
||||
res /= inputs.Length;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Map decibel to linear.
|
||||
/// </summary>
|
||||
/// <param name="db">The decibel value to convert</param>
|
||||
/// <returns>Converted linear value/returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float DecibelToLinear(float db)
|
||||
{
|
||||
return MathF.Pow(10.0f, db / 20.0f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Map decibel to linear in [0, 2] range.
|
||||
/// </summary>
|
||||
/// <param name="db">The decibel value to convert</param>
|
||||
/// <returns>Converted linear value in [0, 2] range</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float DecibelToLinearExtended(float db)
|
||||
{
|
||||
float tmp = MathF.Log2(DecibelToLinear(db));
|
||||
|
||||
return MathF.Truncate(tmp) + MathF.Pow(2.0f, tmp - MathF.Truncate(tmp));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float DegreesToRadians(float degrees)
|
||||
{
|
||||
|
51
Ryujinx.Audio/Renderer/Dsp/State/CompressorState.cs
Normal file
51
Ryujinx.Audio/Renderer/Dsp/State/CompressorState.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using Ryujinx.Audio.Renderer.Dsp.Effect;
|
||||
using Ryujinx.Audio.Renderer.Parameter.Effect;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp.State
|
||||
{
|
||||
public class CompressorState
|
||||
{
|
||||
public ExponentialMovingAverage InputMovingAverage;
|
||||
public float Unknown4;
|
||||
public ExponentialMovingAverage CompressionGainAverage;
|
||||
public float CompressorGainReduction;
|
||||
public float Unknown10;
|
||||
public float Unknown14;
|
||||
public float PreviousCompressionEmaAlpha;
|
||||
public float MakeupGain;
|
||||
public float OutputGain;
|
||||
|
||||
public CompressorState(ref CompressorParameter parameter)
|
||||
{
|
||||
InputMovingAverage = new ExponentialMovingAverage(0.0f);
|
||||
Unknown4 = 1.0f;
|
||||
CompressionGainAverage = new ExponentialMovingAverage(1.0f);
|
||||
|
||||
UpdateParameter(ref parameter);
|
||||
}
|
||||
|
||||
public void UpdateParameter(ref CompressorParameter parameter)
|
||||
{
|
||||
float threshold = parameter.Threshold;
|
||||
float ratio = 1.0f / parameter.Ratio;
|
||||
float attackCoefficient = parameter.AttackCoefficient;
|
||||
float makeupGain;
|
||||
|
||||
if (parameter.MakeupGainEnabled)
|
||||
{
|
||||
makeupGain = (threshold * 0.5f * (ratio - 1.0f)) - 3.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
makeupGain = 0.0f;
|
||||
}
|
||||
|
||||
PreviousCompressionEmaAlpha = attackCoefficient;
|
||||
MakeupGain = makeupGain;
|
||||
CompressorGainReduction = (1.0f - ratio) / Constants.ChannelCountMax;
|
||||
Unknown10 = threshold - 1.5f;
|
||||
Unknown14 = threshold + 1.5f;
|
||||
OutputGain = FloatingPointHelper.DecibelToLinearExtended(parameter.OutputGain + makeupGain);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using Ryujinx.Audio.Renderer.Dsp.Effect;
|
||||
using Ryujinx.Audio.Renderer.Parameter.Effect;
|
||||
using System;
|
||||
|
||||
@ -5,20 +6,20 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
||||
{
|
||||
public class LimiterState
|
||||
{
|
||||
public float[] DectectorAverage;
|
||||
public float[] CompressionGain;
|
||||
public ExponentialMovingAverage[] DetectorAverage;
|
||||
public ExponentialMovingAverage[] CompressionGainAverage;
|
||||
public float[] DelayedSampleBuffer;
|
||||
public int[] DelayedSampleBufferPosition;
|
||||
|
||||
public LimiterState(ref LimiterParameter parameter, ulong workBuffer)
|
||||
{
|
||||
DectectorAverage = new float[parameter.ChannelCount];
|
||||
CompressionGain = new float[parameter.ChannelCount];
|
||||
DetectorAverage = new ExponentialMovingAverage[parameter.ChannelCount];
|
||||
CompressionGainAverage = new ExponentialMovingAverage[parameter.ChannelCount];
|
||||
DelayedSampleBuffer = new float[parameter.ChannelCount * parameter.DelayBufferSampleCountMax];
|
||||
DelayedSampleBufferPosition = new int[parameter.ChannelCount];
|
||||
|
||||
DectectorAverage.AsSpan().Fill(0.0f);
|
||||
CompressionGain.AsSpan().Fill(1.0f);
|
||||
DetectorAverage.AsSpan().Fill(new ExponentialMovingAverage(0.0f));
|
||||
CompressionGainAverage.AsSpan().Fill(new ExponentialMovingAverage(1.0f));
|
||||
DelayedSampleBufferPosition.AsSpan().Fill(0);
|
||||
DelayedSampleBuffer.AsSpan().Fill(0.0f);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user