Compare commits

...

430 Commits

Author SHA1 Message Date
f1eef29409 nuget: bump UnicornEngine.Unicorn (#4459)
Bumps [UnicornEngine.Unicorn](https://github.com/unicorn-engine/unicorn) from 2.0.2-rc1-9c9356d to 2.0.2-rc1-a913199.
- [Release notes](https://github.com/unicorn-engine/unicorn/releases)
- [Changelog](https://github.com/unicorn-engine/unicorn/blob/master/ChangeLog)
- [Commits](https://github.com/unicorn-engine/unicorn/commits)

---
updated-dependencies:
- dependency-name: UnicornEngine.Unicorn
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-22 13:30:53 +01:00
1f8d66db7c Ava: Fix Updater crashing on Linux (#4457) 2023-02-22 09:13:50 +01:00
c3a5716a95 Add copy dependency for some incompatible texture formats (#4380)
* Add copy dependency for some incompatible texture formats

* Simplify compatibility check
2023-02-21 19:21:57 -03:00
1f1e2a7f03 misc: changes base application directory behaviour (#4460)
This allows changing base application directory behavior at build time via FORCE_EXTERNAL_BASE_DIR.

This is intended to be used by nixpkgs and flathub builds.

I also added the missing patch for macOS that we have on macos1 to avoid invalidating code signature.
2023-02-21 22:38:34 +01:00
e54f9dc4b4 Move Ryujinx Folder from ~/.config to ~/Library/Application Support on macOS (#4296)
* Move Ryujinx folder to Application Support on macOS

* Create a symlink to preserve back compat

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Remove extra whitespace

* Don’t create a symlink

* Update Ryujinx.Common/Configuration/AppDataManager.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Revert "Don’t create a symlink"

This reverts commit 31752fe8ab.

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-02-21 12:14:31 +01:00
edfd4d70c0 Use SIMD acceleration for audio upsampler (#4410)
* Use SIMD acceleration for audio upsampler filter kernel for a moderate speedup

* Address formatting. Implement AVX2 fast path for high quality resampling in ResamplerHelper

* now really, are we really getting the benefit of inlining 50+ line methods?

* adding unit tests for resampler + upsampler. The upsampler ones fail for some reason

* Fixing upsampler test. Apparently this algo only works at specific ratios

---------

Co-authored-by: Logan Stromberg <lostromb@microsoft.com>
2023-02-21 11:44:57 +01:00
fc43aecbbd Memory: Faster Split for NonOverlappingRangeList (#4451)
I noticed that in Xenoblade 2, the game can end up spending a lot of time adding and removing tracking handles. One of the main causes of this is actually splitting existing handles, which does the following:

- Remove existing handle from list
- Update existing handle to end at split address, create new handle starting at split address
- Add updated handle (left) to list
- Add new handle (right) to list

This costs 1 deletion and 2 insertions. When there are more handles, this gets a lot more expensive, as insertions are done by copying all values to the right, and deletions by copying values to the left.

This PR simply allows it to look up the handle being split, and replace its entry with the new end address without insertion or deletion. This makes a split only cost one insertion and a binary search lookup (very cheap). This isn't all of the cost on Xenoblade 2, but it does significantly reduce it.

There might be something else to this - we could find a way to reduce the handle count for the game (merging on deletion? buffer deletion?), we could use a different structure for virtual regions, as the current one is optimal for buffer lookups which nearly always read, memory tracking has more of a balance between read/write. That's for a later date though, this was an easy improvment.
2023-02-21 10:53:38 +01:00
58d7a1fe97 Mark texture as modified and sync on I2M fast path (#4449) 2023-02-21 10:40:23 +01:00
7aa430f1a5 Add support for advanced blend (part 1/2) (#2801)
* Add blend microcode registers

* Add advanced blend support using host extension

* Remove debug message

* Use pre-generated table for blend functions

* XML docs

* Rename AdvancedBlendMode to AdvancedBlendOp for consistency

* Remove redundant code

* Fix some advanced blend related issues on Vulkan

* Formatting
2023-02-19 22:37:37 -03:00
6bf460e104 nuget: bump System.IdentityModel.Tokens.Jwt from 6.26.1 to 6.27.0 (#4441)
Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 6.26.1 to 6.27.0.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/commits)

---
updated-dependencies:
- dependency-name: System.IdentityModel.Tokens.Jwt
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-18 02:35:02 +01:00
efb135b74c Clear CPU side data on GPU buffer clears (#4125)
* Clear CPU side data on GPU buffer clears

* Implement tracked fill operation that can signal other resource types except buffer

* Fix tests, add missing XML doc

* PR feedback
2023-02-16 18:28:49 -03:00
a707842e14 Validate dimensions before creating texture (#4430) 2023-02-16 11:16:31 -03:00
a5a9b9bc8b GUI: Small Updater refactor & Set correct permissions on Linux when extracting files (#4315)
* ava: Refactor Updater.cs

Fix typos
Remove unused usings
Rename variables to follow naming scheme

* ava: Set file permissions when extracting update files

* gtk: Apply the same refactor to Updater.cs

* updater: Replace assert with if statement

* updater: Remove await usings again
2023-02-15 22:36:35 +00:00
17078ad929 vulkan: Respect VK_KHR_portability_subset vertex stride alignment (#4419)
* vulkan: Respect VK_KHR_portability_subset vertex stride alignment

We were hardcoding alignment to 4, but by specs it can be any values that
is a power of 2.

This also enable VK_KHR_portability_subset if present as per specs
requirements.

* address gdkchan's comment

* Make NeedsVertexBufferAlignment internal
2023-02-15 08:41:48 +00:00
32450d45de vulkan: Clean up MemoryAllocator (#4418)
This started as an attempt to remove vkGetPhysicalDeviceMemoryProperties
in FindSuitableMemoryTypeIndex (As this could have some overhead and
shouldn't change at runtime) and turned in a little bigger cleanup.
2023-02-15 07:50:26 +01:00
ed7a0474c6 Infra: Issues template cleanup (#4421)
* Infra: Issues template cleanup

* applied
2023-02-14 15:58:57 +01:00
fe9c49949a vulkan: Enforce Vulkan 1.2+ at instance API level and 1.1+ at device level (#4408)
* vulkan: Enforce Vulkan 1.2+ at instance API level and 1.1+ at device level

This ensure we don't end up trying to initialize with anything currently incompatible.

* Address riperiperi's comment
2023-02-13 22:04:55 +00:00
052b23c83c vulkan: Do not call vkCmdSetViewport when viewportCount is 0 (#4406)
This fix validation error "VUID-vkCmdSetViewport-viewportCount-arraylength".
2023-02-13 20:32:20 +00:00
e4f68592c3 Fix partial updates for textures. (#4401)
I was forcing some types of texture to partially update when investigating performance with games that stream in data, and noticed that partially loading texture data was really broken on both backends.

Fixes Vulkan texture set by getting the correct expected size for the texture. Fixes partial upload on both backends for both Texture 2D Array and Cubemap using the wrong offset and uploading to the first layer/level for a handle. 3D might also be affected.

This might fix textures randomly having incorrect data in games that render to it - jumbled in the case of OpenGL, and outdated/black in the case of Vulkan. This case typically happens in UE4 games.
2023-02-12 10:30:26 +01:00
1dcd44b94f Treat NpadIdType < 0 as invalid. Filter invalid SupportedPlayers inside IHidServer.SetSupportedNpadIdType(). (#4377)
Co-authored-by: Logan Stromberg <lostromb@microsoft.com>
2023-02-10 12:37:20 -03:00
61b1ce252f Allow partially mapped textures with unmapped start (#4394) 2023-02-10 11:47:59 -03:00
5f38086f94 Fix SPIR-V when all inputs/outputs are indexed (#4389) 2023-02-09 04:48:25 +01:00
7bae440d3a ObjectiveC Helper Class (#4286)
* `NativeMacOS` Helper Class

* Corrections

* Make CFString IDisposable

* Fix `openURL:`

* `dealloc` metal layer

* Remove releases

* Use NSString

* Update Ryujinx.Ui.Common/Helper/NativeMacOS.cs

Co-authored-by: merry <git@mary.rs>

* Programatically select updates in Finder

* Address feedback

* Feedback

* Ptr

* Fix whoopsie

* Ack suggestions

* Update Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* GDK Suggestions

---------

Co-authored-by: merry <git@mary.rs>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-02-09 04:08:15 +01:00
f1943fd0b6 Log shader compile errors with Warning level (#2617)
* Log shader compile errors with Warning level

These are infrequent enough that I think it's worth dumping any errors into the log. They also keep causing graphical glitches, and the only indication that anything went wrong is a debug log that is never enabled.

* Add maximum length for shader log
2023-02-09 03:50:18 +01:00
ec8d4f3af5 Replace unicorn bindings with Nuget package (#4378)
* Replace unicorn bindings with Nuget package

* Use nameof for ValueSource args

* Remove redundant code from test projects

* Fix wrong values for EmuStart()

Add notes to address this later again

* Improve formatting

* Fix formatting/alignment issues
2023-02-09 02:24:32 +01:00
b3f0978869 Vulkan: Flush command buffers for queries less aggressively (#4387)
The AutoFlushCounter would flush command buffers on any attachment change (write mask or bindings change) if there was a pending query. This is to get query results as soon as possible for draw skips, but it's assuming that a full occlusion query _pass_ happened, that we want to flush it's data before getting onto draws, rather than the queries being randomly interspersed throughout a pass that also draws.

Xenoblade 2 repeatedly switches between performing a samples passed query and outputting to a render target on each draw, and flips the write mask to do so. Flushing the command buffer every 2 draws isn't ideal, so it's best that we only do this if the pattern matches the large block style of occlusion query.

This change makes this flush only happen after a few consecutive query reports. "Consecutive" is interrupted by attachment changes or command buffer flush.

This doesn't really solve the issue where it resets more queries than it uses, it just stops the game doing it as often. I'm not sure of the best way to do that. The cost of resetting could probably be reduced by using query pools with more than one element and resetting in bulk.
2023-02-09 02:03:41 +01:00
f614d2c435 bug_report.yml hotfix 2023-02-09 02:02:00 +01:00
40c9416097 Misc: Update issues form (#4383) 2023-02-09 00:52:43 +00:00
618c8edc79 nuget: bump System.IdentityModel.Tokens.Jwt from 6.26.0 to 6.26.1 (#4384)
Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 6.26.0 to 6.26.1.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/6.26.0...v6.26.1)

---
updated-dependencies:
- dependency-name: System.IdentityModel.Tokens.Jwt
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-08 22:51:07 +01:00
99fc4fa61b Replace BitConverter.ToString(bytes).Replace("-", "") with Convert.ToHexString(bytes) (#4382) 2023-02-08 14:54:58 +01:00
f6d5499a16 Fix some Vulkan validation errors (#4357) 2023-02-08 14:34:22 +01:00
26bf13a65d Limit texture cache based on total texture size (#4350)
* Limit texture cache based on total texture size

* Formatting
2023-02-08 14:19:43 +01:00
96cf242bcf Handle mismatching texture size with copy dependencies (#4364)
* Handle mismatching texture size with copy dependencies

* Create copy and render textures with the minimum possible size

* Only align width for comparisons, assume that height is always exact

* Fix IsExactMatch size check

* Allow sampler and copy textures to match textures with larger width

* Delete texture ChangeSize related code

* Move AdjustSize to TextureInfo and give it a better name, adjust usages

* Fix GetMinimumWidthInGob when minimumWidth > width

* Only update render targets that are actually cleared for clear

Avoids creating textures with incorrect sizes

* Delete UpdateRenderTargetState method that is not needed anymore

Clears now only ever sets the render targets that will be cleared rather than all of them
2023-02-08 08:48:09 +01:00
59755818ef Add ChangeVSyncMode() call to Avalonia render loop (#4379) 2023-02-08 01:28:53 +01:00
f8beeeb7d3 Support safe blit on non-2D textures (#4374)
* Support safe blit on non-2D textures (except multisample)

* Change safe blit with different levels and layers to match CmdBlitImage path

* Remove now unused variables

* Multisample safe blit support
2023-02-07 13:55:59 -03:00
cb250162cb Accelerate NVDEC VIC surface read/write and colorspace conversion with Arm64 HW intrinsics (#4351)
* Accelerate NVDEC VIC surface read/write and colorspace conversion with Arm64 HW intrinsics

* Improve ReadNv12 x86 SSE path
2023-02-07 02:38:54 +00:00
7528f94536 Implement safe depth-stencil blit using stencil export extension (#4356)
* Implement safe depth-stencil blit using stencil export extension

* Delete depth-stencil blit with buffer path
2023-02-06 00:19:31 -03:00
43081c16c4 Insert bitcast for assignment of fragment integer outputs on GLSL (#4369)
* Insert bitcast for assignment of fragment integer outputs on GLSL

* Shader cache version bump
2023-02-05 18:52:57 -03:00
780627e7b0 Implement Account LoadOpenContext (#4359)
* Implement Account LoadOpenContext

* Formatting
2023-02-01 12:52:36 -03:00
9044cb38d1 nuget: bump SharpZipLib from 1.4.1 to 1.4.2 (#4353)
Bumps [SharpZipLib](https://github.com/icsharpcode/SharpZipLib) from 1.4.1 to 1.4.2.
- [Release notes](https://github.com/icsharpcode/SharpZipLib/releases)
- [Changelog](https://github.com/icsharpcode/SharpZipLib/blob/master/docs/Changes.txt)
- [Commits](https://github.com/icsharpcode/SharpZipLib/compare/v1.4.1...v1.4.2)

---
updated-dependencies:
- dependency-name: SharpZipLib
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-31 01:58:25 +01:00
a53cfdab78 Initial Apple Hypervisor based CPU emulation (#4332)
* Initial Apple Hypervisor based CPU emulation implementation

* Add UseHypervisor Setting

* Add basic MacOS support to Avalonia

* Fix initialization

* Fix GTK build

* Fix/silence warnings

* Change exceptions to asserts on HvAddressSpaceRange

* Replace DllImport with LibraryImport

* Fix LibraryImport

* Remove unneeded usings

* Revert outdated change

* Set DiskCacheLoadState when using hypervisor too

* Fix HvExecutionContext PC value

* Address PR feedback

* Use existing entitlements.xml file on distribution folder

---------

Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2023-01-29 08:37:52 -03:00
c7f9962dde converts the templates into forms (#4068)
* Create bug_report.yml

* Update bug_report.yml

* Update bug_report.yml

* Create feature_request.yml

* Update feature_request.yml

* Update feature_request.yml

* Update feature_request.yml

* Update feature_request.yml

* a

* Update missing_cpu_instruction.yml

* Update missing_cpu_instruction.yml

* Update missing_cpu_instruction.yml

* Update missing_cpu_instruction.yml

* b

* addressed some of the feedback

* forget the label

* added missing text inputs

* formatting changes

* dropdown menu

added dropdown menu for os, idk if we will keep this

* addressed feedback

addressed the long overdue feedback, sorry about that

* added markdowns

everything should be addressed now i hope

* game version optional

made game version optional after further feedback

* feature request checkbox
2023-01-27 18:23:55 +00:00
296c4a3d01 Relax Vulkan requirements (#4282)
* Relax Vulkan requirements

* Fix MaxColorAttachmentIndex

* Fix ColorBlendAttachmentStateCount value mismatch for background pipelines

* Change query capability check to check for pipeline statistics query rather than geometry shader support
2023-01-26 18:34:35 -03:00
e7cf4e6eaf Vulkan: Reset queries on same command buffer (#4329)
* Reset queries on same command buffer

Vulkan seems to complain when the queries are reset on another command buffer. No idea why, the spec really could be written better in this regard. This fixes complaints, and hopefully any implementations that care extensively about them.

This change _guesses_ how many queries need to be reset and resets as many as possible at the same time to avoid splitting render passes. If it resets too many queries, we didn't waste too much time - if it runs out of resets it will batch reset 10 more.

The number of queries reset is the maximum number of queries in the last 3 frames. This has been worked into the AutoFlushCounter so that it only resets up to 32 if it is yet to force a command buffer submission in this attachment.

This is only done for samples passed queries right now, as they have by far the most resets.

* Address Feedback
2023-01-24 13:32:56 -03:00
a1a4771ac1 Remove use of GetFunctionPointerForDelegate to get JIT cache function pointer (#4337)
* Remove use of GetFunctionPointerForDelegate to get JIT cache function pointer

* Rename FuncPtr to FuncPointer
2023-01-23 22:37:53 +00:00
2fd819613f SPIR-V: Change BitfieldExtract and BitfieldInsert for SPIRV-Cross (#4336)
* SPIR-V: Change BitfieldExtract and BitfieldInsert types to make Metal MSL compiler happy

* Shader cache version bump
2023-01-23 19:20:40 -03:00
ad6ff6ce99 GUI: Add option to register file types (#4250)
* Add FileAssociationHelper.cs

* Add register file types option to gtk

* Add register file types option to avalonia

* Add Windows support to FileAssociationHelper.cs

* linux: Add uninstall support for file types

* Ignore .glade~ backup files

* Rename Register/Unregister methods

* gtk: Add manage file types submenu

* ava: Add manage file types submenu

* windows: Add uninstall support for file types

* Don't invert uninstall condition (formatting change)

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Add IsTypesRegisteredWindows & Fix Windows install function

* Add AreMimeTypesRegisteredLinux()

* Fix wrong indention

Co-authored-by: AcK77 <acoustik666@gmail.com>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-01-22 17:39:00 +00:00
dc30d94852 Handle parsing of corrupt Config.json and prevent crash on launch (#4309)
* Handle parsing of corrupt Config.json and prevent crash on launch

* Implement a cleaner solution to handle empty json object
2023-01-22 17:04:33 +01:00
4f293f8cbe Arm64: Simplify TryEncodeBitMask and use for constants (#4328)
* Arm64: Simplify TryEncodeBitMask

* CodeGenerator: Use TryEncodeBitMask in GenerateConstantCopy

* Ptc: Bump version
2023-01-22 14:15:49 +00:00
32a1cd83fd AvaloniaKeyboardDriver: Swallow TextInput events to avoid bell (#4320) 2023-01-22 11:21:52 +01:00
e3d0ccf8d5 Allow setting texture data from 1x to fix some textures resetting randomly (#2860)
* Allow setting texture data from 1x to fix some textures resetting randomly

Expected targets:

- Deltarune 1+2
- Crash Team Racing
- Those new pokemon games idk

* Allow scaling of MSAA textures, propagate scale on copy.

* Fix Rebase

Oops

* Automatic disable

* A bit more aggressive

* Without the debug log

* Actually decrement the score when writing.
2023-01-22 02:03:30 +00:00
c14844d12c Ava UI: Various Fixes (#4326)
* Ava UI: Various Fixes

* use WriteAllBytes
2023-01-22 01:42:55 +01:00
7fea26e97e Remove use of reflection on GAL multithreading (#4287)
* Introduce new IGALCommand<T> interface and use it

* Remove use of reflection on GAL multithreading

* Unmanaged constraint
2023-01-22 01:07:43 +01:00
7b7f62c776 nuget: bump Microsoft.CodeAnalysis.Analyzers from 3.3.3 to 3.3.4 (#4310)
* nuget: bump Microsoft.CodeAnalysis.Analyzers from 3.3.3 to 3.3.4

Bumps [Microsoft.CodeAnalysis.Analyzers](https://github.com/dotnet/roslyn-analyzers) from 3.3.3 to 3.3.4.
- [Release notes](https://github.com/dotnet/roslyn-analyzers/releases)
- [Changelog](https://github.com/dotnet/roslyn-analyzers/blob/main/PostReleaseActivities.md)
- [Commits](https://github.com/dotnet/roslyn-analyzers/compare/v3.3.3...v3.3.4)

---
updated-dependencies:
- dependency-name: Microsoft.CodeAnalysis.Analyzers
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fixes warning

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-21 20:04:39 +00:00
423dbc8888 Use volatile read/writes for GAL threading (#4327) 2023-01-21 19:49:55 +00:00
6adf15e479 Implement CSET and CSETP shader instructions (#4318)
* Implement CSET and CSETP shader instructions

* Shader cache version bump

* Fix CC.HI
2023-01-21 12:18:05 -03:00
2747f12591 nuget: bump System.IdentityModel.Tokens.Jwt from 6.25.1 to 6.26.0 (#4322)
Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 6.25.1 to 6.26.0.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/commits)

---
updated-dependencies:
- dependency-name: System.IdentityModel.Tokens.Jwt
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-21 05:24:57 +01:00
a47824f961 Ava UI: Add Notifications and Cleanup (#4275)
* Ava UI: Add Notifications and Cleanup

* Revert notifications on ErrorDialog

* remove unused code from game list views

* Fix cast
2023-01-21 02:57:37 +01:00
8474d52778 Ava UI: Fix string.Format issues in Locale (#4305)
* Ava UI: Fix `string.Format` issues in Locale

* LoacLanguage everytime now

* Apply suggestions from code review

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* fix UpdateAndGetDynamicValue

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2023-01-21 02:06:19 +01:00
Phi
dd7a924596 Catch Profile.json parse to prevent crash on launch (#3393)
* Catch Profile.json parse to prevent crash on launch

* Update Ryujinx.HLE/HOS/Services/Account/Acc/AccountSaveDataManager.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

Co-authored-by: PhiZero <wolkan.craanen@gmail.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-21 01:36:57 +01:00
a76eaf9a9a Ava UI: Add Control+Cmd+F HotKey for Mac OS (#4317)
* Ava UI: Add Control+Cmd+F HotKey for Mac OS

* fix aligned

* Remove comment from code
2023-01-20 22:18:01 +01:00
009e6bcd1b Audio: Implement PCM24 output (#4321) 2023-01-20 21:46:13 +01:00
eb2cc159fa Ava UI: Fixes and cleanup Updater (#4269)
* ava: Fixes and cleanup Updater

* _updateSuccessful
2023-01-20 21:30:21 +01:00
bb89e36fd8 Vulkan: Destroy old swapchain on swapchain recreation (#3889)
* Destroy old swapchain on swapchain recreation

* vkDeviceWaitIdle before DestroySwapchain

* Update Ryujinx.Graphics.Vulkan/Window.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Avoid unsafe code on RecreateSwapchain()

* Destroying old Swapchain on a queue.

* Cleanup and fix on destroying old Swapchain.

* Update Ryujinx.Graphics.Vulkan/Window.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update Ryujinx.Graphics.Vulkan/Window.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update Ryujinx.Graphics.Vulkan/Window.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update Window.cs

Done.

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-01-19 21:31:25 -03:00
de3134adbe Vulkan: Explicitly enable precise occlusion queries (#4292)
The only guarantee of the occlusion query type in Vulkan is that it will be zero when no samples pass, and non-zero when any samples pass. Of course, most GPUs implement this by just placing the # of samples in the result and calling it a day. However, this lax restriction means that GPUs could just report a boolean (1/0) or report a value after one is recorded, but before all samples have been counted.

MoltenVK falls in the first category - by default it only reports 1/0 for occlusion queries. Thankfully, there is a feature and flag that you can use to force compatible drivers to provide a "precise" query result, that being the real # of samples passed.

Should fix ink collision in Splatoon 2/3 on MoltenVK.
2023-01-19 00:30:42 +00:00
36d53819a4 NativeSignalHandler: Fix write flag (#4306)
* NativeSignalHandler: Fix write flag

* address comments
2023-01-19 00:13:17 +00:00
ae4324032a Optimize string memory usage. Use Spans and StringBuilders where possible (#3933)
* Optimize string memory usage. Use ReadOnlySpan<char> and StringBuilder where possible.

* Fix copypaste error

* Code generator review fixes

* Use if statement instead of switch

* Code style fixes

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Another code style fix

* Styling fix

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Styling fix

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
Co-authored-by: Mary-nyan <thog@protonmail.com>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-01-18 22:25:16 +00:00
f449895e6d HOS: Load RomFs by pid (#4301)
We currently loading only one RomFs at a time, which could be wrong if one day we want to load more than one guest at time.
This PR fixes that by loading romfs by pid.
2023-01-18 13:50:42 +00:00
410be95ab6 Fix NRE when disposing AddressSpace with 4KB pages support (#4307) 2023-01-17 14:50:39 +00:00
cff9046fc7 ConfigurationState: Default to Vulkan on macOS (#4299) 2023-01-17 05:32:08 +01:00
86fd0643c2 Implement support for page sizes > 4KB (#4252)
* Implement support for page sizes > 4KB

* Check and work around more alignment issues

* Was not meant to change this

* Use MemoryBlock.GetPageSize() value for signal handler code

* Do not take the path for private allocations if host supports 4KB pages

* Add Flags attribute on MemoryMapFlags

* Fix dirty region size with 16kb pages

Would accidentally report a size that was too high (generally 16k instead of 4k, uploading 4x as much data)

Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2023-01-17 05:13:24 +01:00
43a83a401e Ava UI: Readd some infos to the GameList (#4302) 2023-01-17 04:57:21 +01:00
f0e27a23a5 Add short duration texture cache (#3754)
* Add short duration texture cache

This texture cache takes textures that lose their last pool reference and keeps them alive until the next frame, or until an incompatible overlap removes it. This is done since under certain circumstances, a texture's reference can be wiped from a pool despite it still being in use - though typically the reference will return when rendering the next frame.

While this may slightly increase texture memory usage when quickly going through a bunch of temporary textures, it's still bounded due to the overlap removal rule.

This greatly increases performance in Hyrule Warriors: Age of Calamity. It may positively affect some UE4 games which dip framerate severely under certain circumstances.

* Small optimization

* Don't forget this.

* Add short cache dictionary

* Address feedback

* Address some feedback
2023-01-17 04:39:46 +01:00
e68650237d Ava: Fix Linux Vulkan renderer regression (#4303)
* ava: Fix Linux Vulkan renderer staying transparent

* ava: Minor Renderer cleanup

* Don't supress potential NRE warning

Co-authored-by: Ac_K <Acoustik666@gmail.com>

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-16 03:59:41 +01:00
1faff14e73 UI: Fixes GTK sorting regression of #4294 2023-01-16 03:09:52 +01:00
784cf9d594 Ava UI: Renderer refactoring (#4297)
* Ava UI: `Renderer` refactoring

* Fix Vulkan CreateSurface
2023-01-16 01:14:01 +01:00
64263c5218 UI: Fix applications times (#4294)
* Fix applications times

* Add spaces

* Fix TimeString formatting
2023-01-16 00:11:16 +01:00
065c4e520d Specify image view usage flags on Vulkan (#4283)
* Specify image view usage flags on Vulkan

* PR feedback
2023-01-15 23:12:52 +01:00
139a930407 Implement missing service calls in pm (#4210)
* Implement `GetTitleId`

Fixes #2516

* Null check + Proper result code

* Better comment

* Implement `GetApplicationProcessId`

* Add TODOs

* Update Ryujinx.HLE/HOS/Services/Pm/IInformationInterface.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.HLE/HOS/Services/Pm/IDebugMonitorInterface.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Remove new function from KernelStatic

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-15 22:16:24 +01:00
719dc97bbd Ava UI: TitleUpdateWindow Refactor (#4276)
* Start Refactor

* Dialogue opens

* Changes

* Switch to ListBox

* Fix bugs and stuff

* Fix spacing

* Implement OpenLocation

* Change icon

* Color

* Color

* Remove background

* Make no update the same height

* Fix height and smooth scroll

* Height

* Fix update selection

* Make window smaller

* Add back remove all button

* Make selection more obvious

* Hide selection bar on SaveManager

* Fix autoscroll

* Fix no update not staying selected

* Better file opener

* Fix

* Revert that

* Update Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Log warning

* Update Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-15 11:11:52 +00:00
41bba5310a Audren: Implement polyphase upsampler (#4256)
* Audren: Implement polyphase upsampler

* prefer shifting to modulo

* prefer MathF

* fix nits

* rm ResampleForUpsampler

* oop

* Array20

* nits
2023-01-15 05:20:49 +01:00
8071c8c8c0 Ava UI: Fixes "Hide Cursor on Idle" for Windows (#4266)
* Ava: Fixes "Hide Cursor on Idle" for Windows

* Add check in MouseDriver and reduce the time of idling

* Fix linux error

* Change idle time everywhere for consistencies
2023-01-15 01:05:44 +01:00
b402b4e7f6 Change GetPageSize to use Environment.SystemPageSize (#4291)
* Change GetPageSize to use Environment.SystemPageSize

* Fix PR comment
2023-01-14 15:37:04 -03:00
93df366b2c Fix texture flush from CPU WaitSync regression on OpenGL (#4289) 2023-01-14 11:23:57 -03:00
cd3a15aea5 Fix NRE when MemoryUnmappedHandler is called for a destroyed channel (#4285) 2023-01-14 00:16:06 -03:00
070136b3f7 Fix texture modified on CPU from GPU thread after being modified on GPU not being updated (#4284) 2023-01-13 23:46:45 -03:00
08ab47c6c0 Update Program.cs 2023-01-13 07:56:41 +01:00
85faa9d8fa Revert "Relax Vulkan requirements (#4228)" (#4279)
This reverts commit dca5b14493.
2023-01-13 06:04:59 +00:00
dca5b14493 Relax Vulkan requirements (#4228) 2023-01-13 06:09:48 +01:00
4d2c8e2a44 Prepo: Fix SaveSystemReport* IPC definitions (#4278)
* Prepo: Fix SaveSystemReport IPC definitions

* Follow original code

* Fix args index in HipcGenerator

* Addresses feedback

* oops
2023-01-13 01:50:14 +01:00
8fa248ceb4 Vulkan: Add workarounds for MoltenVK (#4202)
* Add MVK basics.

* Use appropriate output attribute types

* 4kb vertex alignment, bunch of fixes

* Add reduced shader precision mode for mvk.

* Disable ASTC on MVK for now

* Only request robustnes2 when it is available.

* It's just the one feature actually

* Add triangle fan conversion

* Allow NullDescriptor on MVK for some reason.

* Force safe blit on MoltenVK

* Use ASTC only when formats are all available.

* Disable multilevel 3d texture views

* Filter duplicate render targets (on backend)

* Add Automatic MoltenVK Configuration

* Do not create color attachment views with formats that are not RT compatible

* Make sure that the host format matches the vertex shader input types for invalid/unknown guest formats

* FIx rebase for Vertex Attrib State

* Fix 4b alignment for vertex

* Use asynchronous queue submits for MVK

* Ensure color clear shader has correct output type

* Update MoltenVK config

* Always use MoltenVK workarounds on MacOS

* Make MVK supersede all vendors

* Fix rebase

* Various fixes on rebase

* Get portability flags from extension

* Fix some minor rebasing issues

* Style change

* Use LibraryImport for MVKConfiguration

* Rename MoltenVK vendor to Apple

Intel and AMD GPUs on moltenvk report with the those vendors - only apple silicon reports with vendor 0x106B.

* Fix features2 rebase conflict

* Rename fragment output type

* Add missing check for fragment output types

Might have caused the crash in MK8

* Only do fragment output specialization on MoltenVK

* Avoid copy when passing capabilities

* Self feedback

* Address feedback

Co-authored-by: gdk <gab.dark.100@gmail.com>
Co-authored-by: nastys <nastys@users.noreply.github.com>
2023-01-13 01:31:21 +01:00
30862b5ffd ava: Reorder settings of Resolution Scaler (#4270) 2023-01-13 00:07:53 +01:00
9f57747c57 Ava UI: Various Fixes (#4268)
* Fix saves disappearing

* Better size formatter

* Move TextBox alignment fix to Styles

* Fix bug

* Left align

* Add border

* Update Ryujinx.Ava/UI/Models/SaveModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Models/SaveModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Models/SaveModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Whitespace

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-12 12:23:24 +00:00
fe29a2ff6e Ava UI: Settings Adjustments (#4273)
* Visual adjustments

* Match border to rest of app

* Fix overlapping controls

* Fix

* Fix
2023-01-12 12:09:32 +00:00
e9a173e00c Ptc: Check process architecture (#4272) 2023-01-12 07:50:45 +00:00
a11784fcbf Arm64: Cpu feature detection (#4264)
* Arm64: Cpu feature detection

* Ptc: Add Arm64 feature info

* nits

* simplify CheckSysctlName

* restore some macos flags

* feedback
2023-01-12 08:05:18 +01:00
fd36c8deca lm: Handle Tail flag in LogPacket (#4274)
* lm: Handle TailFlag in LogPacket

* Addresses feedback
2023-01-12 07:42:05 +01:00
70638340b3 Ava UI: Move Ava logging to Logger.Debug (#4255)
* Ava: Move Ava logging to Logger.Debug

Since #4231 we currently redirect Avalonia logs to our Logger, which is pretty nice. But since it uses our Logging level too, it now leads to a massive flood in our Log files.
To avoid that, I've included all `AvaLogLevel` to the log message, and make all Ava Logs using `Logger.Debug`.

* Logs errors to Error and other to Debug

* missing level

* keep var
2023-01-11 23:27:26 +01:00
4b495f3333 Ava UI: Fixes PerformanceCheck condition (#4271) 2023-01-11 20:47:15 +00:00
934b5a64e5 Ava GUI: User Profile Manager + Other Fixes (#4166)
* Fix redundancies

* Add back elses

* Loading Screen fixes

* Redesign User Profile Manager

- Backported long selection bar in Grid/List view not working
- Backported UserSelector is jank

* Fix SelectionIndicator

* Fix DataType

* Fix SaveManager bug

* Remove debug log

* Load saves on UIThread

* Reduce UI thread blocking

* Fix locale keys

* Use block namespaces

* Fix close button width

* Make UserProfile ordering consistent

* Alphabetical order

* Adjust layout, remove green circle for blue selector

* Fix some inconsistencies

* Fix no inital selected profile

* Adjust appearance of edit button

* Adjust SaveManager

* Remove redundant warning dialog

* Make firmware avatar selector clearer

* View redesign again :hero_depressed:

* Consistency adjustments

* Adjust margins

* Make `UserProfileImageSelector` consistent

* Make `UserFirmwareAvatarSelector` consistent

* Fix long grid view selector

* Switch case

* Remove long selection bar

Handled in #4178

* Consistency

* Started dialog titles

* Fixes

* Remaining titles

* Update Ryujinx.Ava/UI/Controls/NavigationDialogHost.axaml

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Fix build

* Hide UserRecoverer if no LostProfiles are found

* UserEditor Avatar Placeholder

* Watermark + locale adjustment

* Border radius

* Remove unnecessary styles

* Fix firmware avatar image order

* Cleanup `ColorPickerButton`

* Make `UserId` copy/paste able

* Make `FirmwareAvatarSelector` 6 images wide

* Make selection bar better

* Unsaved changes dialogue

* Fix indentation

* Remove extra check

* Address suggestions

* Reorganise

- Remove unused views
- Rename views to match convention
- Fix weird namespacing

* Update Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* UserRecovererView empty placeholder

* Update Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/User/UserRecovererView.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Models/UserProfile.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Controls/NavigationDialogHost.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Controls/NavigationDialogHost.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Remove AddModel

* Update Ryujinx.Ava/Assets/Locales/en_US.json

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Fix bug

Co-authored-by: Mary-nyan <thog@protonmail.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-11 06:20:19 +01:00
cee667b491 Ava: Fixes Update count in heading (#4265) 2023-01-11 05:39:25 +01:00
94a64f2aea Remove textures from cache on unmap if not mapped and modified (#4211) 2023-01-11 01:53:56 +00:00
2355c2af62 ava: Generate Locale menu automatically (#4243)
Currently in `MenuMainBarView.axaml` we list all available languages and hardcode the language name with the language key.
It's a bit bad beause if we want to add a new language, we have to edit the `csproj` and the `axaml` with the translated language name and the language code.
I've put all translations in their respective locale files, add code into `MainMenuBarView` constructor to generate the menu automatically. Now we just have to edit the `csproj` if we want to add a new language.
2023-01-11 01:29:22 +01:00
5e0f8e8738 Implement JIT Arm64 backend (#4114)
* Implement JIT Arm64 backend

* PPTC version bump

* Address some feedback from Arm64 JIT PR

* Address even more PR feedback

* Remove unused IsPageAligned function

* Sync Qc flag before calls

* Fix comment and remove unused enum

* Address riperiperi PR feedback

* Delete Breakpoint IR instruction that was only implemented for Arm64
2023-01-10 19:16:59 -03:00
d16288a2a8 Set LSApplicationCategoryType to games (#4257)
https://developer.apple.com/documentation/bundleresources/information_property_list/lsapplicationcategorytype
Makes it auto-add to the macOS Launchpad games folder
2023-01-10 21:49:46 +00:00
600f86dc7b Fix context menu locales (#4242) 2023-01-10 19:15:15 +01:00
7210c17c5e misc: Enforce LF (#4253)
Because we are building everything on Windows for release at the moment,
git default line ending to CRLF causing issues when packing the
Ryujinx.sh script.

This addresses this by enforcing all files to use LF via .gitattributes.
2023-01-10 19:00:14 +01:00
a16854e55a ava: Cleanup AppHost (#4240)
* ava: Cleanup AppHost

This PR cleaned up the AppHost file a bit (adding the infamous extra spaces to improve readability), resorting private vars, remove useless vars, and improve the code here and there, like the AudioBackend check.

Co-Authored-By: gdkchan <5624669+gdkchan@users.noreply.github.com>

* Remove 'renderer"

* Revert currentTime

* revert if condition

Co-authored-by: gdkchan <5624669+gdkchan@users.noreply.github.com>
2023-01-10 18:45:55 +01:00
3e455a90a1 Ava: Add missing null check to ContentDialogHelper.ShowAsync() (#4248)
* ava: Add missing null check to ContentDialogHelper.ShowAsync()

* Replace "is not" with != operator

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-01-10 09:22:25 +01:00
e4413542b2 Add command line arguments to override docked mode (#4239)
* Add command line args for docked mode

* Apply suggestions from code review

Co-authored-by: Ac_K <Acoustik666@gmail.com>

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-10 00:59:23 +01:00
8c720783f5 linux: Fix packaging step for CI & Add Ryujinx.Headless.SDL2 to Ryujinx.sh (#4249) 2023-01-09 23:45:46 +00:00
8734ea9dd4 Linux: Add Avalonia detection to Ryujinx.sh (#4224)
* Revert "ava: Fix regression caused by #4013 (#4222)"

This reverts commit b9f2a96595.

* linux: Detect Ryujinx.Ava and don't rename the Ryujinx.Ava assembly
2023-01-09 22:58:51 +01:00
c586e6d2b7 Replace tabs with spaces across the project (#4244)
* Replace tabs with spaces across the project

* Include AXAML files too
2023-01-09 22:58:29 +01:00
3a4eeb77fe headless: Change window icon size to 48x48 (#4247) 2023-01-09 18:02:41 +00:00
51b3953cfc [Headless] Add missing arguments & Fix typos (#4193)
* headless: Fix typos in command line options

* Remove nullable from command line options

Add EnableMacroHLE option
Add HideCursorOnIdle option

* headless: Adjust enable-ptc help text

* headless: Use switch statement instead of if-else chain

* headless: Improve formatting for long constructors

* headless: Remove discards from SDL_ShowCursor()

* headless: Add window icon

* Fix hiding cursor on idle

At least on Wayland, SDL2 doesn't produce any mouse motion events.

* Add new command line args: BaseDataDir and UserProfile

* headless: Read icon from embedded resource

* headless: Skip SetWindowIcon() on Windows if dll isn't present

* headless: Fix division by zero

* headless: Fix command line options not working correctly

* headless: Fix crash when viewing command line options

* headless: Load window icon bmp from memory

* Add comment to the workaround for SDL_LoadBMP_RW

* headless: Enable logging to file by default

* headless: Add 3 options for --hide-cursor

Replaces --disable-hide-cursor-on-idle
2023-01-09 04:55:37 +01:00
610eecc1c1 ava: Fixes regressions from refactoring (#4237)
* ava: Fix regressions from #4178

* Remove duplicated code

* real fix for right click menu

Co-Authored-By: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com>

* Remove ContentDialogOverlay

Co-authored-by: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com>
2023-01-09 03:37:20 +00:00
492056abf6 Ava: Make Avalonia use our logging system (#4231)
* Ava: Make Avalonia use our logging system

* LoggerAdapter: Address review comments

* Update Ryujinx.Common/Logging/LogClass.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-09 04:32:20 +01:00
ee6e682ab4 Fix selection bar (#4236) 2023-01-09 03:36:11 +01:00
6f60e102a2 HIPC: Fix reply possibly also receiving one request (#4232) 2023-01-08 15:34:49 -03:00
eeb2af9953 Ava GUI: MainWindow Refactor (#4178)
* Fix redundancies

* Add back elses

* `MainWindow` Refactor

* Switch commands to `ReflectionBinding`

Not required in Ava 11

* Update Ryujinx.Ava/AppHost.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/AppHost.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/AppHost.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/AppHost.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/AppHost.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/AppHost.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Resolve issues

* Remove Ava 11 Fix

* Update Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Fix whitespace + other suggestions

* Move Vsync colours to `Styles.xaml`

* Remove catch all

* Use `switch` instead of `if`

* Update locale keys

* Use block-scoped namespaces

* Fix improper Ava api usage then

* Static PTC

* Fix `GridItemSelectorSize` with `ShowNames`

* Update for new About Window

* Add back search fix

Co-authored-by: Ac_K <Acoustik666@gmail.com>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2023-01-08 18:46:25 +01:00
550747eac6 Horizon: Impl Prepo, Fixes bugs, Clean things (#4220)
* Horizon: Impl Prepo, Fixes bugs, Clean things

* remove ToArray()

* resultCode > status

* Remove old services

* Addresses gdkchan's comments and more cleanup

* Addresses Gdkchan's feedback 2

* Reorganize services, make sure service are loaded before guest

Co-Authored-By: gdkchan <5624669+gdkchan@users.noreply.github.com>

* Create interfaces for lm and sm

Co-authored-by: gdkchan <5624669+gdkchan@users.noreply.github.com>
2023-01-08 12:13:39 +00:00
3ffceab1fb MainWindow: Vertically center SearchBox TextPresenter (#4223) 2023-01-07 16:01:53 +00:00
b9f2a96595 ava: Fix regression caused by #4013 (#4222)
Avalonia seems to not like when the artifact doesns't match the root namespace...

Address that by moving the binary to "Ryujinx" like we do on macOS build.
2023-01-07 12:24:21 +01:00
cbaa845f5d Include a start.sh file with correct launch options (#4013)
* Include reference to start.sh to be bundled

* Add start.sh

* Fix silly mistake I made on windows-x64

* ... I cannot read properly

* Make same changes for avalonia csproj

* Remove notice from start.sh

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Update Ryujinx/Ryujinx.csproj

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Update Ryujinx.Ava/Ryujinx.Ava.csproj

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Update distribution/linux/start.sh

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update distribution/linux/start.sh

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/Ryujinx.Ava.csproj

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.csproj

* Update Ryujinx.Ava.csproj

* Rename start.sh to Ryujinx.sh

* Update Ryujinx.csproj

* Update Ryujinx.Ava.csproj

* Update Ryujinx.Ava.csproj

* Update Ryujinx.Ava/Ryujinx.Ava.csproj

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Add `GDK_BACKEND` variable

* Update Ryujinx.Ava.csproj

* Update Program.cs

* Update Program.cs

* Update Ryujinx.sh

* Update Program.cs

* linux: Register mime types on launch

* Add DOTNET_EnableAlternateStackCheck=1 to desktop file

* linux: Add exclusion for RegisterMimeTypes for flathub builds

* Update logo path

* Cleanup Ryujinx.sh

* Fix typo in ReleaseInformation

* gha: Fix permissions for linux release binaries

* ava: Rename output assembly to Ryujinx

* Update mime database after installing new types

Wait until logging is available before registering mime types

* Copy mime types to output directory

Co-authored-by: Mary-nyan <thog@protonmail.com>
Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2023-01-07 09:06:13 +01:00
9e2681f2d7 Ava GUI: AboutWindow Refactor (#4196)
* Start `AboutWindow` refactor

* Redesign

* Update logos + ViewModel

* Fix GTK

* Cleanup usings

* Fix mismatched font size

* Update LocaleKeys

* Block scoped namespace

* Fix appearence on German

* Update Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Move version number up

* Move see all contributors button left

* Add a couple `\n`

* Tooltips

* Layout fix

* Update Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-01-07 01:29:18 +01:00
81fae0d1a6 [hipc] Fix 'Unexpected result code Success returned' in Reply() (#4215)
* horizon: Add AbortOnFailureUnless()

* hipc: Replace AbortUnless() with AbortOnFailureUnless() in Reply()
2023-01-07 00:57:21 +01:00
38519f3b9a Ava GUI: SettingsWindow Refactor (#4177)
* Fix redundancies

* Add back elses

* Settings Refactor

* Fix Disposal functions

* Use `ReflectionBinding` instead of redundant funcs

* Ac_K suggestions

* Update Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update locale keys

* Update Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Use block-scoped namespaces

* Fix typo

* Make `TimeZone` internal again

Co-authored-by: Ac_K <Acoustik666@gmail.com>
Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2023-01-07 00:35:21 +01:00
7f27aabbd0 chore: Update Ryujinx.SDL2-CS to 2.26.1 (#4199) 2023-01-06 17:52:25 +01:00
e876c43ce9 Misc; Remove duplicated entries and clean locale csproj (#4209) 2023-01-05 04:30:55 +01:00
8639245533 hle: Add safety measure around overflow in ScheduleFutureInvocation
Fix crash on Linux since 08831eecf7.
2023-01-05 01:55:27 +01:00
d6b86a6629 Readd Ryujinx.Ui.LocaleGenerator removed in #4188 (again) 2023-01-05 00:23:17 +01:00
8f2b7b5b8e Readd Ryujinx.Ui.LocaleGenerator removed in #4188 2023-01-05 00:20:47 +01:00
fc4b7cba2c Make PPTC state non-static (#4157)
* Make PPTC state non-static

* DiskCacheLoadState can be null
2023-01-05 00:01:44 +01:00
08831eecf7 IPC refactor part 3+4: New server HIPC message processor (#4188)
* IPC refactor part 3 + 4: New server HIPC message processor with source generator based serialization

* Make types match on calls to AlignUp/AlignDown

* Formatting

* Address some PR feedback

* Move BitfieldExtensions to Ryujinx.Common.Utilities and consolidate implementations

* Rename Reader/Writer to SpanReader/SpanWriter and move to Ryujinx.Common.Memory

* Implement EventType

* Address more PR feedback

* Log request processing errors since they are not normal

* Rename waitable to multiwait and add missing lock

* PR feedback

* Ac_K PR feedback
2023-01-04 23:15:45 +01:00
c6a139a6e7 New Crowdin updates (#3985)
* New translations en_US.json (French)

* New translations en_US.json (Portuguese, Brazilian)

* New translations en_US.json (French)

* New translations en_US.json (Portuguese, Brazilian)

* Delete fr_FR.json

* Delete pt_BR.json

* New translations en_US.json (French)

* New translations en_US.json (Spanish)

* New translations en_US.json (German)

* New translations en_US.json (Greek)

* New translations en_US.json (Italian)

* New translations en_US.json (Japanese)

* New translations en_US.json (Korean)

* New translations en_US.json (Polish)

* New translations en_US.json (Russian)

* New translations en_US.json (Turkish)

* New translations en_US.json (Ukrainian)

* New translations en_US.json (Chinese Simplified)

* New translations en_US.json (Chinese Traditional)

* New translations en_US.json (Portuguese, Brazilian)

* New translations en_US.json (German)
2023-01-04 22:44:51 +01:00
02714a1291 Avalonia - Add source generator for locale items (#3999)
* Add source generator for locale keys

* use locale keys in Ui subdir
2023-01-03 19:45:08 +01:00
09c9686498 misc: Use official names for NVDEC registers (#4192)
* misc: Uses official names for NVDEC registers

* Address gdkchan's comment

* Address comments
2023-01-02 14:48:46 +00:00
b6614c6ad5 chore: Update tests dependencies (#3978)
* chore: Update tests dependencies

* Apply TSR Berry suggestion to add a GC.SuppressFinalize in MemoryBlock.cs

* Ensure we wait for the test thread to be dead on PartialUnmap

* Use platform attribute for os specific tests

* Make P/Invoke methods private

* Downgrade NUnit3TestAdapter to 4.1.0

* test: Disable warning about platform compat for ThreadLocalMap()

Co-authored-by: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
2023-01-01 17:35:29 +01:00
b1d4b174a6 fix typo in left joycon sl binding (#4195) 2023-01-01 15:46:02 +01:00
2b23463daa Filter hidden game files from the Game List (#4051)
* Filter “._” files from the game list

* Filter all hidden files from the game list

* Fix style

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* merge OR expression into a pattern

* migrate from GetFiles/Directories to Enumerate

* Remove GetFilesInDirectory()

* Update Ryujinx.Ui.Common/App/ApplicationLibrary.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* add error handeling

* code cleanup

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2022-12-29 16:52:30 +01:00
9dfe81770a Use vector outputs for texture operations (#3939)
* Change AggregateType to include vector type counts

* Replace VariableType uses with AggregateType and delete VariableType

* Support new local vector types on SPIR-V and GLSL

* Start using vector outputs for texture operations

* Use vectors on more texture operations

* Use vector output for ImageLoad operations

* Replace all uses of single destination texture constructors with multi destination ones

* Update textureGatherOffsets replacement to split vector operations

* Shader cache version bump

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2022-12-29 16:09:34 +01:00
52c115a1f8 HLE: Add basic stubs to get Labo VR booting to title screen. (#4007)
* HLE: Add basic stubs to get Labo VR booting to title screen.

* Address code review

* Apply suggestions from code review (pt. 2)

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Apply suggestions from code review (pt. 3)

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Formatting: final batch?

Co-authored-by: Ac_K <Acoustik666@gmail.com>
Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Address last? bit of formatting

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2022-12-29 15:57:35 +01:00
e20abbf9cc Vulkan: Don't flush commands when creating most sync (#4087)
* Vulkan: Don't flush commands when creating most sync

When the WaitForIdle method is called, we create sync as some internal GPU method may read back written buffer data. Some games randomly intersperse compute dispatch into their render passes, which result in this happening an unbounded number of times depending on how many times they run compute.

Creating sync in Vulkan is expensive, as we need to flush the current command buffer so that it can be waited on. We have a limited number of active command buffers due to how we track resource usage, so submitting too many command buffers will force us to wait for them to return to the pool.

This PR allows less "important" sync (things which are less likely to be waited on) to wait on a command buffer's result without submitting it, instead relying on AutoFlush or another, more important sync to flush it later on.

Because of the possibility of us waiting for a command buffer that hasn't submitted yet, any thread needs to be able to force the active command buffer to submit. The ability to do this has been added to the backend multithreading via an "Interrupt", though it is not supported without multithreading.

OpenGL drivers should already be doing something similar so they don't blow up when creating lots of sync, which is why this hasn't been a problem for these games over there.

Improves Vulkan performance on Xenoblade DE, Pokemon Scarlet/Violet, and Zelda BOTW (still another large issue here)

* Add strict argument

This is technically a separate concern from whether the sync is a host syncpoint.

* Remove _interrupted variable

* Actually wait for the invoke

This is required by AMD GPUs, and also may have caused some issues on other GPUs.

* Remove unused using.

* I don't know why it added these ones.

* Address Feedback

* Fix typo
2022-12-29 15:39:04 +01:00
76671d63d4 Ava GUI: Restructure Ryujinx.Ava (#4165)
* Restructure `Ryujinx.Ava`

* Stylistic consistency

* Update Ryujinx.Ava/UI/Controls/UserEditor.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Controls/UserEditor.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Controls/UserSelector.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Controls/SaveManager.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Controls/SaveManager.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/ViewModels/UserProfileViewModel.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/ViewModels/UserProfileViewModel.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Fix redundancies

* Remove redunancies

* Add back elses

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2022-12-29 15:24:05 +01:00
3d1a0bf374 [Headless] Fix for not receiving any SDL events on Linux (#4182)
* headless: Fix SDL events not working

* Add nuget.config
2022-12-29 15:09:18 +01:00
c20f3fbebd haydn: Add support for PCMFloat, PCM32 and PCM8 conversions (#4100)
* haydn: Add support for PCMFloat, PCM32 and PCM8 conversions

This adds support in the compatibility layer for other sample format
than PCM16.

This should help extends compatibility with soundio on devices that
doesn't expose PCM16.

I ommited PCM24 conversion for now as it's not simplest of all.

* Address TSRBerry's comment

* Address comments

* Fix conversion issue and clean up saturation usage

* Revert saturation changes

* Address gdkchan's comment
2022-12-28 19:34:30 -03:00
0d3b82477e Use new ArgumentNullException and ObjectDisposedException throw-helper API (#4163) 2022-12-27 20:27:11 +01:00
470be03c2f GPU: Add fallback when 16-bit formats are not supported (#4108)
* Add conversion for 16 bit RGBA formats (not supported in Rosetta)

* Rebase fix

Rebase fix

* Forgot to remove this

* Fix RGBA16 format conversion

* Add RGBA4 -> RGBA8 conversion

* Handle host stride alignment

* Address Feedback Part 1

* Can't count

* Don't zero out rgb when alpha is 0

* Separate RGBA4 and 5-bit component formats

Not sure of a better way to name them...

* Add A1B5G5R5 conversion

* Put this in the right place.

* Make format naming consistent for capabilities

* Change method names
2022-12-26 15:50:27 -03:00
c963b3c804 Added Generic Math to BitUtils (#3929)
* Generic Math Update

Updated Several functions in Ryujinx.Common/Utilities/BitUtils to use generic math

* Updated BitUtil calls

* Removed Whitespace

* Switched decrement

* Fixed changed method calls.

The method calls were originally changed on accident due to me relying too much on intellisense doing stuff for me

* Update Ryujinx.Common/Utilities/BitUtils.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2022-12-26 14:11:05 +00:00
a4fdfb5f94 bsd::RecvFrom: verify output buffer size before writing socket address (#4135)
* bsd::RecvFrom: Ryujinx does not verify output buffer size before writing socket address

* Calculate the size of BsdSockAddr

* use bsdSockAddr variable

* Update Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Update Ryujinx.HLE/HOS/Services/Sockets/Bsd/Types/BsdSockAddr.cs

Co-authored-by: Mary-nyan <thog@protonmail.com>

* set errno to ENOMEM in case we can't write the address to memory

* Update Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs

Co-authored-by: Mary-nyan <thog@protonmail.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2022-12-26 13:49:26 +00:00
37d27c4c99 Some minor cleanups and optimizations (#4174)
* Replace Array.Clear(x, 0, x.Length) with Array.Clear(x)

* Use DateTime.UnixEpoch field

* Replace SHA256.ComputeHash calls with static SHA256.HashData call

More performant and avoids the need to initialize a SHA256 instance.
2022-12-24 14:30:39 -03:00
f906eb06c2 Implement a software ETC2 texture decoder (#4121)
* Implement a software ETC2 texture decoder

* Fix output size calculation for non-2D textures

* Address PR feedback
2022-12-21 20:39:58 -03:00
219f63ff4e Fix CPU FCVTN instruction implementation (slow path) (#4159)
* Fix CPU FCVTN instruction implementation (slow path)

* PPTC version bump
2022-12-21 23:05:58 +00:00
1cca3e99ab GPU: Force rebind when pool changes (#4129) 2022-12-21 17:35:28 -03:00
Ccl
55a23e5ec8 make UI display correct content in Chinese (#4155) 2022-12-21 17:20:37 -03:00
479d1fd8b0 hle: Handle GPU profiler and debugger device path correctly (#4138)
This fix a warning on "慟哭そして…" by handling correctly the debug mode
flag.

When debug mode isn't enabled, opening /dev/nvhost-dbg-gpu or /dev/nvhost-prof-gpu should fail with a not implemented error code.

This implement this behaviour and also define stubbed interfaces for
completness.
2022-12-21 18:23:11 +00:00
cb70e7bb30 Fix DrawArrays vertex buffer size (#4141) 2022-12-21 19:08:12 +01:00
c200a7b7c6 ARMeilleure: Hash _data pointer instead of value for Operand (#4156)
I noticed a weirdly high cost for dictionary accesses from MarkLabel etc. Turns out that the hash code was always the same for labels, so the whole point of having a dictionary was missed and it was putting everything in the same bucket. I made it always hash the _data pointer as that's a good source of identifiable and "random" data.
2022-12-21 02:28:18 +01:00
6268170a10 fix sw kbd row collision (#4144) 2022-12-19 15:09:36 -03:00
ee0f9b03a4 Eliminate zero-extension moves in more cases on 32-bit games (#4140)
* Eliminate zero-extension moves in more cases on 32-bit games

* PPTC version bump

* Revert X86Optimizer changes
2022-12-19 14:45:58 -03:00
f93c5f006a Revert "ARMeilleure: Add initial support for AVX512(EVEX encoding) (#3663)" (#4145)
This reverts commit 295fbd0542.
2022-12-18 20:21:10 -03:00
295fbd0542 ARMeilleure: Add initial support for AVX512(EVEX encoding) (#3663)
* ARMeilleure: Add AVX512{F,VL,DQ,BW} detection

Add `UseAvx512Ortho` and `UseAvx512OrthoFloat` optimization flags as
short-hands for `F+VL` and `F+VL+DQ`.

* ARMeilleure: Add initial support for EVEX instruction encoding

Does not implement rounding, or exception controls.

* ARMeilleure: Add `X86Vpternlogd`

Accelerates the vector-`Not` instruction.

* ARMeilleure: Add check for `OSXSAVE` for AVX{2,512}

* ARMeilleure: Add check for `XCR0` flags

Add XCR0 register checks for AVX and AVX512F, following the guidelines
from section 14.3 and 15.2 from the Intel Architecture Software
Developer's Manual.

* ARMeilleure: Increment InternalVersion

* ARMeilleure: Remove redundant `ReProtect` and `Dispose`, formatting

* ARMeilleure: Move XCR0 procedure to GetXcr0Eax

* ARMeilleure: Add `XCR0` to `FeatureInfo` structure

* ARMeilleure: Utilize `ReadOnlySpan` for Xcr0 assembly

Avoids an additional allocation

* ARMeilleure: Formatting fixes
2022-12-18 16:46:13 -03:00
d7310d7a1c hle: Fix wrong conversion in UserPresence.ToString (#4142)
This fixes an error from #3805 that caused a wrong conversion of ``AppKeyValueStorage`` to string.
As that information isn't really relevant without appropriate parsing, it was removed from ``ToString``.

This should get ride of "bell warning" in Mario Kart 8 when entering Time Trials.
2022-12-18 14:23:19 +00:00
8c50943a2e nuget: bump Microsoft.NET.Test.Sdk from 17.4.0 to 17.4.1 (#4137)
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.4.0 to 17.4.1.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.4.0...v17.4.1)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-17 01:19:04 +01:00
ec4cd57ccf Implement another non-indexed draw method on GPU (#4123) 2022-12-16 12:06:38 -03:00
5a085cba0f GPU: Fix layered attachment write (#4131)
Fixes a regression caused by #4003 where the code that writes `_vtgWritesRtLayer` was removed, breaking the crowd in mario strikers.
2022-12-16 09:40:01 -03:00
1a1d33a018 ava: Fix invisible swkbd applet on Linux (#4130) 2022-12-16 02:40:55 +01:00
0fbcd630bc Replace DllImport usage with LibraryImport (#4084)
* Replace usage of `DllImport` with `LibraryImport`

* Mark methods as `partial`

* Marshalling

* More `partial` & marshalling

* More `partial` and marshalling

* More partial and marshalling

* Update GdiPlusHelper to LibraryImport

* Unicorn

* More Partial

* Marshal

* Specify EntryPoint

* Specify EntryPoint

* Change GlobalMemoryStatusEx to LibraryImport

* Change RegisterClassEx to LibraryImport

* Define EntryPoints

* Update Ryujinx.Ava/Ui/Controls/Win32NativeInterop.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Move return mashal

* Remove calling convention specification

* Remove calling conventions

* Update Ryujinx.Common/SystemInfo/WindowsSystemInfo.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update Ryujinx/Modules/Updater/Updater.cs

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Update Ryujinx.Ava/Modules/Updater/Updater.cs

Co-authored-by: Mary-nyan <thog@protonmail.com>

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
Co-authored-by: Mary-nyan <thog@protonmail.com>
2022-12-15 18:07:31 +01:00
f4d731ae20 Fix NRE when loading Vulkan shader cache with Vertex A shaders (#4124) 2022-12-15 17:52:12 +01:00
8ac53c66b4 Remove Half Conversion (#4106)
* Remove HalfConversion

* Update `CodeGenVersion`
2022-12-14 21:13:23 -03:00
0f50de72be Vulkan: enable VK_EXT_custom_border_color features (#4116)
* Vulkan: enable VK_EXT_custom_border_color features

radv only create the border color bo if this feature is enabled, so it crashed when creating samplers with custom border colors
Fixes #4072
Fixes #3993

* Address gdkchan's comment

Co-authored-by: Mary <mary@mary.zone>
2022-12-14 20:53:33 -03:00
df758eddd1 Bsd: Add support for dns_mitm (#4102)
* bsd: Add dns_mitm from Atmosphère

related AMS files:
- https://github.com/Atmosphere-NX/Atmosphere/blob/master/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_resolver_impl.cpp
- https://github.com/Atmosphere-NX/Atmosphere/blob/master/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_host_redirection.cpp

* Remove debug logging and adjust redirect message

* Improve formatting

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Replace Initialize with instance property

* bsd: dns_mitm - Ignore empty lines

* bsd: Mark _mitmHostEntries as readonly

* bsd: Initialize Aliases when returning IpHostEntry

Fixes NullReferenceException

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2022-12-12 18:04:08 +01:00
5f32a8ed94 misc: Update to Ryujinx.Graphics.Nvdec.Dependencies 5.0.1-build13 (#4097)
Fix packaging issues on macOS related to an unsatisfied dependency on libX11
2022-12-12 16:19:46 +01:00
535fbec675 Use NuGet Central Package Management to manage package versions solution-wise (#4095) 2022-12-12 16:03:10 +01:00
6fe88115a3 misc: Some fixes to the updaters (#4092)
This was meant to be only an upgrade of how we set unix permission in
the updater to use .NET 7 new APIs, but I end up finding bugs along the
way.

Changelog:
- Remove direct usage of chmod to use File.SetUnixFileMode.
- Fix command line being broken when updating (#3744) but on
  Ryujinx.Ava.
- Makes Ryujinx.Ava updater fallback to Ryujinx executable if current
  name isn't found.
- Make permission setter function more generic.
2022-12-12 15:17:22 +01:00
475fa4d390 Fix "UI" abbreviation being miscapitalized (#4093) 2022-12-12 15:11:55 +01:00
edf7e628ca Use method overloads that support trimming. Mark some types to be trimming friendly (#4083)
* Use method overloads that support trimming. Mark some types to be trimming friendly

* Use generic version of marshalling method
2022-12-12 15:10:05 +01:00
ba5c0cf5d8 Bsd: Implement Select (#4017)
* bsd: Add gdkchan's Select implementation

Co-authored-by: TSRBerry <20988865+tsrberry@users.noreply.github.com>

* bsd: Fix Select() causing a crash with an ArgumentException

.NET Sockets have to be used for the Select() call

* bsd: Make Select more generic

* bsd: Adjust namespaces and remove unused imports

* bsd: Fix NullReferenceException in Select

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2022-12-12 14:59:31 +01:00
403e67d983 audio: Rewrite SoundIo bindings (#4088)
* audio: Rewrite SoundIo bindings

This rewrite SoundIo bindings to be safer and not a pedantic autogenerated mess.

* Address comments

* Switch DllImport to LibraryImport

* Address gdkchan's comment
2022-12-11 00:57:01 +01:00
c6f1908e0f Fix Lambda Explicit Type Specification Warning (#4090) 2022-12-10 22:12:51 +01:00
851d81d24a Fix Redundant Qualifer Warnings (#4091)
* Fix Redundant Qualifer Warnings

* Remove unnecessary using
2022-12-10 21:21:13 +01:00
459c4caeba Fix HasUnalignedStorageBuffers value when buffers are always unaligned (#4078) 2022-12-09 17:41:40 -03:00
539b22ef7b Add explicit dependency on System.Drawing.Common on Ryujinx.Ava to workaround triming bugs 2022-12-09 20:12:09 +01:00
872f036d64 misc: Remove dependency on System.Drawing.Common (#4082)
We only used it in one spot for DPI scaling factor.

This implements the same behaviour using gdiplus.

This remove 700KB of dependency to download and around 170KB unpacked.
2022-12-09 18:00:53 +01:00
dca96122bf gha: Add concurrency restriction on release workflow (#4081) 2022-12-09 16:15:28 +00:00
e752959109 misc: Update Ryujinx.Graphics.Nvdec.Dependencies to 5.0.1-build12 (#4080)
This adds support for Linux x64, macOS x64 and macOS arm64.
2022-12-09 15:46:07 +01:00
cf01664698 ava: Restyle the Status Bar (#4048) 2022-12-09 15:21:54 +01:00
b283a4adcd nuget: bump CommandLineParser from 2.8.0 to 2.9.1 (#4058)
Bumps [CommandLineParser](https://github.com/commandlineparser/commandline) from 2.8.0 to 2.9.1.
- [Release notes](https://github.com/commandlineparser/commandline/releases)
- [Changelog](https://github.com/commandlineparser/commandline/blob/master/CHANGELOG.md)
- [Commits](https://github.com/commandlineparser/commandline/compare/2.8.0...v2.9.1)

---
updated-dependencies:
- dependency-name: CommandLineParser
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-09 14:16:22 +01:00
8428bb6541 Fix shader FSWZADD instruction (#4069)
* Fix shader FSWZADD instruction

* Shader cache version bump
2022-12-08 14:08:07 -03:00
9a0330f7f8 Shader: Implement PrimitiveID (#4067)
* Shader: Implement PrimitiveID

* Shader cache version bump
2022-12-08 10:55:03 +01:00
57fc996337 Fix inconsistent capitalization (#4070) 2022-12-08 09:32:24 +00:00
1f3b860f06 acc: Stub CheckNetworkServiceAvailabilityAsync (#4052) 2022-12-07 23:19:22 +01:00
abe3c02ab4 nuget: bump DynamicData from 7.12.8 to 7.12.11 (#4059)
Bumps [DynamicData](https://github.com/reactiveui/DynamicData) from 7.12.8 to 7.12.11.
- [Release notes](https://github.com/reactiveui/DynamicData/releases)
- [Changelog](https://github.com/reactivemarbles/DynamicData/blob/main/ReleaseNotes.md)
- [Commits](https://github.com/reactiveui/DynamicData/compare/7.12.8...7.12.11)

---
updated-dependencies:
- dependency-name: DynamicData
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-07 23:07:23 +01:00
45b417b2b4 nuget: bump NUnit from 3.12.0 to 3.13.3 (#4060)
Bumps [NUnit](https://github.com/nunit/nunit) from 3.12.0 to 3.13.3.
- [Release notes](https://github.com/nunit/nunit/releases)
- [Changelog](https://github.com/nunit/nunit/blob/v3.13.3/CHANGES.md)
- [Commits](https://github.com/nunit/nunit/compare/v3.12...v3.13.3)

---
updated-dependencies:
- dependency-name: NUnit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-07 22:02:31 +01:00
d076339e3e Add Ryujinx license file to builds (#4057) 2022-12-07 18:20:18 +01:00
837836431d nuget: bump System.Drawing.Common from 6.0.0 to 7.0.0 (#4024)
Bumps [System.Drawing.Common](https://github.com/dotnet/runtime) from 6.0.0 to 7.0.0.
- [Release notes](https://github.com/dotnet/runtime/releases)
- [Commits](https://github.com/dotnet/runtime/compare/v6.0.0...v7.0.0)

---
updated-dependencies:
- dependency-name: System.Drawing.Common
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-07 16:24:34 +00:00
9f555db5cd hle: Do not add disabled AoC item to the list (#4044)
* hle: Do not add disabled AoC item to the list

We currently add all AoC items to a list in `ContentManager` and the enable check is only done when FS service ask for the data. Which is wrong. It causes an issue in MK8D which doesn't boot even if you have disabled a not updated DLC.

I've fixed it by not adding the disabled AoC item to the list, I've removed some duplicate code too.
There is still an edge case because we currently don't check the AoC Item version, but that should be fixed later since now MK8D throw an error if the DLC isn't updated.

* remove useless "enabled"
2022-12-07 15:00:28 +01:00
bf7fa60dfc Fix struct layout packing (#4039) 2022-12-07 02:04:01 +00:00
752b93d3b7 gtk: Fixes warnings about obsolete components (#4049)
* gtk: Fixes warnings about obsolete components

* remove wrong using
2022-12-07 01:49:37 +01:00
f23b2878cc Shader: Add fallback for LDG from "ube" buffer ranges. (#4027)
We have a conversion from LDG on the compute shader to a special constant buffer binding that's used to exceed hardware limits on compute, but it was only running if the byte offset could be identified. The fallback that checks all of the bindings at runtime only checks the storage buffers.

This PR adds checking ube ranges to the LoadGlobal fallback. This extends the changes in #4011 to only check ube entries which are accessed by the shader.

Fixes particles affected by the wind in The Legend of Zelda: Breath of the Wild. May fix other weird issues with compute shaders in some games.

Try a bunch of games and drivers to make sure they don't blow up loading constants willynilly from searchable buffers.
2022-12-06 23:15:44 +00:00
e211c3f00a UI: Add Metal surface creation for MoltenVK (#3980)
* Initial implementation of metal surface across UIs

* Fix SDL2 on windows

* Update Ryujinx/Ryujinx.csproj

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Address Feedback

Co-authored-by: Mary-nyan <thog@protonmail.com>
2022-12-06 19:00:25 -03:00
d3709a753f nuget: bump XamlNameReferenceGenerator from 1.4.2 to 1.5.1 (#4026)
Bumps [XamlNameReferenceGenerator](https://github.com/avaloniaui/Avalonia.NameGenerator) from 1.4.2 to 1.5.1.
- [Release notes](https://github.com/avaloniaui/Avalonia.NameGenerator/releases)
- [Commits](https://github.com/avaloniaui/Avalonia.NameGenerator/compare/1.4.2...1.5.1)

---
updated-dependencies:
- dependency-name: XamlNameReferenceGenerator
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 19:00:08 +01:00
ab676d58ea nuget: bump System.IdentityModel.Tokens.Jwt from 6.25.0 to 6.25.1 (#4043)
Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 6.25.0 to 6.25.1.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/6.25.0...6.25.1)

---
updated-dependencies:
- dependency-name: System.IdentityModel.Tokens.Jwt
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 18:01:21 +01:00
2372c194f1 ava: Cleanup Input classes (#4042)
* ava: Cleanup Input classes

This PR just cleanup all Input classes for consistencies.

* Addresses TSRBerry's feedback
2022-12-06 15:32:14 +00:00
40311310d1 amadeus: Add missing compressor effect from REV11 (#4010)
* amadeus: Add missing compressor effect from REV11

This was in my reversing notes but seems I completely forgot to
implement it

Also took the opportunity to simplify the Limiter effect a bit.

* Remove some outdated comment

* Address gdkchan's comments
2022-12-06 15:04:25 +01:00
dde9bb5c69 Fix storage buffer access when match fails (#4037)
* Fix storage buffer access when match fails

* Shader cache version bump
2022-12-06 03:36:54 +00:00
266338a7c9 Change default Vsync toggle hotkey to F1 instead of Tab (#3995) 2022-12-06 02:09:26 +00:00
90156eea4c nuget: bump Microsoft.CodeAnalysis.CSharp from 4.2.0 to 4.4.0 (#4025)
Bumps [Microsoft.CodeAnalysis.CSharp](https://github.com/dotnet/roslyn) from 4.2.0 to 4.4.0.
- [Release notes](https://github.com/dotnet/roslyn/releases)
- [Changelog](https://github.com/dotnet/roslyn/blob/main/docs/Breaking%20API%20Changes.md)
- [Commits](https://github.com/dotnet/roslyn/compare/v4.2.0...Visual-Studio-2019-Version-16.0-Preview-4.4)

---
updated-dependencies:
- dependency-name: Microsoft.CodeAnalysis.CSharp
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 01:51:33 +00:00
071c01c235 Fix Sorting Regression (#4032)
* Fix sorting regression + Remove unsued sort

* Fix GTK

* Attempt 2 to fix GTK

* Whoopsie

* Fix whitspace
2022-12-06 01:40:06 +00:00
de06ffb0f7 Fix shaders with global memory access from unknown locations (#4029)
* Fix shaders with global memory access from unknown locations

* Shader cache version bump
2022-12-06 01:09:24 +00:00
8a7de35e3f Update 'OpenGL Log Level' to 'Graphics Backend Log Level' (#3996)
* Update 'OpenGL Log Level' to 'Graphics Backend Log Level'

* update other locals and change keys
2022-12-06 00:48:41 +00:00
121296834a Ava GUI: Several UI Fixes (#3991)
* Fix accessability violations in ListView

* Use accent colour for favourite star

* Hide progress bar when its done

* App Data Formating

- Added space before storage unit
- Changed so minutes have 0 decimals, and hours and days have 1

* Fix theming

* Fix mismatched corner radius

* Fix acceability violations in GridView

* More consistency between Grid and List View

* Fix margin

* Let whitespace defocus controls
2022-12-05 22:04:18 +00:00
bbb24d8c7e Restrict shader storage buffer search when match fails (#4011)
* Restrict storage buffer search when match fails

* Shader cache version bump
2022-12-05 19:11:32 +00:00
4da44e09cb Make structs readonly when applicable (#4002)
* Make all structs readonly when applicable. It should reduce amount of needless defensive copies

* Make structs with trivial boilerplate equality code record structs

* Remove unnecessary readonly modifiers from TextureCreateInfo

* Make BitMap structs readonly too
2022-12-05 14:47:39 +01:00
ae13f0ab4d misc: Fix obsolete warnings in Ryujinx.Graphics.Vulkan (#4020)
Was caused by some merges after the Silk.NET update
2022-12-05 12:57:11 +00:00
a2a35f1be6 nuget: bump Microsoft.NET.Test.Sdk from 16.8.0 to 17.4.0 (#3900)
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 16.8.0 to 17.4.0.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Commits](https://github.com/microsoft/vstest/compare/v16.8.0...v17.4.0)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-05 08:17:40 +01:00
aedfadaaf7 Add InfoType.MesosphereCurrentProcess (#3792)
* Add InfoType.MesosphereCurrentProcess

* Make outHandle inlined

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2022-12-04 19:46:02 +00:00
5c0fb0cec3 ui: Disallow checking for updates while emulation active (#3886)
* Disallow updating while game is running

* Reflected change on Avalonia

* Git has gone wonky

* Fix accidental indent
2022-12-04 20:17:11 +01:00
17a1cab5d2 Allow SNorm buffer texture formats on Vulkan (#3957)
* Allow SNorm buffer texture formats on Vulkan

* Shader cache version bump
2022-12-04 15:36:03 -03:00
73aed239c3 Implement non-MS to MS copies with draws (#3958)
* Implement non-MS to MS copies with draws, simplify MS to non-MS copies and supports any host sample count

* Remove unused program
2022-12-04 15:07:11 -03:00
9ac66336a2 GPU: Use lazy checks for specialization state (#4004)
* GPU: Use lazy checks for specialization state

This PR adds a new class, the SpecializationStateUpdater, that allows elements of specialization state to be updated individually, and signal the state is checked when it changes between draws, instead of building and checking it on every draw. This also avoids building spec state when

Most state updates have been moved behind the shader state update, so that their specialization state updates make it in before shaders are fetched.

Downside: Fields in GpuChannelGraphicsState are no longer readonly. To counteract copies that might be caused this I pass it as `ref` when possible, though maybe `in` would be better? Not really sure about the quirks of `in` and the difference probably won't show on a benchmark.

The result is around 2 extra FPS on SMO in the usual spot. Not much right now, but it will remove costs when we're doing more expensive specialization checks, such as fragment output type specialization for macos. It may also help more on other games with more draws.

* Address Feedback

* Oops
2022-12-04 18:41:17 +01:00
4965681e06 GPU: Swap bindings array instead of copying (#4003)
* GPU: Swap bindings array instead of copying

Reduces work on UpdateShaderState. Now the cost is a few reference moves for arrays, rather than copying data.

Downside: bindings arrays are no longer readonly.

* Micro optimisation

* Add missing docs

* Address Feedback
2022-12-04 18:18:40 +01:00
3868a00206 Use source generated regular expressions (#4005) 2022-12-04 00:43:23 +00:00
933e5144a9 Query Available RAM on macOS (#4000) 2022-12-04 00:25:07 +00:00
73a42c85c4 Add crowdin badge and information in readme (#3990)
* Add crowdin bagde and informations in readme.

* Update README.md

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Update README.md

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2022-12-02 23:57:38 +01:00
39ba11054b Update Crowdin configuration file 2022-12-02 15:22:21 +01:00
c250e3392c Fix using in Ava 2022-12-02 15:08:57 +01:00
e56b069081 Update Crowdin configuration file 2022-12-02 14:54:56 +01:00
204c031fef SDL2Driver: Invoke dispatcher on main thread (#3818) 2022-12-02 14:37:22 +01:00
d9053bbe37 Avalonia - Save Manager (#3476)
* Add save manager to account selector

* add fallback to app metadata for titlename if app is not in gamelist

* Allow recovering lost accounts
2022-12-02 13:16:43 +00:00
c25e8427aa amadeus: Fix wrong SendCommands logic (#3969)
* amadeus: Fix wrong SendCommands logic

Might help with audio desync, might cause audio stutters, will see!

* Address gdkchan's comment
2022-12-02 13:01:19 +00:00
21a081b185 Add back locales removed in #3955 (#3983)
Add back `SettingsButtonSave` & `SettingsButtonClose` removed in #3955

Fixes #3982
2022-12-02 12:46:18 +00:00
b540ea80d1 Ava GUI: Make Dialogue More Intuitive (#3955)
* Adjust button position and locales

* Shortcuts + Highlight default action

* Update Locales - Corrections Welcome

* Move `Apply` button back to right side

* OS Reactive Button layout

* Fix reversed boolean :)

* Fix accented button styling
2022-12-02 03:31:21 +01:00
d692a9b83e Revert "nuget: bump SixLabors.ImageSharp from 1.0.4 to 2.1.3 (#3976)"
This reverts commit 9677ddaa5d.

SixLabors.ImageShar switched to a shady and vague license starting with 2.x
without mentioning it on their changelog.

As a result we are staying on 1.x (licensed under Apache-2) and will
seak an alternative package.
2022-12-01 23:06:55 +01:00
9677ddaa5d nuget: bump SixLabors.ImageSharp from 1.0.4 to 2.1.3 (#3976)
* nuget: bump SixLabors.ImageSharp from 1.0.4 to 2.1.3

Bumps [SixLabors.ImageSharp](https://github.com/SixLabors/ImageSharp) from 1.0.4 to 2.1.3.
- [Release notes](https://github.com/SixLabors/ImageSharp/releases)
- [Commits](https://github.com/SixLabors/ImageSharp/compare/v1.0.4...v2.1.3)

---
updated-dependencies:
- dependency-name: SixLabors.ImageSharp
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update for 2.x changes

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Mary <mary@mary.zone>
2022-12-01 21:54:41 +00:00
ce92e8cd04 chore: Update Silk.NET to 2.16.0 (#3953) 2022-12-01 19:11:56 +01:00
456fc04007 Better SDL2 Audio Init Error Logging (#3967)
* Better SDL2 Audio Init Error Logging

* Update Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Update Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Update Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Update Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update Ryujinx.Audio.Backends.SDL2/SDL2HardwareDeviceDriver.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update SDL2HardwareDeviceDriver.cs

* Update SDL2HardwareDeviceDriver.cs

Co-authored-by: Mary-nyan <thog@protonmail.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
2022-12-01 17:53:13 +01:00
458452279c GPU: Track buffer migrations and flush source on incomplete copy (#3952)
* Track buffer migrations and flush source on incomplete copy

Makes sure that the modified range list is always from the latest iteration of the buffer, and flushes earlier iterations of a buffer if the data has not been migrated yet.

* Cleanup 1

* Reduce cost for redundant signal checks on Vulkan

* Only inherit the range list if there are pending ranges.

* Fix OpenGL

* Address Feedback

* Whoops
2022-12-01 16:30:13 +01:00
817b89767a infra: Add distribution files for macOS (#3934)
This upstream macOS packing and distribution files
2022-12-01 14:08:43 +01:00
3fb583c98c Avalonia: Clean up leftover RenderTimer & Fix minimum and initial window size (#3935)
* ava: Cleanup RenderTimer

* ava: Remove ContentControl from RendererHost

* ava: Remove unused actual scale factor

* ava: Enable UseGpu for Linux

* ava: Set better initial size & Scale the window properly

* ava: Realign properties

* ava: Use explicit type & specify where the note applies
2022-11-30 23:34:25 +01:00
d2686e0a5b nuget: bump DiscordRichPresence from 1.0.175 to 1.1.3.18 (#3965)
Bumps [DiscordRichPresence](https://github.com/Lachee/discord-rpc-csharp) from 1.0.175 to 1.1.3.18.
- [Release notes](https://github.com/Lachee/discord-rpc-csharp/releases)
- [Commits](https://github.com/Lachee/discord-rpc-csharp/commits)

---
updated-dependencies:
- dependency-name: DiscordRichPresence
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-30 21:58:45 +00:00
4905101df1 Remove shader dependency on SPV_KHR_shader_ballot and SPV_KHR_subgroup_vote extensions (#3943)
* Remove shader dependency on SPV_KHR_shader_ballot and SPV_KHR_subgroup_vote extensions

* Shader cache version bump
2022-11-30 18:24:15 -03:00
8750b90a7f Ensure that vertex attribute buffer index is valid on GPU (#3942)
* Ensure that vertex attribute buffer index is valid on GPU

* Remove vertex buffer validation code from OpenGL

* Remove some fields that are no longer necessary
2022-11-30 18:06:40 -03:00
af01100050 nuget: bump System.Management from 6.0.0 to 7.0.0 (#3949)
Bumps [System.Management](https://github.com/dotnet/runtime) from 6.0.0 to 7.0.0.
- [Release notes](https://github.com/dotnet/runtime/releases)
- [Commits](https://github.com/dotnet/runtime/compare/v6.0.0...v7.0.0)

---
updated-dependencies:
- dependency-name: System.Management
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-29 23:30:33 +01:00
c0821fee1f Update README.MD (#3946)
Updates the readme to include usage of Metal via MoltenVK, updated game compatibility statistics.
2022-11-29 17:20:26 +01:00
a5c2aead67 ConcurrentBitmap: Use Interlocked Or/And (#3937) 2022-11-29 13:47:57 +00:00
d41c95dcff chore: Update OpenTK to 4.7.5 (#3944) 2022-11-29 13:32:40 +00:00
fbf2b09706 ava: Make dialogs using an overlay window work on Linux (#3938) 2022-11-29 06:33:46 +01:00
1fc0f569de GPU: Always draw polygon topology as triangle fan (#3932)
Polygon topology wasn't really supported and would only work on OpenGL on drivers that haven't removed it. As an alternative, this PR makes all cases of polygon topology use triangle fan. The topology type and transform feedback type have not been changed, as I don't think geo shader/tfb should be used with polygons.

The OpenGL spec states:
Only convex polygons are guaranteed to be drawn correctly by the GL.

For convex polygons, triangle fan is equivalent to polygon. I imagine this is probably how it works on device, as this get-out-of-jail-free card is too enticing to pass up.

This fixes the stat display in Pokemon S/V.
2022-11-28 19:18:22 -03:00
dff138229c amadeus: Fixes and initial 15.0.0 support (#3908)
* amadeus: Allow OOB read of GC-ADPCM coefficients

Fixes "Ninja Gaiden Sigma 2" and possibly "NINJA GAIDEN 3: Razor's Edge"

* amadeus: Fix wrong variable usage in delay effect

We should transform the delay line values, not the input.

* amadeus: Update GroupedBiquadFilterCommand documentation

* amadeus: Simplify PoolMapper alignment checks

* amadeus: Update Surround delay effect matrix to REV11

* amadeus: Add drop parameter support and use 32 bits integers for estimate time

Also implement accurate ExecuteAudioRendererRendering stub.

* Address gdkchan's comments

* Address gdkchan's other comments

* Address gdkchan's comment
2022-11-28 08:28:45 +01:00
472119c8da sfdnsres; Fix deserializer of AddrInfoSerialized when addresses are empty (#3924) 2022-11-28 02:53:57 +01:00
1865ea87e5 bsd: Fix eventfd broken logic (#3647)
* bsd: Fix eventfd broken logic

This commit fix eventfd logic being broken.

The following changes were made:
- EventFd IPC definition had argument inverted
- EventFd events weren't fired correctly
- Poll logic was wrong and unfinished for eventfd
- Reintroduce workaround from #3385 but in a safer way, and spawn 4
  threads.

* ipc: Rework a bit for multithreads

* Clean up debug logs

* Make server thread yield when managed lock isn't availaible

* Fix replyTargetHandle not being added in the proper locking scope

* Simplify some scopes

* Address gdkchan's comments

* Revert IPC workaround for now

* Reintroduce the EventFileDescriptor workaround
2022-11-27 20:18:05 +00:00
18b61aff59 Unbreak bug_report.md (#3915)
* Unbreak bug_report.md

* Update bug_report.md
2022-11-27 20:11:51 +00:00
cb22629ac1 HLE: fix small issue in IPsmSession (#3909) 2022-11-27 01:10:42 +00:00
6f0f99ee2b Avalonia: Fix OpenGL crashing on Linux (#3902)
* ava: Fix OpenGL crashing on Linux

Fixes a regression from #3901

* Fix formatting
2022-11-26 12:06:53 +01:00
70f2da8fdf ava: Fix invisible vulkan window on Linux (#3901)
Co-authored-by: emmauss <emmausssss@gmail.com>

Co-authored-by: emmauss <emmausssss@gmail.com>
2022-11-25 17:40:44 +00:00
5d3ef7761b ava: Refactor Title Update Manager window (#3898)
* ava: Refactor TitleUpdate Manager window

* Update locale
2022-11-25 17:55:08 +01:00
476b4683cf Fix CB0 alignment with addresses used for 8/16-bit LDG/STG (#3897)
This replacement is meant to be done with the original identified byteOffset, not the one assigned later on by the below conditionals (that already has the constant offset added, for instance).

This fixes videos being pixelated in Xenoblade 3, and other regressions that might have happened since #3847.
2022-11-25 14:39:03 +00:00
5fb5079730 chore: Update Avalonia related dependencies (#3891) 2022-11-25 13:27:41 +00:00
3fbacd0f49 ava: Rework DLC Manager, Add various fixes and cleanup (#3896)
* Fixes Everything Part.2

* Change sorting, fix remove and heading
2022-11-25 12:41:34 +01:00
7aa6abc120 nuget: bump SharpZipLib from 1.3.3 to 1.4.1 (#3893)
Bumps [SharpZipLib](https://github.com/icsharpcode/SharpZipLib) from 1.3.3 to 1.4.1.
- [Release notes](https://github.com/icsharpcode/SharpZipLib/releases)
- [Changelog](https://github.com/icsharpcode/SharpZipLib/blob/master/docs/Changes.txt)
- [Commits](https://github.com/icsharpcode/SharpZipLib/compare/v1.3.3...v1.4.1)

---
updated-dependencies:
- dependency-name: SharpZipLib
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-24 20:30:17 +01:00
548bfd60a2 chore: Update Ryujinx.SDL2-CS to 2.24.2 (#3892)
* chore: Update Ryujinx.SDL2-CS to 2.24.2

* Disable SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS
2022-11-24 20:13:16 +01:00
65778a6b78 GPU: Don't trigger uploads for redundant buffer updates (#3828)
* Initial implementation

* Actually do The Thing

* Add remark about performance to IVirtualMemoryManager
2022-11-24 15:50:15 +01:00
f4e879a1e6 Reduce usage of Marshal.PtrToStructure and Marshal.StructureToPtr (#3805)
* common: Make BinaryReaderExtensions Read & Write take unamanged types

This allows us to not rely on Marshal.PtrToStructure and Marshal.StructureToPtr for those.

* common: Make MemoryHelper Read & Write takes unamanged types

* Update Marshal.SizeOf => Unsafe.SizeOf when appropriate and start moving software applet to unmanaged types
2022-11-24 15:26:29 +01:00
a1ddaa2736 ui: Fixes disposing on GTK/Avalonia and Firmware Messages on Avalonia (#3885)
* ui: Only wait on _exitEvent when MainLoop is active under GTK

This fixes a dispose issue under Horizon/GTK, we don't check if the ApplicationClient is null so it throw NCE. We don't check if the main loop is active and waiting an event which is set in the main loop... So that could lead to a freeze.

Everything works fine in GTK now.

Related issue: https://github.com/Ryujinx/Ryujinx/issues/3873

As a side note, same kind of issue appear in Avalonia UI too. Firmware's popup doesn't show anything and the emulator just freeze.

* TSRBerry's change

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Fix Avalonia crashing/freezing

* Add Avalonia OpenGL fixes

* Fix firmware popup on windows

* Fixes everything

* Add _initialized bool to VulkanRenderer and OpenGL Window

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2022-11-24 15:08:27 +01:00
008286b79f Ryujinx.Ava: Add missing redefinition of app name (#3890)
Before this, Ryujinx would possibly report as "Avalonia Application".
2022-11-24 14:52:39 +01:00
a0c77f8d11 Fix NRE on Avalonia for error applets with unknown error message (#3888) 2022-11-24 09:31:00 +01:00
ece36b274d GAL: Send all buffer assignments at once rather than individually (#3881)
* GAL: Send all buffer assignments at once rather than individually

The `(int first, BufferRange[] ranges)` method call has very significant performance implications when the bindings are spread out, which they generally always are in Vulkan. This change makes it so that these methods are only called a maximum of one time per draw.

Significantly improves GPU thread performance in Pokemon Scarlet/Violet.

* Address Feedback

Removed SetUniformBuffers(int first, ReadOnlySpan<BufferRange> buffers)
2022-11-24 07:50:59 +00:00
f3cc2e5703 GPU: Access non-prefetch command buffers directly (#3882)
* GPU: Access non-prefetch command buffers directly

Saves allocating new arrays for them constantly - they can be quite small so it can be very wasteful. About 0.4% of GPU thread in SMO, but was a bit higher in S/V when I checked.

Assumes that non-prefetch command buffers won't be randomly clobbered before they finish executing, though that's probably a safe bet.

* Small change while I'm here

* Address feedback
2022-11-24 01:56:55 +00:00
5a39d3c4a1 GPU: Relax locking on Buffer Cache (#3883)
I did this on ncbuffer2 when we were using it for LDN 3, but I noticed that it can apply to the current buffer manager too, and it's an easy performance win.

The only buffer access that can come from another thread is the overlap search for buffers that have been unmapped. Everything else, including modifications, come from the main GPU thread. That means we only need to lock the range list when it's being modified, as that's the only time where we'll cause a race with the unmapped handler.

This has a significant performance improvements in situations where FIFO is high, like the other two PRs. Joined together they give a nice boost (73.6 master -> 79 -> 83 fps in SMO).
2022-11-24 01:41:16 +00:00
cc51a03af9 nuget: bump Avalonia from 0.10.15 to 0.10.18 (#3817)
Bumps [Avalonia](https://github.com/AvaloniaUI/Avalonia) from 0.10.15 to 0.10.18.
- [Release notes](https://github.com/AvaloniaUI/Avalonia/releases)
- [Commits](https://github.com/AvaloniaUI/Avalonia/compare/0.10.15...0.10.18)

---
updated-dependencies:
- dependency-name: Avalonia
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-24 01:26:53 +00:00
567c64e149 ava: Fix JsonSerializer warnings (#3884)
Since we move to .NET7, JsonSerializer now needs to have explicit options as arguments, which leads to some warnings in Avalonia project. This is fixed by using our `JsonHelper` class.
2022-11-23 17:55:26 +00:00
36f00985d3 Update to LibHac 0.17.0 (#3878)
* Update to LibHac 0.17.0

* Don't clear SD card saves when starting the emulator

This was an old workaround for errors that happened when a user's SD card encryption seed changed. SD card saves have been unencrypted for over a year, so we should be fine to remove the workaround.
2022-11-23 18:32:35 +01:00
748d87adcc Stub IFriendService: 1 (Cancel) (#3841)
* Add friend/Cancel. Closes #3824

* Update according to review comments.

* Add comment base on request

* Update Ryujinx.HLE/HOS/Services/Friend/ServiceCreator/IFriendService.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2022-11-23 16:25:49 +01:00
0fd47ff490 remove redundant logs (#3877) 2022-11-23 11:28:46 +01:00
f088c3d344 Do not update shader state for DrawTextures (#3876) 2022-11-21 18:16:00 +01:00
905a191e28 Use upstream unicorn for Ryujinx.Tests.Unicorn (#3771)
* unicorn: Add modified ver of unicorns const gen

* unicorn: Use upstream consts

These consts were generated from the dev branch of unicorn

* unicorn: Split common consts into multiple enums

* unicorn: Remove arch prefix from consts

* unicorn: Add new windows dll

Windows 10 - MSVC x64 shared build

* unicorn: Use absolute path for const generation

* unicorn: Remove fspcr patch

* unicorn: Fix using the wrong file extension

For some reason _NativeLibraryExtension evaluates to ".so" even on Windows.

* unicorn: Add linux shared object again

* unicron: Add DllImportResolver

* unicorn: Try to import unicorn using an absolute path

* unicorn: Add clean target

* unicorn: Replace IsUnicornAvailable() methods

* unicorn: Skip tests instead of silently passing them if unicorn is missing

* unicorn: Write error message to stderr

* unicorn: Make Interface static

* unicron: Include prefixed unicorn libs (libunicorn.so)

Co-authored-by: merry <git@mary.rs>

* unicorn: Add lib prefix to shared object for linux

Co-authored-by: merry <git@mary.rs>
2022-11-20 20:18:21 +01:00
ab0491817e Reword the description of the 6GB expand DRAM hack to be less tantalizing (#3870)
* Reword the hack to something less tantalizing

* Address feedback
2022-11-20 17:15:57 +00:00
5de6ae426e Unsubscribe MemoryUnmappedHandler even when GPU channel is destroyed (#3872) 2022-11-19 23:54:33 -03:00
69ced3a6e8 Fix shader cache on Vulkan when geometry shaders are inserted (#3868) 2022-11-19 10:24:23 +01:00
2e43d01d36 Move gl_Layer from vertex to geometry if GPU does not support it on vertex (#3866)
* Move gl_Layer from vertex to geometry if GPU does not support it on vertex

* Shader cache version bump

* PR feedback
2022-11-18 23:27:54 -03:00
7373ec5792 Vulkan: Clear dummy texture to (0,0,0,0) on creation (#3867)
This might fix an issue with AMD gpus on linux where the data could contain random garbage data. On the switch, it always samples as 0.
2022-11-18 23:11:34 -03:00
de162a648b Gpu: Fix thread safety of ReregisterRanges (#3865)
A quick fix to prevent reading the wrong value of Count when reregistering ranges for a new target buffer. Buffer flushes from another thread can modify the range list when the lock isn't active, which can change the count.

This prevents some crashes in Pokemon Scarlet/Violet. It's probably likely that buffer migration during flush is causing some other issues in this game, but this at least prevents the crashing.
2022-11-18 21:47:29 +01:00
131baebe2a Vulkan: Don't create preload command buffer outside a render pass (#3864)
* Vulkan: Don't create preload buffer outside a render pass

The preload command buffer is used to avoid render pass splits and barriers when updating buffer data. However, when a render pass is not active (for example, at the start of a pass, or during compute invocations) buffer uploads can be performed at any time, so the optimization isn't as useful.

This PR makes it so that the preload command buffer is only used for buffer updates outside of a render pass. It's still used for textures as I don't want to shake things up right now regarding how the preload buffer is obtained before some other changes, and texture updates are a lot rarer anyways.

Improves performance slightly in Pokemon Scarlet/Violet (43 -> 48), as it was switching to compute, writing a bunch of buffers inline, then dispatching, then flushing commands... It uses 1 command buffer instead of 2 every time it does this now. Maybe it would be nice to find a faster way to sync without creating so many command buffers in a short period of time.

* Address feedback
2022-11-18 14:58:56 +00:00
187372cbde Prune ForceDirty and CheckModified caches on unmap (#3862)
* Prune ForceDirty and CheckModified caches on unmap

Since we're now using this for modified checks on the HLE indirect draw method, I'm worried that leaving these to forever gather cache entries isn't the best idea for performance in the long term, and it could keep old buffer objects alive for longer than they should be.

This PR adds the ability to prune invalid entries before checking these caches, and queues it whenever gpu memory is unmapped. It also aligns modified checks to the page size, as I figured it would be possible for a huge number of overlapping over a game's runtime.

This prevents Super Mario Odyssey from having 10s of thousands of entries in the modified cache in Metro Kingdom, and them duplicating when entering and leaving a building (should be cleared, as they were unmapped).

* Address Feedback
2022-11-18 14:58:24 +00:00
022d495335 am: Stub GetSaveDataSizeMax (#3857)
* am: Stub GetSaveDataSizeMax()

* am: Remove todo comment for GetSaveDataSizeMax()

* am: saveDataSize & journalDataSize should be of type long

* am: Add explanation for returning default values in GetSaveDataSizeMax()
2022-11-18 03:29:01 +00:00
c1372ed775 Use ReadOnlySpan<byte> compiler optimization in more places (#3853)
* Use ReadOnlySpan<byte> compiler optimization in more places

* Revert changes in ShaderBinaries.cs

* Remove unused using;

* Use ReadOnlySpan<byte> compiler optimization in more places
2022-11-18 03:10:44 +00:00
a16682cfd3 Allow _volatile to be set from MultiRegionHandle checks again (#3830)
* Allow _volatile to be set from MultiRegionHandle checks again

Tracking handles have a `_volatile` flag which indicates that the resource being tracked is modified every time it is used under a new sequence number. This is used to reduce the time spent reprotecting memory for tracking writes to commonly modified buffers, like constant buffers.

This optimisation works by detecting if a buffer is modified every time a check happens. If a buffer is checked but it is not dirty, then that data is likely not modified every sequence number, and should use memory protection for write tracking. If the opposite is the case all the time, it is faster to just assume it's dirty as we'd just be wasting time protecting the memory.

The new MultiRegionBitmap could not notify handles that they had been checked as part of the fast bitmap lookup, so bindings larger than 4096 bytes wouldn't trigger it at all. This meant that they would be subject to a ton of reprotection if they were modified often.

This does mean there are two separate sources for a _volatile set: VolatileOrDirty + _checkCount, and the bitmap check. These shouldn't interfere with each other, though.

This fixes performance regressions from #3775 in Pokemon Sword, and hopefully Yu-Gi-Oh! RUSH DUEL: Dawn of the Battle Royale. May affect other games.

* Fix stupid mistake
2022-11-18 02:54:20 +00:00
7c53b69c30 SPIR-V: Fix unscaling helper not being able to find Array textures (#3863)
The type in the `texOp` in the textureSize instruction doesn't have the exact type on SPIR-V (for example, it is missing the Array flag). This PR gives it the proper type before giving it to the unscaling helper.

This fixes the ground textures being broken on Pokemon Scarlet/Violet when scaling. It wasn't finding the texture, so the descriptor index it provided was -1...
2022-11-18 02:37:37 +00:00
33a4d7d1ba GPU: Eliminate CB0 accesses when storage buffer accesses are resolved (#3847)
* Eliminate CB0 accesses

Still some work to do, decouple from hle?

* Forgot the important part somehow

* Fix and improve alignment test

* Address Feedback

* Remove some complexity when checking storage buffer alignment

* Update Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2022-11-17 18:47:41 +01:00
391e08dd27 ci: Clean up Actions leftovers (#3859)
As title say.

Fix Avalonia build versions for PRs.

Also ensure that the --self-contained doesn't warn at build.
2022-11-17 18:30:54 +01:00
b5cf8b8af9 Capitalization to be consistent (#3860)
Thread ID Register, Floating-point Control Register, and Floating-point Status Register all had Register capitalized, so the Register in Processor State register should be capitalized.
2022-11-17 18:13:37 +01:00
55043c8afc Allow to start Ryujinx in wayland environment (#3516)
PrimaryMonitor is only available on X11

At some point it will be deprecated, this change support wayland
2022-11-17 13:02:43 +01:00
5d73a9f5fc Fix Fedora support (#3815)
For some reasons, my fresh installation of Fedora 36 (KDE) doesn't have a
symlink for libX11.so.

This commit fixes this by trying to import the library with its major
version or fallback to the normal way.
2022-11-17 00:18:29 +01:00
2c9ab5e45f Prevent raw Unicode control codes from showing on software keyboard applet. (#3845)
* Revert "Add support for releasing a semaphore to DmaClass (#2926)"

This reverts commit 521a07e612.

* Revert "Revert "Add support for releasing a semaphore to DmaClass (#2926)""

This reverts commit ec8a5fd053.

* Strip non-visible control codes from strings before they are sent to the software keyboard to prevent ugly unicode blocks from being shown on the UI.

* remove debugging junk

* Initialize stringbuilder capacity at the start to prevent resizing (a tiny tiny microoptimization)

* Update remarks documentation. Remove unneeded imports.

* Removing a test that's actually just redundant

Co-authored-by: Logan Stromberg <lostromb@microsoft.com>
2022-11-16 23:53:17 +01:00
d536cc8ae6 Update units of memory from decimal to binary prefixes (#3716)
`MB` and `GB` can either be interpreted as having base-10 units, or
base-2. `MiB` and `GiB` removes this discrepancy so that units of memory
are always interpreted using base-2 units.
2022-11-16 23:27:42 +01:00
d751da84f9 Use new C# 11 u8 string literals (#3854) 2022-11-16 16:30:12 -03:00
11aae9cfbc Make use of Random.Shared (#3852) 2022-11-16 15:34:18 -03:00
b96794e72b Use new LINQ Order() methods (#3851) 2022-11-16 15:17:03 -03:00
f1d1670b0b Implement HLE macro for DrawElementsIndirect (#3748)
* Implement HLE macro for DrawElementsIndirect

* Shader cache version bump

* Use GL_ARB_shader_draw_parameters extension on OpenGL

* Fix DrawIndexedIndirectCount on Vulkan when extension is not supported

* Implement DrawIndex

* Alignment

* Fix some validation errors

* Rename BaseIds to DrawParameters

* Fix incorrect index buffer and vertex buffer size in some cases

* Add HLE macros for DrawArraysInstanced and DrawElementsInstanced

* Perform a regular draw when indirect data is not modified

* Use non-indirect draw methods if indirect buffer was not GPU modified

* Only check if draw parameters match if the shader actually uses them

* Expose Macro HLE setting on GUI

* Reset FirstVertex and FirstInstance after draw

* Update shader cache version again since some people already tested this

* PR feedback

Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2022-11-16 14:53:04 -03:00
b8de72de8f It's REE-YOU-JINX (#3839) 2022-11-15 22:19:25 +01:00
eebc39228d UI: Allow overriding graphics backend + Move command line parser into a new class (#3707)
* Ava: Keep command line args when restarting

* UI: Move common UI functions to ProgramHelper

Add command line option to override the configured graphics backend

* Ava: Add CleanupUpdate task back

* Remove unused usings

* Revert combining common UI functions

Rename ProgramHelper to CommandLineState
Move command line parsing to CommandLineState

* Rename CommandLineProfile to Profile

* Fix assigning the wrong array to Arguments
2022-11-12 20:36:36 -03:00
9daf029f35 Use vector transform feedback outputs if possible (#3832) 2022-11-12 20:20:40 -03:00
51a27032f0 Fix VertexId and InstanceId on Vulkan (#3833)
* Fix VertexId and InstanceId on Vulkan

* Shader cache version bump
2022-11-11 13:22:49 -03:00
a6a67a2b7a Minor improvement to Vulkan pipeline state and bindings management (#3829)
* Minor improvement to Vulkan pipeline state and bindings management

* Clean up buffer textures too

* Use glBindTextureUnit
2022-11-10 13:38:38 -03:00
c6d05301aa infra: Migrate to .NET 7 (#3795)
* Update readme to mention .NET 7

* infra: Migrate to .NET 7

.NET 7 is still in preview but this prepare for the release coming up
next month.

* Use Random.Shared in CreateRandom

* Move UInt128Utils.cs to Ryujinx.Common project

* Fix inverted parameters in System.UInt128 constructor

* Fix Visual Studio complains on  Ryujinx.Graphics.Vic

* time: Fix missing alignment enforcement in SystemClockContext

Fixes at least Smash

* time: Fix missing alignment enforcement in SteadyClockContext

Fix games (like recent version of Smash) using time shared memory

* Switch to .NET 7.0.100 release

* Enable Tiered PGO

* Ensure CreateId validity requirements are meet when doing random generation

Also enforce correct packing layout for other Mii structures.

This fix a Mario Kart 8 crashes related to the default Miis.
2022-11-09 20:22:43 +01:00
647de4cd31 Ensure all pending draws are done before compute dispatch (#3822) 2022-11-03 19:54:30 -03:00
f82309fa2d Vulkan: Implement multisample <-> non-multisample copies and depth-stencil resolve (#3723)
* Vulkan: Implement multisample <-> non-multisample copies and depth-stencil resolve

* FramebufferParams is no longer required there

* Implement Specialization Constants and merge CopyMS Shaders (#15)

* Vulkan: Initial Specialization Constants

* Replace with specialized helper shader

* Reimplement everything

Fix nonexistant interaction with Ryu pipeline caching
Decouple specialization info from data and relocate them
Generalize mapping and add type enum to better match spv types
Use local fixed scopes instead of global unmanaged allocs

* Fix misses in initial implementation

Use correct info variable in Create2DLayerView
Add ShaderStorageImageMultisample to required feature set

* Use texture for source image

* No point in using ReadOnlyMemory

* Apply formatting feedback

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Apply formatting suggestions on shader source

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Support conversion with samples count that does not match the requested count, other minor changes

Co-authored-by: mageven <62494521+mageven@users.noreply.github.com>
2022-11-02 18:17:19 -03:00
7d8e198c33 fix: Support FFmpeg 5.1.x for decoding (#3816)
For some reason FFmpeg 5.1.x reverted part of the changes made in 5.0.x
on AVCodec.

This fix decoding issues with it.
2022-11-02 09:26:50 +01:00
3d98e1361b GPU: Use a bitmap to track buffer modified flags. (#3775)
* Initial implementation

* Some improvements.

* Fix incorrect cast

* Performance improvement and improved correctness

* Add very fast path when all handles are checked.

* Slightly faster

* Add comment

* De-virtualize region handle

All region handles are now bitmap backed.

* Remove non-bitmap tracking

* Remove unused methods

* Add docs, remove unused methods

* Address Feedback

* Rename file
2022-10-29 22:07:37 +00:00
141cf61ff7 CI: Run git_short_hash inside of bash (#3808) 2022-10-29 19:00:08 +00:00
3fe3598d41 Vulkan: Replace VK_EXT_debug_report usage with VK_EXT_debug_utils (#3802)
* Vulkan: Replace `VK_EXT_debug_report` usage with `VK_EXT_debug_utils`

[VK_EXT_debug_report](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_debug_report.html)
has been depreciated for quite some time now in favor of the much more
featureful
[VK_EXT_debug_utils](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_debug_utils.html)
extension.

This PR converts our debug-report-callback into the newer
debug-messenger pattern.

`VK_EXT_debug_utils` adds some additional diagnostic tooling for marking
debug-label scopes for queue-operations, command-buffers, and assigning
name-labels to vulkan objects to aid in debugging(for a later PR).

* Vulkan: Fix `DebugMessenger` severity-flag classification

Extension bits between the two flags, for reference:

https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkDebugUtilsMessageSeverityFlagBitsEXT.html

https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkDebugReportFlagBitsEXT.html
2022-10-29 14:09:25 -03:00
59cdf310bd SPIR-V: Fix tessellation control shader output types (#3807)
* SPIR-V: Fix tessellation control shader output types

* Shader cache version bump
2022-10-29 13:45:30 -03:00
4e34170a84 nuget: bump System.IdentityModel.Tokens.Jwt from 6.15.0 to 6.25.0 (#3806)
Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 6.15.0 to 6.25.0.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/commits)

---
updated-dependencies:
- dependency-name: System.IdentityModel.Tokens.Jwt
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-29 10:46:46 +02:00
d540af5dc0 AppletAE: stub SetRecordVolumeMuted (#3804)
* Update IIrSensorServer.cs

* Update IIrSensorServer.cs

* Apply suggestions from code review

Addressed formatting feedback

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update IIrSensorServer.cs

* Update ISelfController.cs

* Update ISelfController.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2022-10-27 23:15:57 +00:00
f7c7b66fc0 hid/irs: Stub StopImageProcessorAsync (#3799)
* Update IIrSensorServer.cs

* Update IIrSensorServer.cs

* Apply suggestions from code review

Addressed formatting feedback

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Update IIrSensorServer.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2022-10-27 21:36:37 +00:00
28ba55598d Vulkan: Fix indirect buffer barrier (#3798) 2022-10-26 14:53:11 -03:00
9719b6a112 Vulkan: Use dynamic state for blend constants (#3793) 2022-10-25 23:49:23 +00:00
f70236f947 Updated Compatibility info and GPU info (Vulkan, SPIRV, and Texture Recompression) (#3568)
* Updated Compatibility info and GPU info (Vulkan, SPIRV, and Texture Recompression)

* Added Mutant's changes.

Co-authored-by: MutantAura <44103205+MutantAura@users.noreply.github.com>

* Five to four.

* Fixed github's terrible conflict diffs

Co-authored-by: MutantAura <44103205+MutantAura@users.noreply.github.com>
2022-10-24 16:40:39 +00:00
eafadf10c7 Ryujinx.Tests.Unicorn: Implement IDisposable (#3794)
Dispose unicorn when done
2022-10-23 23:51:54 +00:00
9b06ee7736 Attempt to fix issues since github-script v6 upgrade 2022-10-23 17:15:15 +02:00
baba2c2467 Avalonia: Use overlay dialog for controller applet (#3777)
* use overlay dialog for controller applet

* Update Ryujinx.Ava/Ui/Controls/ContentDialogHelper.cs

Co-authored-by: riperiperi <rhy3756547@hotmail.com>

Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2022-10-23 11:15:45 +02:00
286e5d39b2 nuget: bump SPB from 0.0.4-build24 to 0.0.4-build27 (#3791)
Bumps [SPB](https://github.com/Thog/SPB) from 0.0.4-build24 to 0.0.4-build27.
- [Release notes](https://github.com/Thog/SPB/releases)
- [Commits](https://github.com/Thog/SPB/commits)

---
updated-dependencies:
- dependency-name: SPB
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-22 10:32:12 +02:00
dc529c1181 ci: Add updates for nuget packages to dependabot (#3786) 2022-10-21 14:23:16 +02:00
c7cf1cbc35 CI: Update workflows (#3774)
* ci: Update workflows

* gha: Add no-build switch to test action
2022-10-21 10:31:38 +02:00
d8e487d018 gha: Add dependabot.yml (#3778) 2022-10-21 10:16:28 +02:00
5fdc46ac7f Vulkan: Fix vertex position Z conversion with geometry shader passthrough (#3781)
* Vulkan: Fix vertex position Z conversion with geometry shader passthrough

* Shader cache version bump
2022-10-21 04:48:21 +00:00
1e5b45f580 Avalonia: update it_IT.json (#3742)
* Avalonia: update it_IT.json

* Fixed ; instead of :

* Update it_IT.json

port di #3766

* Update Ryujinx.Ava/Assets/Locales/it_IT.json

Co-authored-by: Antonio Brugnolo <36473846+AntoSkate@users.noreply.github.com>

* Grammar fix

Co-authored-by: Lorenzo Giannini <55211569+Lorenzo0310200@users.noreply.github.com>
Co-authored-by: Antonio Brugnolo <36473846+AntoSkate@users.noreply.github.com>
2022-10-19 09:30:28 +00:00
62585755fd Do not clear the rejit queue when overlaps count is equal to 0. (#3721)
* Do not clear the rejit queue when overlaps count is equal to 0.

* Ptc and PtcProfiler must be invalidated.

* Revert "Ptc and PtcProfiler must be invalidated."

This reverts commit f5b0ad9d7d.

* Fix #3710 slow path due to #3701.
2022-10-19 02:08:34 +00:00
56621615b1 Implement the GetSessionCacheMode in SSL servuce (#3735) 2022-10-19 01:27:11 +00:00
2099a3e84b Manage state of NfcManager (#3678)
* Manage state of NfcManager

Very basic state management but works with Hyrule Warriors Definitive Edition. Partially fixes #2122

* Fixes changes from review
2022-10-19 01:14:31 +00:00
7d26e4ac7b Fix mapping leaks caused by UnmapView not working on Linux (#3650)
* Add test for UnmapView mapping leaks

* Throw when UnmapView fails on Linux

* Fix UnmapView

* Remove throw
2022-10-19 01:02:45 +00:00
8d41402fa6 A32: Implement VCVTT, VCVTB (#3710)
* A32: Implement VCVTT, VCVTB

* A32: F16C implementation of VCVTT/VCVTB
2022-10-19 02:36:04 +02:00
5af8ce7c38 A64: Add fast path for Fcvtas_Gp/S/V, Fcvtau_Gp/S/V and Frinta_S/V in… (#3712)
* A64: Add fast path for Fcvtas_Gp/S/V, Fcvtau_Gp/S/V and Frinta_S/V instructions;

they use "Round to Nearest with Ties to Away" rounding mode not supported in x86.

All instructions involved have been tested locally in both release and debug modes, in both lowcq and highcq.

The titles Mario Strikers and Super Smash Bros. U. use these instructions intensively.

* Update Ptc.cs

* A32: Add fast path for Vcvta_RM, Vrinta_RM and Vrinta_V instructions aswell.
2022-10-19 00:21:33 +00:00
77c4291c34 Avalonia: Update Polish Translation (#3722)
* Add new string

You need the period there otherwise it could be read as "Głoś" -> "Preach"

* Update MainWindow.axaml

Updating to bring it in line with the other languages naming themselves in their respective languages

* Update pl_PL.json

realizing that period isn't necessary considering the string's usage (which to be fair, I should have checked when I added it)

* Update pl_PL.json

* Add Updater Message
2022-10-19 00:10:28 +00:00
6e92b7a378 Dispose Vulkan TextureStorage when views hit 0 instead of immediately (#3738)
Due to the `using` statement being scoped to the `CreateTextureView` method, `TextureStorage` would be disposed as soon as the view was returned.

This was largely fine as the TextureStorage resources were being kept alive by the views holding their own references to them, but it also meant that dispose is only called as soon as the texture is created.

Aliased Storages are TextureStorages created with the same allocation as another TextureStorage, if they have to be aliased as another format. We keep track of a TextureStorage's `_aliasedStorages` as they are created, and dispose them when the TextureStorage is disposed...

...except it is disposed immediately, before any aliased storages are even created. The aliased storages added after this will never be disposed.

This PR attempts to fix this by disposing TextureStorage when its view count reaches 0. The other use of texture storage - the D32S8 blit - still manually disposes the storage, but regular uses created via the GAL are now disposed by the view count.

I think this makes the most sense, as otherwise in the future this behaviour might be forgotton and more things could be added to the Dispose() method that don't work due to it not actually calling at the right time.

This should improve memory leaks in Super Mario Odyssey, most noticeable when resolution scaling. The memory usage of the game is still wildly unpredictable due to how it interacts with the texture cache, but now it shouldn't get considerably longer as you play... I hope. I've seen it typically recover back to the same level occasionally, though it can spike significantly.

Please test a bunch of games on multiple GPUs to make sure this doesn't break anything.
2022-10-18 23:52:08 +00:00
9b852c7481 Fix: Arguments Break when Updating (#3744)
* Wrap Args in quotes

-Wrap args in quotes to allow for spaces in dir paths when restarting Ryujinxs from Update.

* Wrap second instance of GetCommandLineArgs()

* Changed ryuArgs from string to string[]

* Update Ryujinx.Ava/Modules/Updater/Updater.cs

Co-authored-by: mageven <62494521+mageven@users.noreply.github.com>

* Update UpdateDialog.cs

Co-authored-by: mageven <62494521+mageven@users.noreply.github.com>
2022-10-18 23:41:16 +00:00
c40c3905e2 Avoid allocations in .Parse methods (#3760)
* Avoid allocations in .Parse methods

Use the Span overloads of the Parse methods when possible to avoid string allocations and remove one unnecessarry array allocation

* Avoid another string allocation
2022-10-18 23:31:34 +00:00
a6cd044f0f Vulkan: Fix blit levels/layers parameters being inverted (#3768) 2022-10-18 10:13:44 +02:00
f5a1de6ac5 Fix kernel VA allocation when random allocation fails (#3755)
* Fix kernel VA allocation when random allocation fails

* This was off by one
2022-10-17 22:12:49 +00:00
2aeb5b00e3 Update README.md (#3767)
Update compatibility numbers
2022-10-17 23:58:11 +02:00
60ba7b71f2 remove property changed call in time zone validation (#3752) 2022-10-17 16:48:14 +00:00
7c1d2bbb98 Implement OpenDataStorageWithProgramIndex partially (#3765)
* Implement OpenDataStorageWithProgramIndex partially

* Was not supposed to change this
2022-10-17 13:37:05 +00:00
beacf8c1c8 TamperMachine: Fix input mask check (#3764) 2022-10-16 19:51:52 -03:00
0dbe45ae37 Fix various issues caused by Vertex/Index buffer conversions (#3762)
* Fix various issues caused by #3679

- The arguments for the 0th dummy vertex buffer were incorrect - it was given an offset of 16 rather than a size of 16.
- The wrong size was used when doing `autoBuffer.Get` on a converted vertex buffer.
- The possibility of a vertex buffer being disposed and then rebound can rebindings to find a different buffer where the current range is out of bounds. Avoid binding when out of range to prevent validation errors.
- The above also affects generation of converted buffers, which was a bit more fatal. Conversion functions now attempt to bound input offset/size.

* Fix offset for converted buffer
2022-10-16 19:38:58 -03:00
2b50e52e48 Fix primitive count calculation for topology conversion (#3763)
Luigi's Mansion 3 performs a non-index quads draw with 6 vertices. It's meant to ignore the last two, but the index pattern's primitive count calculation was rounding up.

No idea why the game does this but this should fix random triangles in the map.
2022-10-16 19:25:40 -03:00
49eadbc209 Fix phantom configured Controllers (#3720)
Enable guest controller only when a valid host controller is mapped.
2022-10-16 20:34:42 +02:00
2df16ded9b Improve shader BRX instruction code generation (#3759)
* Improve shader BRX instruction code generation

* Shader cache version bump, add some comments and asserts
2022-10-15 23:20:16 +00:00
e43390c723 bsd: Check if socket is bound before calling RecvFrom() (#3761) 2022-10-15 20:52:49 +00:00
5af1327068 Vulkan: Fix sampler custom border color (#3751) 2022-10-10 08:35:44 +02:00
88a8d1e567 Fix disposed textures being updated on TextureBindingsManager (#3750)
* Fix disposed textures being updated on TextureBindingsManager

* PR feedback
2022-10-09 15:23:52 -03:00
bf77d1cab9 GPU: Pass SpanOrArray for Texture SetData to avoid copy (#3745)
* GPU: Pass SpanOrArray for Texture SetData to avoid copy

Texture data is often converted before upload, meaning that an array was allocated to perform the conversion into. However, the backend SetData methods were being passed a Span of that data, and the Multithreaded layer does `ToArray()` on it so that it can be stored for later! This method can't extract the original array, so it creates a copy.

This PR changes the type passed for textures to a new ref struct called SpanOrArray, which is backed by either a ReadOnlySpan or an array. The benefit here is that we can have a ToArray method that doesn't copy if it is originally backed by an array.

This will also avoid a copy when running the ASTC decoder.

On NieR this was taking 38% of texture upload time, which it does a _lot_ of when you move between areas, so there should be a 1.6x performance boost when strictly uploading textures. No doubt this will also improve texture streaming performance in UE4 games, and maybe a small reduction with video playback.

From the numbers, it's probably possible to improve the upload rate by a further 1.6x by performing layout conversion on GPU. I'm not sure if we could improve it further than that - multithreading conversion on CPU would probably result in memory bottleneck.

This doesn't extend to buffers, since we don't convert their data on the GPU emulator side.

* Remove implicit cast to array.
2022-10-08 12:04:47 -03:00
1ca0517c99 Vulkan: Fix some issues with CacheByRange (#3743)
* Fix some issues with CacheByRange

- Cache now clears under more circumstances, the most important being the fast path write.
- Cache supports partial clear which should help when more buffers join.
- Fixed an issue with I8->I16 conversion where it wouldn't register the buffer for use on dispose.

Should hopefully fix issues with https://github.com/Ryujinx/Ryujinx-Games-List/issues/4010 and maybe others.

* Fix collection modified exception

* Fix accidental use of parameterless constructor

* Replay DynamicState when restoring from helper shader
2022-10-08 11:28:27 -03:00
599d485bff Change NvMap ID allocation to match nvservices (#3741)
* Change NvMap ID allocation to match nvservices

* Move NvMapIdDictionary to Types
2022-10-05 17:49:18 -03:00
60e16c15b6 Fix memory corruption in BCAT and FS Read methods when buffer is larger than needed (#3739)
* Fix memory corruption in FS Read methods when buffer is larger than needed

* PR feedback

* nit: Don't move this around
2022-10-04 20:12:54 -03:00
2068445939 Fix shader SULD (bindless) instruction using wrong register as handle (#3732)
* GLSL: Do not generate scale helpers if we have no textures

* Fix shader SULD (bindless) instruction using wrong register as handle
2022-10-03 20:40:22 -03:00
a4fc9f8050 Support use of buffer ranges with size 0 (#3736) 2022-10-03 20:08:38 -03:00
5437d6cb13 Vulkan: Fix buffer texture storage not being updated on buffer handle reuse (#3731) 2022-10-03 19:45:33 -03:00
7539e26144 Avalonia - Fixes updater (#3670)
* update avalonia

* fix updater

* fix spacing

* addressed review

* convert permission value to octal

* Add missing comma

* revert package updates
2022-10-03 11:25:25 -03:00
1c3697b6a4 Update AboutWindow.axaml (#3724) 2022-10-02 22:02:11 +00:00
81f848e54f Allow Surface Flinger frame enqueue after process has exited (#3733) 2022-10-02 21:50:03 +00:00
358a781639 Volume Hotkeys (#3500)
* Initial GTK implementation

* Less messy and Avalonia imp

* Move clamping to HLE and streamline imps

* Make viewmodel update consistent

* Fix rebase and add an english locale.

Co-authored-by: Mary-nyan <mary@mary.zone>
2022-10-02 09:38:37 +00:00
45ce540b9b ARMeilleure: Add gfni acceleration (#3669)
* ARMeilleure: Add `GFNI` detection

This is intended for utilizing the `gf2p8affineqb` instruction

* ARMeilleure: Add `gf2p8affineqb`

Not using the VEX or EVEX-form of this instruction is intentional. There
are `GFNI`-chips that do not support AVX(so no VEX encoding) such as
Tremont(Lakefield) chips as well as Jasper Lake.

13df339fe7/GenuineIntel/GenuineIntel00806A1_Lakefield_LC_InstLatX64.txt (L1297-L1299)

13df339fe7/GenuineIntel/GenuineIntel00906C0_JasperLake_InstLatX64.txt (L1252-L1254)

* ARMeilleure: Add `gfni` acceleration of `Rbit_V`

Passes all `Rbit_V*` unit tests on my `i9-11900k`

* ARMeilleure: Add `gfni` acceleration of `S{l,r}i_V`

Also added a fast-path for when the shift amount is greater than the
size of the element.

* ARMeilleure: Add `gfni` acceleration of `Shl_V` and `Sshr_V`

* ARMeilleure: Increment InternalVersion

* ARMeilleure: Fix Intrinsic and Assembler Table alignment

`gf2p8affineqb` is the longest instruction name I know of. It shouldn't
get any wider than this.

* ARMeilleure: Remove SSE2+SHA requirement for GFNI

* ARMeilleure Add `X86GetGf2p8LogicalShiftLeft`

Used to generate GF(2^8) 8x8 bit-matrices for bit-shifting for the `gf2p8affineqb` instruction.

* ARMeilleure: Append `FeatureInfo7Ecx` to `FeatureInfo`
2022-10-02 11:17:19 +02:00
96bf7f8522 Avoid allocating unmanaged string per shader (#3730)
* Avoid reallocating same unmanaged string per shader

* Address PR feedback

* Rename to _disposed
2022-10-02 10:59:34 +02:00
33e673ceb8 fatal: Implement Service (#3573)
* fatal: Implement Service

This PR adds a basic implementation of fatal service, guest processes call it when there is something wrong. But since we can already have all informations by debugging it's not really useful.
In any case, that's avoid an unimplemented service exception. Structs/Enum are based on Atmosphère source code.

After logs the error report, I call SvcBreak. Feedbacks are welcome on this, since some guests calls it right after fatal service so I can remove it if needed.

* Addresses gdkchan feedback
2022-10-02 10:30:46 +02:00
9c2500de5f Fix incorrect tessellation inputs/outputs (#3728)
* Fix incorrect tessellation inputs/outputs

* Shader cache version bump
2022-10-01 02:35:52 -03:00
dbe43c1719 Fix SSL GetCertificates with certificate ID set to All (#3727)
* Fix SSL GetCertificates with certificate ID set to All

* Fix last entry status value
2022-09-29 12:45:25 -03:00
f502cfaf62 Vulkan: Zero blend state when disabled or write mask is 0 (#3719)
* Zero blend state when disabled or write mask is 0

Any difference in the blend state when blend is disabled is meaningless, but Ryujinx would compare different disabled blends and compile them as separate pipelines. This change ensures that all pipelines where blend state is meaningless record it as such, which avoids compiling a bunch of pipelines that are essentially identical.

The NVIDIA driver is pretty forgiving when it comes to silly pipeline misses like this, but other drivers don't offer the same level of kindness.

This should reduce stuttering on those drivers, and might improve overall performance very slightly due to less pipeline variants being in the hash table.

* Fix blend possibly being wrong when an attachment is unmasked
2022-09-29 12:32:49 -03:00
1fd5cf2b4a Fix ListOpenContextStoredUsers and stub LoadOpenContext (#3718)
* Fix ListOpenContextStoredUsers and stub LoadOpenContext

* Remove nonsensical comment
2022-09-27 21:24:52 -03:00
814f75142e Fpsr and Fpcr freed. (#3701)
* Implemented in IR the managed methods of the Saturating region ...

... of the SoftFallback class (the SatQ ones).

The need to natively manage the Fpcr and Fpsr system registers is still a fact.

Contributes to https://github.com/Ryujinx/Ryujinx/issues/2917 ; I will open another PR to implement in Intrinsics-branchless the methods of the Saturation region as well (the SatXXXToXXX ones).

All instructions involved have been tested locally in both release and debug modes, in both lowcq and highcq.

* Ptc.InternalVersion = 3665

* Addressed PR feedback.

* Implemented in IR the managed methods of the ShlReg region of the SoftFallback class.

It also includes the last two SatQ ones (following up on https://github.com/Ryujinx/Ryujinx/pull/3665).

All instructions involved have been tested locally in both release and debug modes, in both lowcq and highcq.

* Fpsr and Fpcr freed.

Handling/isolation of Fpsr and Fpcr via register for IR and via memory for Tests and Threads, with synchronization to context exchanges (explicit for SoftFloat); without having to call managed methods. Thanks to the inlining work of the previous two PRs and others in this.

Tests performed locally in both release and debug modes, in both lowcq and highcq, with FastFP to true and false (explicit FP tests included). Tested with the title Tony Hawk's PS.

Depends on shlreg.

* Update InstEmitSimdHelper.cs

* De-magic Masks.

Remove the Stride and Len flags; Fpsr.NZCV are A32 only, then moved to Fpscr: this leads to emitting less IR in reference to Get/Set Fpsr/Fpcr/Fpscr methods in reference to Mrs/Msr (A64) and Vmrs/Vmsr (A32) instructions.

* Addressed PR feedback.
2022-09-20 18:55:13 -03:00
4c0eb91d7e Convert Quads to Triangles in Vulkan (#3715)
* Add Index Buffer conversion for quads to Vulkan

Also adds a reusable repeating pattern index buffer to use for non-indexed
draws, and generalizes the conversion cache for buffers.

* Fix some issues

* End render pass before conversion

* Resume transform feedback after we ensure we're in a pass.

* Always generate UInt32 type indices for topology conversion

* No it's not.

* Remove unused code

* Rely on TopologyRemap to convert quads to tris.

* Remove double newline

* Ensure render pass ends before stride or I8 conversion
2022-09-20 18:38:48 -03:00
da75a9a6ea OpenGL: Fix blit from non-multisample to multisample texture (#3596)
* OpenGL: Fix blit from non-multisample to multisample texture

* New approach for multisample copy using compute shaders
2022-09-19 16:12:56 -03:00
41790aa743 Avalonia - Misc changes to UX (#3643)
* Change navbar from compact to default and force text overflow globally

* Fix settings window

* Fix right stick control alignment

* Initialize value and add logging for SDL IDs

* Fix alignment of setting text and improve borders

* Clean up padding and size of buttons on controller settings

* Fix right side trigger alignment and correct styling

* Revert axaml alignment

* Fix alignment of volume widget

* Fix timezone autocompletebox dropdown height

* MainWindow: Line up volume status bar item

* Remove margins and add padding to volume widget

* Make volume text localizable.

Co-authored-by: merry <git@mary.rs>
2022-09-19 16:04:22 -03:00
0cb1e926b5 Allow bindless textures with handles from unbound constant buffer (#3706) 2022-09-19 15:35:47 -03:00
6f0395538b Avalonia - Use embedded window for avalonia (#3674)
* wip

* use embedded window

* fix race condition on opengl Windows

* fix glx issues on prime nvidia

* fix mouse support win32

* clean up

* addressed review

* addressed review

* fix warnings

* fix sotware keyboard dialog

* Update Ryujinx.Ava/Ui/Applet/SwkbdAppletDialog.axaml.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* remove double semi

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2022-09-19 15:05:26 -03:00
b9f1ff3c77 Implemented in IR the managed methods of the ShlReg region of the SoftFallback class. (#3700)
* Implemented in IR the managed methods of the Saturating region ...

... of the SoftFallback class (the SatQ ones).

The need to natively manage the Fpcr and Fpsr system registers is still a fact.

Contributes to https://github.com/Ryujinx/Ryujinx/issues/2917 ; I will open another PR to implement in Intrinsics-branchless the methods of the Saturation region as well (the SatXXXToXXX ones).

All instructions involved have been tested locally in both release and debug modes, in both lowcq and highcq.

* Ptc.InternalVersion = 3665

* Addressed PR feedback.

* Implemented in IR the managed methods of the ShlReg region of the SoftFallback class.

It also includes the last two SatQ ones (following up on https://github.com/Ryujinx/Ryujinx/pull/3665).

All instructions involved have been tested locally in both release and debug modes, in both lowcq and highcq.

* Update InstEmitSimdHelper.cs
2022-09-19 14:49:10 -03:00
a77af4c5e9 Readme: Fix broken shell image (#3708) 2022-09-19 14:06:00 +02:00
fbcf802fbc A32/T32/A64: Implement Hint instructions (CSDB, SEV, SEVL, WFE, WFI, YIELD) (#3694)
* OpCodeTable: Implement Hint instructions (CSDB, SEV, SEVL, WFE, WFI, YIELD)

* A64: Remove catch-all Hint instruction

* T16: Handle unallocated hint instructions

Some thumb tests execute these assuming that they're nops.

* T32: Fill out other Hint instructions

* A32: Fill out other hint instructions
2022-09-14 18:18:15 -03:00
c3c41fa4bb Periodically Flush Commands for Vulkan (#3689)
* Periodically Flush Commands for Vulkan

NVIDIA's OpenGL driver has a built-in mechanism to automatically flush commands to GPU when a lot have been queued. It's also pretty inconsistent, but we'll ignore that for now.

Our Vulkan implementation only submits a command buffer (flush equivalent) when it needs to. This is typically when another command buffer needs to be sequenced after it, presenting a frame, or an edge case where we flush around GPU queries to get results sooner.

This difference in flush behaviour causes a notable difference between Vulkan and OpenGL when we have to wait for commands. In the worst case, we will wait for a sync point that has just been created. In Vulkan, this sync point is created by flushing the command buffer, and storing a waitable fence that signals its completion. Our command buffer contains _every command that we queued since the last submit_, which could be an entire frame's worth of draws.

This has a huge effect on CPU <-> GPU latency. The more commands in a command buffer, the longer we have to wait for it to complete, which results in wasted time. Because we don't know when the guest will force us to wait, we always want the smallest possible latency.

By periodically flushing, we ensure that each command buffer takes a more consistent, smaller amount of time to execute, and that the back of the GPU queue isn't as far away when we need to wait for something to happen. This also might reduce time that the GPU is left inactive while commands are being built.

The main affected game is Pokemon Sword, which got significantly faster in overworld areas due to reduced waiting time when it flushes a shadow map from the main GPU thread.

Another affected game is BOTW, which gets faster depending on the area. This game flushes textures/buffers from its game thread, which is the bottleneck.

Flush latency and throughput may be improved on other games that are inexplicably slower than OpenGL. It's possible that certain games could have their performance _decreased_ slightly due to flushes not being free, but it is unlikely.

Also, flushing to get query results sooner has been tweaked to improve the number of full draw skips that can be done. (tested in SMO)

* Remove unused variable

* Fix possible issue with early query flush
2022-09-14 13:48:31 -03:00
356e480bf5 Fix partial unmap reprotection on Windows (#3702) 2022-09-14 17:46:37 +02:00
8e119a1e96 Implement PLD and SUB (imm16) on T32, plus UADD8, SADD8, USUB8 and SSUB8 on both A32 and T32 (#3693) 2022-09-13 19:51:40 -03:00
e05bf90af6 T32: Implement Asimd instructions (#3692) 2022-09-13 18:25:37 -03:00
66f16f4392 Fix bindless 1D textures having a buffer type on the shader (#3697)
* Fix bindless 1D textures having a buffer type on the shader

* Shader cache version bump
2022-09-13 08:53:55 +02:00
729ff5337c Fix increment on Arm32 NEON VLDn/VSTn instructions with regs > 1 (#3695)
* Fix increment on Arm32 NEON VLDn/VSTn instructions with regs > 1

* PPTC version bump

* PR feedback
2022-09-13 08:24:09 +02:00
2492e7e808 Fix R4G4B4A4 format on Vulkan (#3696) 2022-09-13 07:59:38 +02:00
36172ab43b Scale SamplesPassed counter by RT scale on report (#3680)
* Scale SamplesPassed counter by RT scale on report

Adds a scale factor for samples passed counter report based on the render target scale at the time. This ensures that when a game reads this counter, it appears similar to the result at 1x.

This doesn't cover cases where the the render target scale changes during the queried draws, though that might be better to handle along with other scope related issues in a future rework of counters. Games generally don't count for occlusion queries over render target changes anyways.

Fixes an issue in the Splatoon games where the special charge would scale too quickly at high res, points at the end of the game would be broken (but still provide a correct winner), and playing at a low res would make it impossible to swim in ink.

May also affect LOD scaling in The Witcher 3.

* Update Ryujinx.Graphics.Gpu/Engine/Threed/SemaphoreUpdater.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2022-09-11 15:58:15 +00:00
4d69286a9c Implement VRINT (vector) Arm32 NEON instructions (#3691) 2022-09-11 15:44:27 +00:00
1529e6cf0d T32: Add Vfp instructions (#3690) 2022-09-10 23:03:14 -03:00
f468db7602 Implement Thumb (32-bit) memory (ordered), multiply, extension and bitfield instructions (#3687)
* Implement Thumb (32-bit) memory (ordered), multiply and bitfield instructions

* Remove public from interface

* Fix T32 BL immediate and implement signed and unsigned extend instructions
2022-09-10 22:51:00 -03:00
gdk
c5f1d1749a Revert address space mirror changes 2022-09-10 16:23:49 +02:00
gdk
7dd69f2d0e Allocation free tree lookup 2022-09-10 16:23:49 +02:00
gdk
c646638680 Update several methods to use GetNode directly and avoid array allocations 2022-09-10 16:23:49 +02:00
gdk
65f2a82b97 Optimize PlaceholderManager.UnreserveRange 2022-09-10 16:23:49 +02:00
gdk
93dd6d525a Fix potential issue with partial unmap
We must also do the unmap operation with the RWLock, otherwise faults on the unmapped region will cause crashes and the whole thing becomes pointless
2022-09-10 16:23:49 +02:00
gdk
96d4ad952c Fix reprotection regression 2022-09-10 16:23:49 +02:00
gdk
6a07f80b76 Make RBTree node fields internal again
Prevents someone from accidentaly messing with them and leaving the tree in a invalid state
2022-09-10 16:23:49 +02:00
gdk
22214ac664 Delete unused code 2022-09-10 16:23:49 +02:00
gdk
45e520a27c Rewrite PlaceholderManager4KB to use intrusive RBTree, and to coalesce free placeholders
Also make the other placeholder manager use intrusive RBTree, allows the IntervalTree that was added just for this to be deleted
2022-09-10 16:23:49 +02:00
gdk
5b5810a46a Defer address space mirror mapping and use it only if strictly needed 2022-09-10 16:23:49 +02:00
619ac86bd0 Do not output ViewportIndex on SPIR-V if GPU does not support it (#3644)
* Do not output ViewportIndex on SPIR-V if GPU does not support it

* Bump shader cache version
2022-09-10 13:20:23 +00:00
7a1ab71c73 Update README.MD verbiage and compatibility 2022-09-10 15:07:37 +02:00
dc4ba3993b Rebind textures if format changes or they're buffer textures 2022-09-10 14:12:50 +02:00
81f1a4dc31 Allocate work buffer for audio renderer instead of using guest supplied memory (#3276)
* Allocate work buffer for audio renderer instead of using guest supplied memory

* Typo

* Use GC.AllocateArray to allocate pinned array
2022-09-10 01:16:24 +00:00
c64524a240 Add ADD (zx imm12), NOP, MOV (rs), LDA, TBB, TBH, MOV (zx imm16) and CLZ thumb instructions (#3683)
* Add ADD (zx imm12), NOP, MOV (register shifted), LDA, TBB, TBH, MOV (zx imm16) and CLZ thumb instructions, fix LDRD, STRD, CBZ, CBNZ and BLX (reg)

* Bump PPTC version
2022-09-09 22:09:11 -03:00
db45688aa8 Implement VRSRA, VRSHRN, VQSHRUN, VQMOVN, VQMOVUN, VQADD, VQSUB, VRHADD, VPADDL, VSUBL, VQDMULH and VMLAL Arm32 NEON instructions (#3677)
* Implement VRSRA, VRSHRN, VQSHRUN, VQMOVN, VQMOVUN, VQADD, VQSUB, VRHADD, VPADDL, VSUBL, VQDMULH and VMLAL Arm32 NEON instructions

* PPTC version

* Fix VQADD/VQSUB

* Improve MRC/MCR handling and exception messages

In case data is being recompiled as code, we don't want to throw at emit stage, instead we should only throw if it actually tries to execute
2022-09-09 21:47:38 -03:00
c6d82209ab Restride vertex buffer when stride causes attributes to misalign in Vulkan. (#3679)
* Vertex Buffer Alignment part 1

* Update CacheByRange

* Add Stride Change compute shader, fix storage buffers in helpers

* An AMD exclusive

* Reword

* Change rules - stride conversion when attrs misalign

* Fix stupid mistake

* Fix background pipeline compile

* Improve a few things.

* Fix some feedback

* Address Feedback

(the shader binary didn't change when i changed the source to use the subgroup size)

* Fix bug where rewritten buffer would be disposed instantly.
2022-09-08 20:30:19 -03:00
ee1825219b Clean up rejit queue (#2751) 2022-09-08 20:14:08 -03:00
7baa08dcb4 Implemented in IR the managed methods of the Saturating region ... (#3665)
* Implemented in IR the managed methods of the Saturating region ...

... of the SoftFallback class (the SatQ ones).

The need to natively manage the Fpcr and Fpsr system registers is still a fact.

Contributes to https://github.com/Ryujinx/Ryujinx/issues/2917 ; I will open another PR to implement in Intrinsics-branchless the methods of the Saturation region as well (the SatXXXToXXX ones).

All instructions involved have been tested locally in both release and debug modes, in both lowcq and highcq.

* Ptc.InternalVersion = 3665

* Addressed PR feedback.
2022-09-08 19:40:41 -03:00
408bd63b08 Transform shader LDC into constant buffer access if offset is constant (#3672)
* Transform shader LDC into constant buffer access if offset is constant

* Shader cache version bump
2022-09-07 20:25:22 -03:00
df99257d7f bsd: improve socket poll
We should report errors even when not requested.

This also ensure we only clear the bits that were requested on the output.

Finally, this fix when input events is 0.
2022-09-07 22:58:41 +02:00
f3835dc78b bsd: implement SendMMsg and RecvMMsg (#3660)
* bsd: implement sendmmsg and recvmmsg

* Fix wrong increment of vlen
2022-09-07 22:37:15 +02:00
51bb8707ef Update bug report template (#3676)
Adds some verbiage to indicate that game-specific issues should be posted instead on the game compatibility list, unless it is a provable regression.
2022-09-06 22:30:07 +02:00
5ff5fe47ba Bsd: Fix NullReferenceException in BsdSockAddr.FromIPEndPoint() (#3652)
* Bsd: Fix NullReferenceException in BsdSockAddr.FromIPEndPoint()

Allows "Victor Vran Overkill Edition" to boot with guest internet access enabled.
Thanks to EmulationFanatic for testing this for me!

* Bsd: Return proper error code if RemoteEndPoint is null

* Remove whitespace from empty line

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2022-09-01 22:04:01 +00:00
38275f9056 Change vsync signal to happen at 60hz, regardless of swap interval (#3642)
* Change vsync signal to happen at 60hz, regardless of swap interval

* Update Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Fix softlock when toggling vsync

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2022-09-01 17:57:50 -03:00
67cbdc3a6a bsd: Fix Poll(0) returning ETIMEDOUT instead of SUCCESS
This was an oversight of the implementation.
2022-09-01 21:46:11 +02:00
131b43170e sfdsnres: fix endianess issue for port serialisation 2022-09-01 21:31:20 +02:00
730d2f4b9b Address gdkchan's comment 2022-08-31 21:33:03 +02:00
f6a7309b14 account: Implement LoadNetworkServiceLicenseKindAsync
This is needed to run Pokemon Legends Arceus 1.1.1 with guest internet enabled.

The game still get stuck at loading screen.
2022-08-31 21:33:03 +02:00
472a621589 Bsd: Fix ArgumentOutOfRangeException in SetSocketOption (#3633)
* Bsd: Fix ArgumentOutOfRangeException in SetSocketOption

* Ensure option level is Socket before checking for SoLinger
2022-08-28 14:24:19 +00:00
311c2661b8 Replace image format magic numbers with enums (#3631)
* Replace magic constants with enums

* Extra formatting

* Lower case ASTC dimensions

* Use uint for VertexAttributeFormat
2022-08-28 01:56:26 +00:00
a92e2028cb Updates Japanese localization for the Avalonia UI (#3635) 2022-08-27 07:01:30 +00:00
6922862db8 Optimize kernel memory block lookup and consolidate RBTree implementations (#3410)
* Implement intrusive red-black tree, use it for HLE kernel block manager

* Implement TreeDictionary using IntrusiveRedBlackTree

* Implement IntervalTree using IntrusiveRedBlackTree

* Implement IntervalTree (on Ryujinx.Memory) using IntrusiveRedBlackTree

* Make PredecessorOf and SuccessorOf internal, expose Predecessor and Successor properties on the node itself

* Allocation free tree node lookup
2022-08-26 18:21:48 +00:00
6592d64751 Update Turkish Translation (#3498)
Translated newly added lines and polished older entries.
2022-08-26 18:00:17 +00:00
8001c832d9 Update de_DE.json (#3502)
* Update de_DE.json

* Update de_DE.json

* Update de_DE.json

* Update de_DE.json

* Update de_DE.json

* Update de_DE.json

* Update de_DE.json

* Another one

* Update de_DE.json

* addressed reviews

Co-Authored-By: Miepee <38186597+Miepee@users.noreply.github.com>

* welp

Co-Authored-By: Miepee <38186597+Miepee@users.noreply.github.com>

* Update de_DE.json

* Update de_DE.json

quick update with the latest changes

Co-Authored-By: Miepee <38186597+Miepee@users.noreply.github.com>

* Update de_DE.json

Co-Authored-By: Miepee <38186597+Miepee@users.noreply.github.com>

Co-authored-by: Miepee <38186597+Miepee@users.noreply.github.com>
Co-authored-by: reloxx13 <reloxx@interia.pl>
2022-08-26 19:49:05 +02:00
87919b193c Update zh_CN.json (#3598)
* Update zh_CN.json

* Update zh_CN.json

* Update zh_CN.json

* Update zh_CN.json

* Delete zh_CN.json

* fix crash

* Update zh_CN.json

* Update zh_CN.json

* Update zh_CN.json

* Update zh_CN.json

* Update zh_CN.json
2022-08-26 19:36:42 +02:00
8de033e60e Avalonia - Add Polish Translation (#3569)
* Update Ryujinx.Ava.csproj

* Update MainWindow.axaml

* Create pl_PL.json

* Update pl_PL.json

* Update pl_PL.json

* Update pl_PL.json

* Update pl_PL.json

* PPTC wording changes

adding PPTC changes

Co-authored-by: Clara <moonbowjelly@gmail.com>
2022-08-26 19:24:59 +02:00
90432946ac Avalonia - Display language names in their corresponding language under "Change Language" (#3490)
* change languages to their native names

* fix Chinese language names

* Update MainWindow.axaml
2022-08-26 19:12:11 +02:00
9bad71afbf bsd: Fix Poll writting in input buffer (#3630)
This is a very old oversight on our Poll implementation.
This worked so far reliably because games and homebrews pass the same
buffer as input and output.
2022-08-26 18:10:45 +02:00
923089a298 Fast path for Inline-to-Memory texture data transfers (#3610)
* Fast path for Inline-to-Memory texture data transfers

* Only do it for block linear textures to be on the safe side
2022-08-26 02:16:41 +00:00
d9aa15eb24 pctl: Implement EndFreeCommunication
This PR Implement `EndFreeCommunication` (checked by RE). Nothing more.

Closes #2420
2022-08-25 23:18:37 +02:00
1578 changed files with 83073 additions and 36446 deletions

View File

@ -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

61
.gitattributes vendored
View File

@ -1,63 +1,4 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
* text=auto eol=lf

View File

@ -1,43 +0,0 @@
---
name: Bug Report
about: Something doesn't work correctly in Ryujinx.
#assignees:
---
## Bug Report
[ If any section does not apply, replace its contents with "N/A". ]</br>
[ Lines between [ ] (square brackets) should be removed before posting. ]
### What's the issue you encountered?
[ Describe the issue in detail and what you were doing beforehand. ]</br>
[ Did you make any changes related to Ryujinx itself? ]</br>
[ If so, make sure to include details relating to what exactly you changed. ]
### How can the issue be reproduced?
[ Include a detailed step by step process for recreating your issue. ]
### Log file
[ Logs files can be found under ``Logs`` folder in Ryujinx program folder. ]</br>
[ If you don't include a crash report in instances of crash related issues, we will ask you one to provide one. ]
### Environment?
- Ryujinx version: 1.0.X</br>
[ Replace X's with the Ryujinx version at time of crash. ]
- Game version: X.X.X</br>
[ Replace X's with the game version at time of crash. ]
- System Specs:
- OS: *(e.g. Windows 10)*
- CPU: *(e.g. i7-6700)*
- GPU: *(e.g. NVIDIA RTX 2070)*
- RAM: *(e.g. 16GB)*
- Applied Mods : [ Yes (Which ones) / No ]
### Additional context?
Additional info about your environment:</br>
[ Any other information relevant to your issue. ]

86
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@ -0,0 +1,86 @@
name: Bug Report
description: File a bug report
title: "[Bug]"
labels: bug
body:
- type: textarea
id: issue
attributes:
label: Description of the issue
description: What's the issue you encountered?
validations:
required: true
- type: textarea
id: repro
attributes:
label: Reproduction steps
description: How can the issue be reproduced?
placeholder: Describe each step as precisely as possible
validations:
required: true
- type: textarea
id: log
attributes:
label: Log file
description: A log file will help our developers to better diagnose and fix the issue.
placeholder: Logs files can be found under "Logs" folder in Ryujinx program folder. You can drag and drop the log on to the text area
validations:
required: true
- type: input
id: os
attributes:
label: OS
placeholder: "e.g. Windows 10"
validations:
required: true
- type: input
id: ryujinx-version
attributes:
label: Ryujinx version
placeholder: "e.g. 1.0.470"
validations:
required: true
- type: input
id: game-version
attributes:
label: Game version
placeholder: "e.g. 1.1.1"
validations:
required: false
- type: input
id: cpu
attributes:
label: CPU
placeholder: "e.g. i7-6700"
validations:
required: false
- type: input
id: gpu
attributes:
label: GPU
placeholder: "e.g. NVIDIA RTX 2070"
validations:
required: false
- type: input
id: ram
attributes:
label: RAM
placeholder: "e.g. 16GB"
validations:
required: false
- type: textarea
id: mods
attributes:
label: List of applied mods
placeholder: You can list applied mods here.
validations:
required: false
- type: textarea
id: additional-context
attributes:
label: Additional context?
description: |
- Additional info about your environment:
- Any other information relevant to your issue.
validations:
required: false

View File

@ -1,34 +0,0 @@
---
name: Feature Request
about: Suggest a new feature for Ryujinx.
#assignees:
---
## Feature Request
[ If any section does not apply, replace its contents with "N/A". ]</br>
[ If you do not have the information needed for a section, replace its contents with "Unknown". ]</br>
[ Lines between [ ] (square brackets) are to be removed before posting. ]</br>
[ Please search for existing [feature requests](https://github.com/Ryujinx/Ryujinx/issues) before you make your own request. ]</br>
[ Duplicate requests will be marked as such and you will be referred to the original request. ]
### What feature are you suggesting?
#### Overview:
- [ Include the basic, high-level concepts for this feature here. ]
#### Smaller Details:
- [ These may include specific methods of implementation etc. ]
#### Nature of Request:
[ Remove all that do not apply to your request. ]
- Addition
- [ Ex: Addition of certain original features or features from other community projects. ]
- [ If you are suggesting porting features or including features from other projects, include what license they are distributed under and what, if any libraries those project use. ]
- Change
- Removal
- [Ex: Removal of certain features or implementation due to a specific issue/bug or because of low quality code, etc.]
### Why would this feature be useful?
[ If this is a feature for an end-user, how does it benefit the end-user? ]</br>
[ If this feature is for developers, what does it add to Ryujinx that did not already exist? ]

View File

@ -0,0 +1,30 @@
name: Feature Request
description: Suggest a new feature for Ryujinx.
title: "[Feature Request]"
body:
- type: textarea
id: overview
attributes:
label: Overview
description: Include the basic, high-level concepts for this feature here.
validations:
required: true
- type: textarea
id: details
attributes:
label: Smaller details
description: These may include specific methods of implementation etc.
validations:
required: true
- type: textarea
id: request
attributes:
label: Nature of request
validations:
required: true
- type: textarea
id: feature
attributes:
label: Why would this feature be useful?
validations:
required: true

View File

@ -1,34 +0,0 @@
---
name: Missing CPU Instruction
about: CPU Instruction is missing in Ryujinx.
#assignees:
---
## Missing CPU Instruction
[ If any section does not apply, replace its contents with "N/A". ]</br>
[ If you do not have the information needed for a section, replace its contents with "Unknown". ]</br>
[ Lines between [ ] (square brackets) are to be removed before posting. ]
[ Please search for existing [missing CPU instruction](https://github.com/Ryujinx/Ryujinx/issues) before you make your own issue. ]</br>
[ See the following [issue](https://github.com/Ryujinx/Ryujinx/issues/1405) as an example ]</br>
[ Duplicate issue will be marked as such and you will be referred to the original request. ]
### What CPU instruction is missing?
Requires the *INSTRUCTION* instruction.</br>
[ Replace *INSTRUCTION* by the instruction name, e.g. VADDL.U16 ]
```
*
```
[ Add the undefined instruction error message in the above code block ]
### Instruction name
```
*
```
[ Include the name from [armconverter.com](https://armconverter.com/?disasm) or [shell-storm.org](http://shell-storm.org/online/Online-Assembler-and-Disassembler/?arch=arm64&endianness=big&dis_with_raw=True&dis_with_ins=True) in the above code block ]
### Required by:
[ Add our (games list database)[https://github.com/Ryujinx/Ryujinx-Games-List/issues] links of games who require this instruction ]

View File

@ -0,0 +1,26 @@
name: Missing CPU Instruction
description: CPU Instruction is missing in Ryujinx.
title: "[CPU]"
labels: [cpu, not-implemented]
body:
- type: textarea
id: instruction
attributes:
label: CPU instruction
description: What CPU instruction is missing?
validations:
required: true
- type: textarea
id: name
attributes:
label: Instruction name
description: Include the name from [armconverter.com](https://armconverter.com/?disasm) or [shell-storm.org](http://shell-storm.org/online/Online-Assembler-and-Disassembler/?arch=arm64&endianness=big&dis_with_raw=True&dis_with_ins=True) in the above code block
validations:
required: true
- type: textarea
id: required
attributes:
label: Required by
description: Add links to the [compatibility list page(s)](https://github.com/Ryujinx/Ryujinx-Games-List/issues) of the game(s) that require this instruction.
validations:
required: true

View File

@ -1,35 +0,0 @@
---
name: Missing Service Call
about: Service call is missing in Ryujinx.
#assignees:
---
## Missing Service Call
[ If any section does not apply, replace its contents with "N/A". ]</br>
[ If you do not have the information needed for a section, replace its contents with "Unknown". ]</br>
[ Lines between [ ] (square brackets) are to be removed before posting. ]
[ Please search for existing [missing service call](https://github.com/Ryujinx/Ryujinx/issues) before you make your own issue. ]</br>
[ See the following [issue](https://github.com/Ryujinx/Ryujinx/issues/1431) as an example ]</br>
[ Duplicate issue will be marked as such and you will be referred to the original request. ]
### What service call is missing?
*SERVICE* *INTERFACE*: *NUMBER* (*NAME*) is not implemented.</br>
[ Replace *SERVICE* by the service name, e.g. appletAE ]</br>
[ Replace *INTERFACE* by the interface name, e.g. IAllSystemAppletProxiesService ]</br>
[ Replace *NUMBER* by the call number, e.g. 100 ]</br>
[ Replace *NAME* by the call name, e.g. OpenSystemAppletProxy ]</br>
[ e.g. appletAE IAllSystemAppletProxiesService: 100 (OpenSystemAppletProxy) ]
[ Add related links to the specific call from [Switchbrew](https://switchbrew.org/w/index.php?title=Services_API) and/or [SwIPC](https://reswitched.github.io/SwIPC/) ]
### Service description
```
*
```
[ Include the description/explanation from [Switchbrew](https://switchbrew.org/w/index.php?title=Services_API) and/or [SwIPC](https://reswitched.github.io/SwIPC/) in the above code block ]
### Required by:
[ Add our (games list database)[https://github.com/Ryujinx/Ryujinx-Games-List/issues] links of games who require this call ]

View File

@ -0,0 +1,25 @@
name: Missing Service Call
description: Service call is missing in Ryujinx.
labels: not-implemented
body:
- type: textarea
id: instruction
attributes:
label: Service call
description: What service call is missing?
validations:
required: true
- type: textarea
id: name
attributes:
label: Service description
description: Include the description/explanation from [Switchbrew](https://switchbrew.org/w/index.php?title=Services_API) and/or [SwIPC](https://reswitched.github.io/SwIPC/) in the above code block
validations:
required: true
- type: textarea
id: required
attributes:
label: Required by
description: Add links to the [compatibility list page(s)](https://github.com/Ryujinx/Ryujinx-Games-List/issues) of the game(s) that require this service.
validations:
required: true

24
.github/dependabot.yml vendored Normal file
View 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

View File

@ -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

View File

@ -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});
}

View File

@ -11,6 +11,7 @@ on:
- '*.yml'
- 'README.md'
concurrency: release
jobs:
release:
@ -25,35 +26,31 @@ 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: |
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' Ryujinx.Common/ReleaseInformations.cs
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' Ryujinx.Common/ReleaseInformations.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' Ryujinx.Common/ReleaseInformations.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' Ryujinx.Common/ReleaseInformations.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' Ryujinx.Common/ReleaseInformations.cs
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' Ryujinx.Common/ReleaseInformation.cs
shell: bash
- name: Create output dir
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,22 +68,34 @@ 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: |
pushd publish_linux
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
tar --exclude "publish/Ryujinx" --exclude "publish/Ryujinx.sh" -cvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar publish
python3 ../distribution/misc/add_tar_exec.py ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx" "publish/Ryujinx"
python3 ../distribution/misc/add_tar_exec.py ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx.sh" "publish/Ryujinx.sh"
gzip -9 < ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar > ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz
rm ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar
popd
pushd publish_linux_sdl2_headless
tar -czvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
tar --exclude "publish/Ryujinx.Headless.SDL2" --exclude "publish/Ryujinx.sh" -cvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar publish
python3 ../distribution/misc/add_tar_exec.py ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx.Headless.SDL2" "publish/Ryujinx.Headless.SDL2"
python3 ../distribution/misc/add_tar_exec.py ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx.sh" "publish/Ryujinx.sh"
gzip -9 < ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar > ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz
rm ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar
popd
pushd publish_linux_ava
tar -czvf ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
tar --exclude "publish/Ryujinx.Ava" --exclude "publish/Ryujinx.sh" -cvf ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar publish
python3 ../distribution/misc/add_tar_exec.py ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx.Ava" "publish/Ryujinx.Ava"
python3 ../distribution/misc/add_tar_exec.py ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx.sh" "publish/Ryujinx.sh"
gzip -9 < ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar > ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz
rm ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar
popd
shell: bash

6
.gitignore vendored
View File

@ -125,6 +125,9 @@ ClientBin/
packages/*
*.config
# Include nuget.config
!nuget.config
# RIA/Silverlight projects
Generated_Code/
@ -167,3 +170,6 @@ launchSettings.json
# NetCore Publishing Profiles
PublishProfiles/
# Glade backup files
*.glade~

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
@ -9,4 +9,17 @@
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
</ItemGroup>
<ItemGroup>
<ContentWithTargetPath Include="Native\libs\libarmeilleure-jitsupport.dylib" Condition="'$(RuntimeIdentifier)' == '' OR '$(RuntimeIdentifier)' == 'osx-arm64'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>libarmeilleure-jitsupport.dylib</TargetPath>
</ContentWithTargetPath>
</ItemGroup>
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Ryujinx.Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
</Project>

View File

@ -0,0 +1,270 @@
using ARMeilleure.CodeGen.Optimizations;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System.Collections.Generic;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
namespace ARMeilleure.CodeGen.Arm64
{
static class Arm64Optimizer
{
private const int MaxConstantUses = 10000;
public static void RunPass(ControlFlowGraph cfg)
{
var constants = new Dictionary<ulong, Operand>();
Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source)
{
// If the constant has many uses, we also force a new constant mov to be added, in order
// to avoid overflow of the counts field (that is limited to 16 bits).
if (!constants.TryGetValue(source.Value, out var constant) || constant.UsesCount > MaxConstantUses)
{
constant = Local(source.Type);
Operation copyOp = Operation(Instruction.Copy, constant, source);
block.Operations.AddBefore(operation, copyOp);
constants[source.Value] = constant;
}
return constant;
}
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
{
constants.Clear();
Operation nextNode;
for (Operation node = block.Operations.First; node != default; node = nextNode)
{
nextNode = node.ListNext;
// Insert copies for constants that can't fit on a 32-bit immediate.
// Doing this early unblocks a few optimizations.
if (node.Instruction == Instruction.Add)
{
Operand src1 = node.GetSource(0);
Operand src2 = node.GetSource(1);
if (src1.Kind == OperandKind.Constant && (src1.Relocatable || ConstTooLong(src1, OperandType.I32)))
{
node.SetSource(0, GetConstantCopy(block, node, src1));
}
if (src2.Kind == OperandKind.Constant && (src2.Relocatable || ConstTooLong(src2, OperandType.I32)))
{
node.SetSource(1, GetConstantCopy(block, node, src2));
}
}
// Try to fold something like:
// lsl x1, x1, #2
// add x0, x0, x1
// ldr x0, [x0]
// add x2, x2, #16
// ldr x2, [x2]
// Into:
// ldr x0, [x0, x1, lsl #2]
// ldr x2, [x2, #16]
if (IsMemoryLoadOrStore(node.Instruction))
{
OperandType type;
if (node.Destination != default)
{
type = node.Destination.Type;
}
else
{
type = node.GetSource(1).Type;
}
Operand memOp = GetMemoryOperandOrNull(node.GetSource(0), type);
if (memOp != default)
{
node.SetSource(0, memOp);
}
}
}
}
Optimizer.RemoveUnusedNodes(cfg);
}
private static Operand GetMemoryOperandOrNull(Operand addr, OperandType type)
{
Operand baseOp = addr;
// First we check if the address is the result of a local X with immediate
// addition. If that is the case, then the baseOp is X, and the memory operand immediate
// becomes the addition immediate. Otherwise baseOp keeps being the address.
int imm = GetConstOp(ref baseOp, type);
if (imm != 0)
{
return MemoryOp(type, baseOp, default, Multiplier.x1, imm);
}
// Now we check if the baseOp is the result of a local Y with a local Z addition.
// If that is the case, we now set baseOp to Y and indexOp to Z. We further check
// if Z is the result of a left shift of local W by a value == 0 or == Log2(AccessSize),
// if that is the case, we set indexOp to W and adjust the scale value of the memory operand
// to match that of the left shift.
// There is one missed case, which is the address being a shift result, but this is
// probably not worth optimizing as it should never happen.
(Operand indexOp, Multiplier scale) = GetIndexOp(ref baseOp, type);
// If baseOp is still equal to address, then there's nothing that can be optimized.
if (baseOp == addr)
{
return default;
}
return MemoryOp(type, baseOp, indexOp, scale, 0);
}
private static int GetConstOp(ref Operand baseOp, OperandType accessType)
{
Operation operation = GetAsgOpWithInst(baseOp, Instruction.Add);
if (operation == default)
{
return 0;
}
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
Operand constOp;
Operand otherOp;
if (src1.Kind == OperandKind.Constant && src2.Kind == OperandKind.LocalVariable)
{
constOp = src1;
otherOp = src2;
}
else if (src1.Kind == OperandKind.LocalVariable && src2.Kind == OperandKind.Constant)
{
constOp = src2;
otherOp = src1;
}
else
{
return 0;
}
// If we have addition by a constant that we can't encode on the instruction,
// then we can't optimize it further.
if (ConstTooLong(constOp, accessType))
{
return 0;
}
baseOp = otherOp;
return constOp.AsInt32();
}
private static (Operand, Multiplier) GetIndexOp(ref Operand baseOp, OperandType accessType)
{
Operand indexOp = default;
Multiplier scale = Multiplier.x1;
Operation addOp = GetAsgOpWithInst(baseOp, Instruction.Add);
if (addOp == default)
{
return (indexOp, scale);
}
Operand src1 = addOp.GetSource(0);
Operand src2 = addOp.GetSource(1);
if (src1.Kind != OperandKind.LocalVariable || src2.Kind != OperandKind.LocalVariable)
{
return (indexOp, scale);
}
baseOp = src1;
indexOp = src2;
Operation shlOp = GetAsgOpWithInst(src1, Instruction.ShiftLeft);
bool indexOnSrc2 = false;
if (shlOp == default)
{
shlOp = GetAsgOpWithInst(src2, Instruction.ShiftLeft);
indexOnSrc2 = true;
}
if (shlOp != default)
{
Operand shSrc = shlOp.GetSource(0);
Operand shift = shlOp.GetSource(1);
int maxShift = Assembler.GetScaleForType(accessType);
if (shSrc.Kind == OperandKind.LocalVariable &&
shift.Kind == OperandKind.Constant &&
(shift.Value == 0 || shift.Value == (ulong)maxShift))
{
scale = shift.Value switch
{
1 => Multiplier.x2,
2 => Multiplier.x4,
3 => Multiplier.x8,
4 => Multiplier.x16,
_ => Multiplier.x1
};
baseOp = indexOnSrc2 ? src1 : src2;
indexOp = shSrc;
}
}
return (indexOp, scale);
}
private static Operation GetAsgOpWithInst(Operand op, Instruction inst)
{
// If we have multiple assignments, folding is not safe
// as the value may be different depending on the
// control flow path.
if (op.AssignmentsCount != 1)
{
return default;
}
Operation asgOp = op.Assignments[0];
if (asgOp.Instruction != inst)
{
return default;
}
return asgOp;
}
private static bool IsMemoryLoadOrStore(Instruction inst)
{
return inst == Instruction.Load || inst == Instruction.Store;
}
private static bool ConstTooLong(Operand constOp, OperandType accessType)
{
if ((uint)constOp.Value != constOp.Value)
{
return true;
}
return !CodeGenCommon.ConstFitsOnUImm12(constOp.AsInt32(), accessType);
}
}
}

View File

@ -0,0 +1,47 @@
using ARMeilleure.IntermediateRepresentation;
using System;
namespace ARMeilleure.CodeGen.Arm64
{
enum ArmCondition
{
Eq = 0,
Ne = 1,
GeUn = 2,
LtUn = 3,
Mi = 4,
Pl = 5,
Vs = 6,
Vc = 7,
GtUn = 8,
LeUn = 9,
Ge = 10,
Lt = 11,
Gt = 12,
Le = 13,
Al = 14,
Nv = 15
}
static class ComparisonArm64Extensions
{
public static ArmCondition ToArmCondition(this Comparison comp)
{
return comp switch
{
Comparison.Equal => ArmCondition.Eq,
Comparison.NotEqual => ArmCondition.Ne,
Comparison.Greater => ArmCondition.Gt,
Comparison.LessOrEqual => ArmCondition.Le,
Comparison.GreaterUI => ArmCondition.GtUn,
Comparison.LessOrEqualUI => ArmCondition.LeUn,
Comparison.GreaterOrEqual => ArmCondition.Ge,
Comparison.Less => ArmCondition.Lt,
Comparison.GreaterOrEqualUI => ArmCondition.GeUn,
Comparison.LessUI => ArmCondition.LtUn,
_ => throw new ArgumentException(null, nameof(comp))
};
}
}
}

View File

@ -0,0 +1,14 @@
namespace ARMeilleure.CodeGen.Arm64
{
enum ArmExtensionType
{
Uxtb = 0,
Uxth = 1,
Uxtw = 2,
Uxtx = 3,
Sxtb = 4,
Sxth = 5,
Sxtw = 6,
Sxtx = 7
}
}

View File

@ -0,0 +1,11 @@
namespace ARMeilleure.CodeGen.Arm64
{
enum ArmShiftType
{
Lsl = 0,
Lsr = 1,
Asr = 2,
Ror = 3
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,96 @@
using System;
namespace ARMeilleure.CodeGen.Arm64
{
static class CallingConvention
{
private const int RegistersMask = unchecked((int)0xffffffff);
// Some of those register have specific roles and can't be used as general purpose registers.
// X18 - Reserved for platform specific usage.
// X29 - Frame pointer.
// X30 - Return address.
// X31 - Not an actual register, in some cases maps to SP, and in others to ZR.
private const int ReservedRegsMask = (1 << CodeGenCommon.ReservedRegister) | (1 << 18) | (1 << 29) | (1 << 30) | (1 << 31);
public static int GetIntAvailableRegisters()
{
return RegistersMask & ~ReservedRegsMask;
}
public static int GetVecAvailableRegisters()
{
return RegistersMask;
}
public static int GetIntCallerSavedRegisters()
{
return (GetIntCalleeSavedRegisters() ^ RegistersMask) & ~ReservedRegsMask;
}
public static int GetFpCallerSavedRegisters()
{
return GetFpCalleeSavedRegisters() ^ RegistersMask;
}
public static int GetVecCallerSavedRegisters()
{
return GetVecCalleeSavedRegisters() ^ RegistersMask;
}
public static int GetIntCalleeSavedRegisters()
{
return 0x1ff80000; // X19 to X28
}
public static int GetFpCalleeSavedRegisters()
{
return 0xff00; // D8 to D15
}
public static int GetVecCalleeSavedRegisters()
{
return 0;
}
public static int GetArgumentsOnRegsCount()
{
return 8;
}
public static int GetIntArgumentRegister(int index)
{
if ((uint)index < (uint)GetArgumentsOnRegsCount())
{
return index;
}
throw new ArgumentOutOfRangeException(nameof(index));
}
public static int GetVecArgumentRegister(int index)
{
if ((uint)index < (uint)GetArgumentsOnRegsCount())
{
return index;
}
throw new ArgumentOutOfRangeException(nameof(index));
}
public static int GetIntReturnRegister()
{
return 0;
}
public static int GetIntReturnRegisterHigh()
{
return 1;
}
public static int GetVecReturnRegister()
{
return 0;
}
}
}

View File

@ -0,0 +1,91 @@
using ARMeilleure.IntermediateRepresentation;
using System.Numerics;
namespace ARMeilleure.CodeGen.Arm64
{
static class CodeGenCommon
{
public const int TcAddressRegister = 8;
public const int ReservedRegister = 17;
public static bool ConstFitsOnSImm7(int value, int scale)
{
return (((value >> scale) << 25) >> (25 - scale)) == value;
}
public static bool ConstFitsOnSImm9(int value)
{
return ((value << 23) >> 23) == value;
}
public static bool ConstFitsOnUImm12(int value)
{
return (value & 0xfff) == value;
}
public static bool ConstFitsOnUImm12(int value, OperandType type)
{
int scale = Assembler.GetScaleForType(type);
return (((value >> scale) & 0xfff) << scale) == value;
}
public static bool TryEncodeBitMask(Operand operand, out int immN, out int immS, out int immR)
{
return TryEncodeBitMask(operand.Type, operand.Value, out immN, out immS, out immR);
}
public static bool TryEncodeBitMask(OperandType type, ulong value, out int immN, out int immS, out int immR)
{
if (type == OperandType.I32)
{
value |= value << 32;
}
return TryEncodeBitMask(value, out immN, out immS, out immR);
}
public static bool TryEncodeBitMask(ulong value, out int immN, out int immS, out int immR)
{
// Some special values also can't be encoded:
// 0 can't be encoded because we need to subtract 1 from onesCount (which would became negative if 0).
// A value with all bits set can't be encoded because it is reserved according to the spec, because:
// Any value AND all ones will be equal itself, so it's effectively a no-op.
// Any value OR all ones will be equal all ones, so one can just use MOV.
// Any value XOR all ones will be equal its inverse, so one can just use MVN.
if (value == 0 || value == ulong.MaxValue)
{
immN = 0;
immS = 0;
immR = 0;
return false;
}
// Normalize value, rotating it such that the LSB is 1: Ensures we get a complete element that has not
// been cut-in-half across the word boundary.
int rotation = BitOperations.TrailingZeroCount(value & (value + 1));
ulong rotatedValue = ulong.RotateRight(value, rotation);
// Now that we have a complete element in the LSB with the LSB = 1, determine size and number of ones
// in element.
int elementSize = BitOperations.TrailingZeroCount(rotatedValue & (rotatedValue + 1));
int onesInElement = BitOperations.TrailingZeroCount(~rotatedValue);
// Check the value is repeating; also ensures element size is a power of two.
if (ulong.RotateRight(value, elementSize) != value)
{
immN = 0;
immS = 0;
immR = 0;
return false;
}
immN = (elementSize >> 6) & 1;
immS = (((~elementSize + 1) << 1) | (onesInElement - 1)) & 0x3f;
immR = (elementSize - rotation) & (elementSize - 1);
return true;
}
}
}

View File

@ -0,0 +1,286 @@
using ARMeilleure.CodeGen.Linking;
using ARMeilleure.CodeGen.RegisterAllocators;
using ARMeilleure.IntermediateRepresentation;
using System;
using System.Collections.Generic;
using System.IO;
namespace ARMeilleure.CodeGen.Arm64
{
class CodeGenContext
{
private const int BccInstLength = 4;
private const int CbnzInstLength = 4;
private const int LdrLitInstLength = 4;
private Stream _stream;
public int StreamOffset => (int)_stream.Length;
public AllocationResult AllocResult { get; }
public Assembler Assembler { get; }
public BasicBlock CurrBlock { get; private set; }
public bool HasCall { get; }
public int CallArgsRegionSize { get; }
public int FpLrSaveRegionSize { get; }
private readonly Dictionary<BasicBlock, long> _visitedBlocks;
private readonly Dictionary<BasicBlock, List<(ArmCondition Condition, long BranchPos)>> _pendingBranches;
private struct ConstantPoolEntry
{
public readonly int Offset;
public readonly Symbol Symbol;
public readonly List<(Operand, int)> LdrOffsets;
public ConstantPoolEntry(int offset, Symbol symbol)
{
Offset = offset;
Symbol = symbol;
LdrOffsets = new List<(Operand, int)>();
}
}
private readonly Dictionary<ulong, ConstantPoolEntry> _constantPool;
private bool _constantPoolWritten;
private long _constantPoolOffset;
private ArmCondition _jNearCondition;
private Operand _jNearValue;
private long _jNearPosition;
private readonly bool _relocatable;
public CodeGenContext(AllocationResult allocResult, int maxCallArgs, int blocksCount, bool relocatable)
{
_stream = new MemoryStream();
AllocResult = allocResult;
Assembler = new Assembler(_stream);
bool hasCall = maxCallArgs >= 0;
HasCall = hasCall;
if (maxCallArgs < 0)
{
maxCallArgs = 0;
}
CallArgsRegionSize = maxCallArgs * 16;
FpLrSaveRegionSize = hasCall ? 16 : 0;
_visitedBlocks = new Dictionary<BasicBlock, long>();
_pendingBranches = new Dictionary<BasicBlock, List<(ArmCondition, long)>>();
_constantPool = new Dictionary<ulong, ConstantPoolEntry>();
_relocatable = relocatable;
}
public void EnterBlock(BasicBlock block)
{
CurrBlock = block;
long target = _stream.Position;
if (_pendingBranches.TryGetValue(block, out var list))
{
foreach (var tuple in list)
{
_stream.Seek(tuple.BranchPos, SeekOrigin.Begin);
WriteBranch(tuple.Condition, target);
}
_stream.Seek(target, SeekOrigin.Begin);
_pendingBranches.Remove(block);
}
_visitedBlocks.Add(block, target);
}
public void JumpTo(BasicBlock target)
{
JumpTo(ArmCondition.Al, target);
}
public void JumpTo(ArmCondition condition, BasicBlock target)
{
if (_visitedBlocks.TryGetValue(target, out long offset))
{
WriteBranch(condition, offset);
}
else
{
if (!_pendingBranches.TryGetValue(target, out var list))
{
list = new List<(ArmCondition, long)>();
_pendingBranches.Add(target, list);
}
list.Add((condition, _stream.Position));
_stream.Seek(BccInstLength, SeekOrigin.Current);
}
}
private void WriteBranch(ArmCondition condition, long to)
{
int imm = checked((int)(to - _stream.Position));
if (condition != ArmCondition.Al)
{
Assembler.B(condition, imm);
}
else
{
Assembler.B(imm);
}
}
public void JumpToNear(ArmCondition condition)
{
_jNearCondition = condition;
_jNearPosition = _stream.Position;
_stream.Seek(BccInstLength, SeekOrigin.Current);
}
public void JumpToNearIfNotZero(Operand value)
{
_jNearValue = value;
_jNearPosition = _stream.Position;
_stream.Seek(CbnzInstLength, SeekOrigin.Current);
}
public void JumpHere()
{
long currentPosition = _stream.Position;
long offset = currentPosition - _jNearPosition;
_stream.Seek(_jNearPosition, SeekOrigin.Begin);
if (_jNearValue != default)
{
Assembler.Cbnz(_jNearValue, checked((int)offset));
_jNearValue = default;
}
else
{
Assembler.B(_jNearCondition, checked((int)offset));
}
_stream.Seek(currentPosition, SeekOrigin.Begin);
}
public void ReserveRelocatableConstant(Operand rt, Symbol symbol, ulong value)
{
if (!_constantPool.TryGetValue(value, out ConstantPoolEntry cpe))
{
cpe = new ConstantPoolEntry(_constantPool.Count * sizeof(ulong), symbol);
_constantPool.Add(value, cpe);
}
cpe.LdrOffsets.Add((rt, (int)_stream.Position));
_stream.Seek(LdrLitInstLength, SeekOrigin.Current);
}
private long WriteConstantPool()
{
if (_constantPoolWritten)
{
return _constantPoolOffset;
}
long constantPoolBaseOffset = _stream.Position;
foreach (ulong value in _constantPool.Keys)
{
WriteUInt64(value);
}
foreach (ConstantPoolEntry cpe in _constantPool.Values)
{
foreach ((Operand rt, int ldrOffset) in cpe.LdrOffsets)
{
_stream.Seek(ldrOffset, SeekOrigin.Begin);
int absoluteOffset = checked((int)(constantPoolBaseOffset + cpe.Offset));
int pcRelativeOffset = absoluteOffset - ldrOffset;
Assembler.LdrLit(rt, pcRelativeOffset);
}
}
_stream.Seek(constantPoolBaseOffset + _constantPool.Count * sizeof(ulong), SeekOrigin.Begin);
_constantPoolOffset = constantPoolBaseOffset;
_constantPoolWritten = true;
return constantPoolBaseOffset;
}
public (byte[], RelocInfo) GetCode()
{
long constantPoolBaseOffset = WriteConstantPool();
byte[] code = new byte[_stream.Length];
long originalPosition = _stream.Position;
_stream.Seek(0, SeekOrigin.Begin);
_stream.Read(code, 0, code.Length);
_stream.Seek(originalPosition, SeekOrigin.Begin);
RelocInfo relocInfo;
if (_relocatable)
{
RelocEntry[] relocs = new RelocEntry[_constantPool.Count];
int index = 0;
foreach (ConstantPoolEntry cpe in _constantPool.Values)
{
if (cpe.Symbol.Type != SymbolType.None)
{
int absoluteOffset = checked((int)(constantPoolBaseOffset + cpe.Offset));
relocs[index++] = new RelocEntry(absoluteOffset, cpe.Symbol);
}
}
if (index != relocs.Length)
{
Array.Resize(ref relocs, index);
}
relocInfo = new RelocInfo(relocs);
}
else
{
relocInfo = new RelocInfo(new RelocEntry[0]);
}
return (code, relocInfo);
}
private void WriteUInt64(ulong value)
{
_stream.WriteByte((byte)(value >> 0));
_stream.WriteByte((byte)(value >> 8));
_stream.WriteByte((byte)(value >> 16));
_stream.WriteByte((byte)(value >> 24));
_stream.WriteByte((byte)(value >> 32));
_stream.WriteByte((byte)(value >> 40));
_stream.WriteByte((byte)(value >> 48));
_stream.WriteByte((byte)(value >> 56));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,662 @@
using ARMeilleure.IntermediateRepresentation;
using System;
using System.Diagnostics;
namespace ARMeilleure.CodeGen.Arm64
{
static class CodeGeneratorIntrinsic
{
public static void GenerateOperation(CodeGenContext context, Operation operation)
{
Intrinsic intrin = operation.Intrinsic;
IntrinsicInfo info = IntrinsicTable.GetInfo(intrin & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask));
switch (info.Type)
{
case IntrinsicType.ScalarUnary:
GenerateVectorUnary(
context,
0,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(0));
break;
case IntrinsicType.ScalarUnaryByElem:
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
GenerateVectorUnaryByElem(
context,
0,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
(uint)operation.GetSource(1).AsInt32(),
operation.Destination,
operation.GetSource(0));
break;
case IntrinsicType.ScalarBinary:
GenerateVectorBinary(
context,
0,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(0),
operation.GetSource(1));
break;
case IntrinsicType.ScalarBinaryFPByElem:
Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
GenerateVectorBinaryFPByElem(
context,
0,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
(uint)operation.GetSource(2).AsInt32(),
operation.Destination,
operation.GetSource(0),
operation.GetSource(1));
break;
case IntrinsicType.ScalarBinaryRd:
GenerateVectorUnary(
context,
0,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(1));
break;
case IntrinsicType.ScalarBinaryShl:
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
GenerateVectorBinaryShlImm(
context,
0,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(0),
(uint)operation.GetSource(1).AsInt32());
break;
case IntrinsicType.ScalarBinaryShr:
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
GenerateVectorBinaryShrImm(
context,
0,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(0),
(uint)operation.GetSource(1).AsInt32());
break;
case IntrinsicType.ScalarFPCompare:
GenerateScalarFPCompare(
context,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(0),
operation.GetSource(1));
break;
case IntrinsicType.ScalarFPConvFixed:
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
GenerateVectorBinaryShrImm(
context,
0,
((uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift) + 2u,
info.Inst,
operation.Destination,
operation.GetSource(0),
(uint)operation.GetSource(1).AsInt32());
break;
case IntrinsicType.ScalarFPConvFixedGpr:
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
GenerateScalarFPConvGpr(
context,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(0),
(uint)operation.GetSource(1).AsInt32());
break;
case IntrinsicType.ScalarFPConvGpr:
GenerateScalarFPConvGpr(
context,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(0));
break;
case IntrinsicType.ScalarTernary:
GenerateScalarTernary(
context,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(1),
operation.GetSource(2),
operation.GetSource(0));
break;
case IntrinsicType.ScalarTernaryFPRdByElem:
Debug.Assert(operation.GetSource(3).Kind == OperandKind.Constant);
GenerateVectorBinaryFPByElem(
context,
0,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
(uint)operation.GetSource(3).AsInt32(),
operation.Destination,
operation.GetSource(1),
operation.GetSource(2));
break;
case IntrinsicType.ScalarTernaryShlRd:
Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
GenerateVectorBinaryShlImm(
context,
0,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(1),
(uint)operation.GetSource(2).AsInt32());
break;
case IntrinsicType.ScalarTernaryShrRd:
Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
GenerateVectorBinaryShrImm(
context,
0,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(1),
(uint)operation.GetSource(2).AsInt32());
break;
case IntrinsicType.VectorUnary:
GenerateVectorUnary(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(0));
break;
case IntrinsicType.VectorUnaryByElem:
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
GenerateVectorUnaryByElem(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
(uint)operation.GetSource(1).AsInt32(),
operation.Destination,
operation.GetSource(0));
break;
case IntrinsicType.VectorBinary:
GenerateVectorBinary(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(0),
operation.GetSource(1));
break;
case IntrinsicType.VectorBinaryBitwise:
GenerateVectorBinary(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
info.Inst,
operation.Destination,
operation.GetSource(0),
operation.GetSource(1));
break;
case IntrinsicType.VectorBinaryByElem:
Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
GenerateVectorBinaryByElem(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
(uint)operation.GetSource(2).AsInt32(),
operation.Destination,
operation.GetSource(0),
operation.GetSource(1));
break;
case IntrinsicType.VectorBinaryFPByElem:
Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
GenerateVectorBinaryFPByElem(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
(uint)operation.GetSource(2).AsInt32(),
operation.Destination,
operation.GetSource(0),
operation.GetSource(1));
break;
case IntrinsicType.VectorBinaryRd:
GenerateVectorUnary(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(1));
break;
case IntrinsicType.VectorBinaryShl:
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
GenerateVectorBinaryShlImm(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(0),
(uint)operation.GetSource(1).AsInt32());
break;
case IntrinsicType.VectorBinaryShr:
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
GenerateVectorBinaryShrImm(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(0),
(uint)operation.GetSource(1).AsInt32());
break;
case IntrinsicType.VectorFPConvFixed:
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
GenerateVectorBinaryShrImm(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
((uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift) + 2u,
info.Inst,
operation.Destination,
operation.GetSource(0),
(uint)operation.GetSource(1).AsInt32());
break;
case IntrinsicType.VectorInsertByElem:
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
Debug.Assert(operation.GetSource(3).Kind == OperandKind.Constant);
GenerateVectorInsertByElem(
context,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
(uint)operation.GetSource(3).AsInt32(),
(uint)operation.GetSource(1).AsInt32(),
operation.Destination,
operation.GetSource(2));
break;
case IntrinsicType.VectorLookupTable:
Debug.Assert((uint)(operation.SourcesCount - 2) <= 3);
for (int i = 1; i < operation.SourcesCount - 1; i++)
{
Register currReg = operation.GetSource(i).GetRegister();
Register prevReg = operation.GetSource(i - 1).GetRegister();
Debug.Assert(prevReg.Index + 1 == currReg.Index && currReg.Type == RegisterType.Vector);
}
GenerateVectorBinary(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
info.Inst | ((uint)(operation.SourcesCount - 2) << 13),
operation.Destination,
operation.GetSource(0),
operation.GetSource(operation.SourcesCount - 1));
break;
case IntrinsicType.VectorTernaryFPRdByElem:
Debug.Assert(operation.GetSource(3).Kind == OperandKind.Constant);
GenerateVectorBinaryFPByElem(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
(uint)operation.GetSource(3).AsInt32(),
operation.Destination,
operation.GetSource(1),
operation.GetSource(2));
break;
case IntrinsicType.VectorTernaryRd:
GenerateVectorBinary(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(1),
operation.GetSource(2));
break;
case IntrinsicType.VectorTernaryRdBitwise:
GenerateVectorBinary(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
info.Inst,
operation.Destination,
operation.GetSource(1),
operation.GetSource(2));
break;
case IntrinsicType.VectorTernaryRdByElem:
Debug.Assert(operation.GetSource(3).Kind == OperandKind.Constant);
GenerateVectorBinaryByElem(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
(uint)operation.GetSource(3).AsInt32(),
operation.Destination,
operation.GetSource(1),
operation.GetSource(2));
break;
case IntrinsicType.VectorTernaryShlRd:
Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
GenerateVectorBinaryShlImm(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(1),
(uint)operation.GetSource(2).AsInt32());
break;
case IntrinsicType.VectorTernaryShrRd:
Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
GenerateVectorBinaryShrImm(
context,
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
info.Inst,
operation.Destination,
operation.GetSource(1),
(uint)operation.GetSource(2).AsInt32());
break;
case IntrinsicType.GetRegister:
context.Assembler.WriteInstruction(info.Inst, operation.Destination);
break;
case IntrinsicType.SetRegister:
context.Assembler.WriteInstruction(info.Inst, operation.GetSource(0));
break;
default:
throw new NotImplementedException(info.Type.ToString());
}
}
private static void GenerateScalarFPCompare(
CodeGenContext context,
uint sz,
uint instruction,
Operand dest,
Operand rn,
Operand rm)
{
instruction |= (sz << 22);
if (rm.Kind == OperandKind.Constant && rm.Value == 0)
{
instruction |= 0b1000;
rm = rn;
}
context.Assembler.WriteInstructionRm16NoRet(instruction, rn, rm);
context.Assembler.Mrs(dest, 1, 3, 4, 2, 0);
}
private static void GenerateScalarFPConvGpr(
CodeGenContext context,
uint sz,
uint instruction,
Operand rd,
Operand rn)
{
instruction |= (sz << 22);
if (rd.Type.IsInteger())
{
context.Assembler.WriteInstructionAuto(instruction, rd, rn);
}
else
{
if (rn.Type == OperandType.I64)
{
instruction |= Assembler.SfFlag;
}
context.Assembler.WriteInstruction(instruction, rd, rn);
}
}
private static void GenerateScalarFPConvGpr(
CodeGenContext context,
uint sz,
uint instruction,
Operand rd,
Operand rn,
uint fBits)
{
Debug.Assert(fBits <= 64);
instruction |= (sz << 22);
instruction |= (64 - fBits) << 10;
if (rd.Type.IsInteger())
{
Debug.Assert(rd.Type != OperandType.I32 || fBits <= 32);
context.Assembler.WriteInstructionAuto(instruction, rd, rn);
}
else
{
if (rn.Type == OperandType.I64)
{
instruction |= Assembler.SfFlag;
}
else
{
Debug.Assert(fBits <= 32);
}
context.Assembler.WriteInstruction(instruction, rd, rn);
}
}
private static void GenerateScalarTernary(
CodeGenContext context,
uint sz,
uint instruction,
Operand rd,
Operand rn,
Operand rm,
Operand ra)
{
instruction |= (sz << 22);
context.Assembler.WriteInstruction(instruction, rd, rn, rm, ra);
}
private static void GenerateVectorUnary(
CodeGenContext context,
uint q,
uint sz,
uint instruction,
Operand rd,
Operand rn)
{
instruction |= (q << 30) | (sz << 22);
context.Assembler.WriteInstruction(instruction, rd, rn);
}
private static void GenerateVectorUnaryByElem(
CodeGenContext context,
uint q,
uint sz,
uint instruction,
uint srcIndex,
Operand rd,
Operand rn)
{
uint imm5 = (srcIndex << ((int)sz + 1)) | (1u << (int)sz);
instruction |= (q << 30) | (imm5 << 16);
context.Assembler.WriteInstruction(instruction, rd, rn);
}
private static void GenerateVectorBinary(
CodeGenContext context,
uint q,
uint instruction,
Operand rd,
Operand rn,
Operand rm)
{
instruction |= (q << 30);
context.Assembler.WriteInstructionRm16(instruction, rd, rn, rm);
}
private static void GenerateVectorBinary(
CodeGenContext context,
uint q,
uint sz,
uint instruction,
Operand rd,
Operand rn,
Operand rm)
{
instruction |= (q << 30) | (sz << 22);
context.Assembler.WriteInstructionRm16(instruction, rd, rn, rm);
}
private static void GenerateVectorBinaryByElem(
CodeGenContext context,
uint q,
uint size,
uint instruction,
uint srcIndex,
Operand rd,
Operand rn,
Operand rm)
{
instruction |= (q << 30) | (size << 22);
if (size == 2)
{
instruction |= ((srcIndex & 1) << 21) | ((srcIndex & 2) << 10);
}
else
{
instruction |= ((srcIndex & 3) << 20) | ((srcIndex & 4) << 9);
}
context.Assembler.WriteInstructionRm16(instruction, rd, rn, rm);
}
private static void GenerateVectorBinaryFPByElem(
CodeGenContext context,
uint q,
uint sz,
uint instruction,
uint srcIndex,
Operand rd,
Operand rn,
Operand rm)
{
instruction |= (q << 30) | (sz << 22);
if (sz != 0)
{
instruction |= (srcIndex & 1) << 11;
}
else
{
instruction |= ((srcIndex & 1) << 21) | ((srcIndex & 2) << 10);
}
context.Assembler.WriteInstructionRm16(instruction, rd, rn, rm);
}
private static void GenerateVectorBinaryShlImm(
CodeGenContext context,
uint q,
uint sz,
uint instruction,
Operand rd,
Operand rn,
uint shift)
{
instruction |= (q << 30);
Debug.Assert(shift >= 0 && shift < (8u << (int)sz));
uint imm = (8u << (int)sz) | (shift & (0x3fu >> (int)(3 - sz)));
instruction |= (imm << 16);
context.Assembler.WriteInstruction(instruction, rd, rn);
}
private static void GenerateVectorBinaryShrImm(
CodeGenContext context,
uint q,
uint sz,
uint instruction,
Operand rd,
Operand rn,
uint shift)
{
instruction |= (q << 30);
Debug.Assert(shift > 0 && shift <= (8u << (int)sz));
uint imm = (8u << (int)sz) | ((8u << (int)sz) - shift);
instruction |= (imm << 16);
context.Assembler.WriteInstruction(instruction, rd, rn);
}
private static void GenerateVectorInsertByElem(
CodeGenContext context,
uint sz,
uint instruction,
uint srcIndex,
uint dstIndex,
Operand rd,
Operand rn)
{
uint imm4 = srcIndex << (int)sz;
uint imm5 = (dstIndex << ((int)sz + 1)) | (1u << (int)sz);
instruction |= imm4 << 11;
instruction |= imm5 << 16;
context.Assembler.WriteInstruction(instruction, rd, rn);
}
}
}

View File

@ -0,0 +1,185 @@
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics.Arm;
using System.Runtime.Versioning;
namespace ARMeilleure.CodeGen.Arm64
{
static partial class HardwareCapabilities
{
static HardwareCapabilities()
{
if (!ArmBase.Arm64.IsSupported)
{
return;
}
if (OperatingSystem.IsLinux())
{
LinuxFeatureInfoHwCap = (LinuxFeatureFlagsHwCap)getauxval(AT_HWCAP);
LinuxFeatureInfoHwCap2 = (LinuxFeatureFlagsHwCap2)getauxval(AT_HWCAP2);
}
if (OperatingSystem.IsMacOS())
{
for (int i = 0; i < _sysctlNames.Length; i++)
{
if (CheckSysctlName(_sysctlNames[i]))
{
MacOsFeatureInfo |= (MacOsFeatureFlags)(1 << i);
}
}
}
}
#region Linux
private const ulong AT_HWCAP = 16;
private const ulong AT_HWCAP2 = 26;
[LibraryImport("libc", SetLastError = true)]
private static partial ulong getauxval(ulong type);
[Flags]
public enum LinuxFeatureFlagsHwCap : ulong
{
Fp = 1 << 0,
Asimd = 1 << 1,
Evtstrm = 1 << 2,
Aes = 1 << 3,
Pmull = 1 << 4,
Sha1 = 1 << 5,
Sha2 = 1 << 6,
Crc32 = 1 << 7,
Atomics = 1 << 8,
FpHp = 1 << 9,
AsimdHp = 1 << 10,
CpuId = 1 << 11,
AsimdRdm = 1 << 12,
Jscvt = 1 << 13,
Fcma = 1 << 14,
Lrcpc = 1 << 15,
DcpOp = 1 << 16,
Sha3 = 1 << 17,
Sm3 = 1 << 18,
Sm4 = 1 << 19,
AsimdDp = 1 << 20,
Sha512 = 1 << 21,
Sve = 1 << 22,
AsimdFhm = 1 << 23,
Dit = 1 << 24,
Uscat = 1 << 25,
Ilrcpc = 1 << 26,
FlagM = 1 << 27,
Ssbs = 1 << 28,
Sb = 1 << 29,
Paca = 1 << 30,
Pacg = 1UL << 31
}
[Flags]
public enum LinuxFeatureFlagsHwCap2 : ulong
{
Dcpodp = 1 << 0,
Sve2 = 1 << 1,
SveAes = 1 << 2,
SvePmull = 1 << 3,
SveBitperm = 1 << 4,
SveSha3 = 1 << 5,
SveSm4 = 1 << 6,
FlagM2 = 1 << 7,
Frint = 1 << 8,
SveI8mm = 1 << 9,
SveF32mm = 1 << 10,
SveF64mm = 1 << 11,
SveBf16 = 1 << 12,
I8mm = 1 << 13,
Bf16 = 1 << 14,
Dgh = 1 << 15,
Rng = 1 << 16,
Bti = 1 << 17,
Mte = 1 << 18,
Ecv = 1 << 19,
Afp = 1 << 20,
Rpres = 1 << 21,
Mte3 = 1 << 22,
Sme = 1 << 23,
Sme_i16i64 = 1 << 24,
Sme_f64f64 = 1 << 25,
Sme_i8i32 = 1 << 26,
Sme_f16f32 = 1 << 27,
Sme_b16f32 = 1 << 28,
Sme_f32f32 = 1 << 29,
Sme_fa64 = 1 << 30,
Wfxt = 1UL << 31,
Ebf16 = 1UL << 32,
Sve_Ebf16 = 1UL << 33,
Cssc = 1UL << 34,
Rprfm = 1UL << 35,
Sve2p1 = 1UL << 36
}
public static LinuxFeatureFlagsHwCap LinuxFeatureInfoHwCap { get; } = 0;
public static LinuxFeatureFlagsHwCap2 LinuxFeatureInfoHwCap2 { get; } = 0;
#endregion
#region macOS
[LibraryImport("libSystem.dylib", SetLastError = true)]
private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
[SupportedOSPlatform("macos")]
private static bool CheckSysctlName(string name)
{
ulong size = sizeof(int);
if (sysctlbyname(name, out int val, ref size, IntPtr.Zero, 0) == 0 && size == sizeof(int))
{
return val != 0;
}
return false;
}
private static string[] _sysctlNames = new string[]
{
"hw.optional.floatingpoint",
"hw.optional.AdvSIMD",
"hw.optional.arm.FEAT_FP16",
"hw.optional.arm.FEAT_AES",
"hw.optional.arm.FEAT_PMULL",
"hw.optional.arm.FEAT_LSE",
"hw.optional.armv8_crc32",
"hw.optional.arm.FEAT_SHA1",
"hw.optional.arm.FEAT_SHA256"
};
[Flags]
public enum MacOsFeatureFlags
{
Fp = 1 << 0,
AdvSimd = 1 << 1,
Fp16 = 1 << 2,
Aes = 1 << 3,
Pmull = 1 << 4,
Lse = 1 << 5,
Crc32 = 1 << 6,
Sha1 = 1 << 7,
Sha256 = 1 << 8
}
public static MacOsFeatureFlags MacOsFeatureInfo { get; } = 0;
#endregion
public static bool SupportsAdvSimd => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Asimd) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.AdvSimd);
public static bool SupportsAes => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Aes) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Aes);
public static bool SupportsPmull => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Pmull) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Pmull);
public static bool SupportsLse => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Atomics) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Lse);
public static bool SupportsCrc32 => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Crc32) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Crc32);
public static bool SupportsSha1 => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Sha1) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Sha1);
public static bool SupportsSha256 => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Sha2) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Sha256);
}
}

View File

@ -0,0 +1,14 @@
namespace ARMeilleure.CodeGen.Arm64
{
struct IntrinsicInfo
{
public uint Inst { get; }
public IntrinsicType Type { get; }
public IntrinsicInfo(uint inst, IntrinsicType type)
{
Inst = inst;
Type = type;
}
}
}

View File

@ -0,0 +1,461 @@
using ARMeilleure.Common;
using ARMeilleure.IntermediateRepresentation;
namespace ARMeilleure.CodeGen.Arm64
{
static class IntrinsicTable
{
private static IntrinsicInfo[] _intrinTable;
static IntrinsicTable()
{
_intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))];
Add(Intrinsic.Arm64AbsS, new IntrinsicInfo(0x5e20b800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64AbsV, new IntrinsicInfo(0x0e20b800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64AddhnV, new IntrinsicInfo(0x0e204000u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64AddpS, new IntrinsicInfo(0x5e31b800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64AddpV, new IntrinsicInfo(0x0e20bc00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64AddvV, new IntrinsicInfo(0x0e31b800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64AddS, new IntrinsicInfo(0x5e208400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64AddV, new IntrinsicInfo(0x0e208400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64AesdV, new IntrinsicInfo(0x4e285800u, IntrinsicType.Vector128Unary));
Add(Intrinsic.Arm64AeseV, new IntrinsicInfo(0x4e284800u, IntrinsicType.Vector128Unary));
Add(Intrinsic.Arm64AesimcV, new IntrinsicInfo(0x4e287800u, IntrinsicType.Vector128Unary));
Add(Intrinsic.Arm64AesmcV, new IntrinsicInfo(0x4e286800u, IntrinsicType.Vector128Unary));
Add(Intrinsic.Arm64AndV, new IntrinsicInfo(0x0e201c00u, IntrinsicType.VectorBinaryBitwise));
Add(Intrinsic.Arm64BicVi, new IntrinsicInfo(0x2f001400u, IntrinsicType.VectorBinaryBitwiseImm));
Add(Intrinsic.Arm64BicV, new IntrinsicInfo(0x0e601c00u, IntrinsicType.VectorBinaryBitwise));
Add(Intrinsic.Arm64BifV, new IntrinsicInfo(0x2ee01c00u, IntrinsicType.VectorTernaryRdBitwise));
Add(Intrinsic.Arm64BitV, new IntrinsicInfo(0x2ea01c00u, IntrinsicType.VectorTernaryRdBitwise));
Add(Intrinsic.Arm64BslV, new IntrinsicInfo(0x2e601c00u, IntrinsicType.VectorTernaryRdBitwise));
Add(Intrinsic.Arm64ClsV, new IntrinsicInfo(0x0e204800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64ClzV, new IntrinsicInfo(0x2e204800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64CmeqS, new IntrinsicInfo(0x7e208c00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64CmeqV, new IntrinsicInfo(0x2e208c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64CmeqSz, new IntrinsicInfo(0x5e209800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64CmeqVz, new IntrinsicInfo(0x0e209800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64CmgeS, new IntrinsicInfo(0x5e203c00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64CmgeV, new IntrinsicInfo(0x0e203c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64CmgeSz, new IntrinsicInfo(0x7e208800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64CmgeVz, new IntrinsicInfo(0x2e208800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64CmgtS, new IntrinsicInfo(0x5e203400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64CmgtV, new IntrinsicInfo(0x0e203400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64CmgtSz, new IntrinsicInfo(0x5e208800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64CmgtVz, new IntrinsicInfo(0x0e208800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64CmhiS, new IntrinsicInfo(0x7e203400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64CmhiV, new IntrinsicInfo(0x2e203400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64CmhsS, new IntrinsicInfo(0x7e203c00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64CmhsV, new IntrinsicInfo(0x2e203c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64CmleSz, new IntrinsicInfo(0x7e209800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64CmleVz, new IntrinsicInfo(0x2e209800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64CmltSz, new IntrinsicInfo(0x5e20a800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64CmltVz, new IntrinsicInfo(0x0e20a800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64CmtstS, new IntrinsicInfo(0x5e208c00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64CmtstV, new IntrinsicInfo(0x0e208c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64CntV, new IntrinsicInfo(0x0e205800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64DupSe, new IntrinsicInfo(0x5e000400u, IntrinsicType.ScalarUnaryByElem));
Add(Intrinsic.Arm64DupVe, new IntrinsicInfo(0x0e000400u, IntrinsicType.VectorUnaryByElem));
Add(Intrinsic.Arm64DupGp, new IntrinsicInfo(0x0e000c00u, IntrinsicType.VectorUnaryByElem));
Add(Intrinsic.Arm64EorV, new IntrinsicInfo(0x2e201c00u, IntrinsicType.VectorBinaryBitwise));
Add(Intrinsic.Arm64ExtV, new IntrinsicInfo(0x2e000000u, IntrinsicType.VectorExt));
Add(Intrinsic.Arm64FabdS, new IntrinsicInfo(0x7ea0d400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FabdV, new IntrinsicInfo(0x2ea0d400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FabsV, new IntrinsicInfo(0x0ea0f800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FabsS, new IntrinsicInfo(0x1e20c000u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FacgeS, new IntrinsicInfo(0x7e20ec00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FacgeV, new IntrinsicInfo(0x2e20ec00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FacgtS, new IntrinsicInfo(0x7ea0ec00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FacgtV, new IntrinsicInfo(0x2ea0ec00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FaddpS, new IntrinsicInfo(0x7e30d800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FaddpV, new IntrinsicInfo(0x2e20d400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FaddV, new IntrinsicInfo(0x0e20d400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FaddS, new IntrinsicInfo(0x1e202800u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FccmpeS, new IntrinsicInfo(0x1e200410u, IntrinsicType.ScalarFPCompareCond));
Add(Intrinsic.Arm64FccmpS, new IntrinsicInfo(0x1e200400u, IntrinsicType.ScalarFPCompareCond));
Add(Intrinsic.Arm64FcmeqS, new IntrinsicInfo(0x5e20e400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FcmeqV, new IntrinsicInfo(0x0e20e400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FcmeqSz, new IntrinsicInfo(0x5ea0d800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcmeqVz, new IntrinsicInfo(0x0ea0d800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcmgeS, new IntrinsicInfo(0x7e20e400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FcmgeV, new IntrinsicInfo(0x2e20e400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FcmgeSz, new IntrinsicInfo(0x7ea0c800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcmgeVz, new IntrinsicInfo(0x2ea0c800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcmgtS, new IntrinsicInfo(0x7ea0e400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FcmgtV, new IntrinsicInfo(0x2ea0e400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FcmgtSz, new IntrinsicInfo(0x5ea0c800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcmgtVz, new IntrinsicInfo(0x0ea0c800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcmleSz, new IntrinsicInfo(0x7ea0d800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcmleVz, new IntrinsicInfo(0x2ea0d800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcmltSz, new IntrinsicInfo(0x5ea0e800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcmltVz, new IntrinsicInfo(0x0ea0e800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcmpeS, new IntrinsicInfo(0x1e202010u, IntrinsicType.ScalarFPCompare));
Add(Intrinsic.Arm64FcmpS, new IntrinsicInfo(0x1e202000u, IntrinsicType.ScalarFPCompare));
Add(Intrinsic.Arm64FcselS, new IntrinsicInfo(0x1e200c00u, IntrinsicType.ScalarFcsel));
Add(Intrinsic.Arm64FcvtasS, new IntrinsicInfo(0x5e21c800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcvtasV, new IntrinsicInfo(0x0e21c800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcvtasGp, new IntrinsicInfo(0x1e240000u, IntrinsicType.ScalarFPConvGpr));
Add(Intrinsic.Arm64FcvtauS, new IntrinsicInfo(0x7e21c800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcvtauV, new IntrinsicInfo(0x2e21c800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcvtauGp, new IntrinsicInfo(0x1e250000u, IntrinsicType.ScalarFPConvGpr));
Add(Intrinsic.Arm64FcvtlV, new IntrinsicInfo(0x0e217800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcvtmsS, new IntrinsicInfo(0x5e21b800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcvtmsV, new IntrinsicInfo(0x0e21b800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcvtmsGp, new IntrinsicInfo(0x1e300000u, IntrinsicType.ScalarFPConvGpr));
Add(Intrinsic.Arm64FcvtmuS, new IntrinsicInfo(0x7e21b800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcvtmuV, new IntrinsicInfo(0x2e21b800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcvtmuGp, new IntrinsicInfo(0x1e310000u, IntrinsicType.ScalarFPConvGpr));
Add(Intrinsic.Arm64FcvtnsS, new IntrinsicInfo(0x5e21a800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcvtnsV, new IntrinsicInfo(0x0e21a800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcvtnsGp, new IntrinsicInfo(0x1e200000u, IntrinsicType.ScalarFPConvGpr));
Add(Intrinsic.Arm64FcvtnuS, new IntrinsicInfo(0x7e21a800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcvtnuV, new IntrinsicInfo(0x2e21a800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcvtnuGp, new IntrinsicInfo(0x1e210000u, IntrinsicType.ScalarFPConvGpr));
Add(Intrinsic.Arm64FcvtnV, new IntrinsicInfo(0x0e216800u, IntrinsicType.VectorBinaryRd));
Add(Intrinsic.Arm64FcvtpsS, new IntrinsicInfo(0x5ea1a800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcvtpsV, new IntrinsicInfo(0x0ea1a800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcvtpsGp, new IntrinsicInfo(0x1e280000u, IntrinsicType.ScalarFPConvGpr));
Add(Intrinsic.Arm64FcvtpuS, new IntrinsicInfo(0x7ea1a800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcvtpuV, new IntrinsicInfo(0x2ea1a800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcvtpuGp, new IntrinsicInfo(0x1e290000u, IntrinsicType.ScalarFPConvGpr));
Add(Intrinsic.Arm64FcvtxnS, new IntrinsicInfo(0x7e216800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcvtxnV, new IntrinsicInfo(0x2e216800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcvtzsSFixed, new IntrinsicInfo(0x5f00fc00u, IntrinsicType.ScalarFPConvFixed));
Add(Intrinsic.Arm64FcvtzsVFixed, new IntrinsicInfo(0x0f00fc00u, IntrinsicType.VectorFPConvFixed));
Add(Intrinsic.Arm64FcvtzsS, new IntrinsicInfo(0x5ea1b800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcvtzsV, new IntrinsicInfo(0x0ea1b800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcvtzsGpFixed, new IntrinsicInfo(0x1e180000u, IntrinsicType.ScalarFPConvFixedGpr));
Add(Intrinsic.Arm64FcvtzsGp, new IntrinsicInfo(0x1e380000u, IntrinsicType.ScalarFPConvGpr));
Add(Intrinsic.Arm64FcvtzuSFixed, new IntrinsicInfo(0x7f00fc00u, IntrinsicType.ScalarFPConvFixed));
Add(Intrinsic.Arm64FcvtzuVFixed, new IntrinsicInfo(0x2f00fc00u, IntrinsicType.VectorFPConvFixed));
Add(Intrinsic.Arm64FcvtzuS, new IntrinsicInfo(0x7ea1b800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FcvtzuV, new IntrinsicInfo(0x2ea1b800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FcvtzuGpFixed, new IntrinsicInfo(0x1e190000u, IntrinsicType.ScalarFPConvFixedGpr));
Add(Intrinsic.Arm64FcvtzuGp, new IntrinsicInfo(0x1e390000u, IntrinsicType.ScalarFPConvGpr));
Add(Intrinsic.Arm64FcvtS, new IntrinsicInfo(0x1e224000u, IntrinsicType.ScalarFPConv));
Add(Intrinsic.Arm64FdivV, new IntrinsicInfo(0x2e20fc00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FdivS, new IntrinsicInfo(0x1e201800u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FmaddS, new IntrinsicInfo(0x1f000000u, IntrinsicType.ScalarTernary));
Add(Intrinsic.Arm64FmaxnmpS, new IntrinsicInfo(0x7e30c800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FmaxnmpV, new IntrinsicInfo(0x2e20c400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FmaxnmvV, new IntrinsicInfo(0x2e30c800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FmaxnmV, new IntrinsicInfo(0x0e20c400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FmaxnmS, new IntrinsicInfo(0x1e206800u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FmaxpS, new IntrinsicInfo(0x7e30f800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FmaxpV, new IntrinsicInfo(0x2e20f400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FmaxvV, new IntrinsicInfo(0x2e30f800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FmaxV, new IntrinsicInfo(0x0e20f400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FmaxS, new IntrinsicInfo(0x1e204800u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FminnmpS, new IntrinsicInfo(0x7eb0c800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FminnmpV, new IntrinsicInfo(0x2ea0c400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FminnmvV, new IntrinsicInfo(0x2eb0c800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FminnmV, new IntrinsicInfo(0x0ea0c400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FminnmS, new IntrinsicInfo(0x1e207800u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FminpS, new IntrinsicInfo(0x7eb0f800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FminpV, new IntrinsicInfo(0x2ea0f400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FminvV, new IntrinsicInfo(0x2eb0f800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FminV, new IntrinsicInfo(0x0ea0f400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FminS, new IntrinsicInfo(0x1e205800u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FmlaSe, new IntrinsicInfo(0x5f801000u, IntrinsicType.ScalarTernaryFPRdByElem));
Add(Intrinsic.Arm64FmlaVe, new IntrinsicInfo(0x0f801000u, IntrinsicType.VectorTernaryFPRdByElem));
Add(Intrinsic.Arm64FmlaV, new IntrinsicInfo(0x0e20cc00u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64FmlsSe, new IntrinsicInfo(0x5f805000u, IntrinsicType.ScalarTernaryFPRdByElem));
Add(Intrinsic.Arm64FmlsVe, new IntrinsicInfo(0x0f805000u, IntrinsicType.VectorTernaryFPRdByElem));
Add(Intrinsic.Arm64FmlsV, new IntrinsicInfo(0x0ea0cc00u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64FmovVi, new IntrinsicInfo(0x0f00f400u, IntrinsicType.VectorFmovi));
Add(Intrinsic.Arm64FmovS, new IntrinsicInfo(0x1e204000u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FmovGp, new IntrinsicInfo(0x1e260000u, IntrinsicType.ScalarFPConvGpr));
Add(Intrinsic.Arm64FmovSi, new IntrinsicInfo(0x1e201000u, IntrinsicType.ScalarFmovi));
Add(Intrinsic.Arm64FmsubS, new IntrinsicInfo(0x1f008000u, IntrinsicType.ScalarTernary));
Add(Intrinsic.Arm64FmulxSe, new IntrinsicInfo(0x7f809000u, IntrinsicType.ScalarBinaryFPByElem));
Add(Intrinsic.Arm64FmulxVe, new IntrinsicInfo(0x2f809000u, IntrinsicType.VectorBinaryFPByElem));
Add(Intrinsic.Arm64FmulxS, new IntrinsicInfo(0x5e20dc00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FmulxV, new IntrinsicInfo(0x0e20dc00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FmulSe, new IntrinsicInfo(0x5f809000u, IntrinsicType.ScalarBinaryFPByElem));
Add(Intrinsic.Arm64FmulVe, new IntrinsicInfo(0x0f809000u, IntrinsicType.VectorBinaryFPByElem));
Add(Intrinsic.Arm64FmulV, new IntrinsicInfo(0x2e20dc00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FmulS, new IntrinsicInfo(0x1e200800u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FnegV, new IntrinsicInfo(0x2ea0f800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FnegS, new IntrinsicInfo(0x1e214000u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FnmaddS, new IntrinsicInfo(0x1f200000u, IntrinsicType.ScalarTernary));
Add(Intrinsic.Arm64FnmsubS, new IntrinsicInfo(0x1f208000u, IntrinsicType.ScalarTernary));
Add(Intrinsic.Arm64FnmulS, new IntrinsicInfo(0x1e208800u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FrecpeS, new IntrinsicInfo(0x5ea1d800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FrecpeV, new IntrinsicInfo(0x0ea1d800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FrecpsS, new IntrinsicInfo(0x5e20fc00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FrecpsV, new IntrinsicInfo(0x0e20fc00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FrecpxS, new IntrinsicInfo(0x5ea1f800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FrintaV, new IntrinsicInfo(0x2e218800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FrintaS, new IntrinsicInfo(0x1e264000u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FrintiV, new IntrinsicInfo(0x2ea19800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FrintiS, new IntrinsicInfo(0x1e27c000u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FrintmV, new IntrinsicInfo(0x0e219800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FrintmS, new IntrinsicInfo(0x1e254000u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FrintnV, new IntrinsicInfo(0x0e218800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FrintnS, new IntrinsicInfo(0x1e244000u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FrintpV, new IntrinsicInfo(0x0ea18800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FrintpS, new IntrinsicInfo(0x1e24c000u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FrintxV, new IntrinsicInfo(0x2e219800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FrintxS, new IntrinsicInfo(0x1e274000u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FrintzV, new IntrinsicInfo(0x0ea19800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FrintzS, new IntrinsicInfo(0x1e25c000u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FrsqrteS, new IntrinsicInfo(0x7ea1d800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FrsqrteV, new IntrinsicInfo(0x2ea1d800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FrsqrtsS, new IntrinsicInfo(0x5ea0fc00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64FrsqrtsV, new IntrinsicInfo(0x0ea0fc00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FsqrtV, new IntrinsicInfo(0x2ea1f800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64FsqrtS, new IntrinsicInfo(0x1e21c000u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64FsubV, new IntrinsicInfo(0x0ea0d400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64FsubS, new IntrinsicInfo(0x1e203800u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64InsVe, new IntrinsicInfo(0x6e000400u, IntrinsicType.VectorInsertByElem));
Add(Intrinsic.Arm64InsGp, new IntrinsicInfo(0x4e001c00u, IntrinsicType.ScalarUnaryByElem));
Add(Intrinsic.Arm64Ld1rV, new IntrinsicInfo(0x0d40c000u, IntrinsicType.VectorLdSt));
Add(Intrinsic.Arm64Ld1Vms, new IntrinsicInfo(0x0c402000u, IntrinsicType.VectorLdSt));
Add(Intrinsic.Arm64Ld1Vss, new IntrinsicInfo(0x0d400000u, IntrinsicType.VectorLdStSs));
Add(Intrinsic.Arm64Ld2rV, new IntrinsicInfo(0x0d60c000u, IntrinsicType.VectorLdSt));
Add(Intrinsic.Arm64Ld2Vms, new IntrinsicInfo(0x0c408000u, IntrinsicType.VectorLdSt));
Add(Intrinsic.Arm64Ld2Vss, new IntrinsicInfo(0x0d600000u, IntrinsicType.VectorLdStSs));
Add(Intrinsic.Arm64Ld3rV, new IntrinsicInfo(0x0d40e000u, IntrinsicType.VectorLdSt));
Add(Intrinsic.Arm64Ld3Vms, new IntrinsicInfo(0x0c404000u, IntrinsicType.VectorLdSt));
Add(Intrinsic.Arm64Ld3Vss, new IntrinsicInfo(0x0d402000u, IntrinsicType.VectorLdStSs));
Add(Intrinsic.Arm64Ld4rV, new IntrinsicInfo(0x0d60e000u, IntrinsicType.VectorLdSt));
Add(Intrinsic.Arm64Ld4Vms, new IntrinsicInfo(0x0c400000u, IntrinsicType.VectorLdSt));
Add(Intrinsic.Arm64Ld4Vss, new IntrinsicInfo(0x0d602000u, IntrinsicType.VectorLdStSs));
Add(Intrinsic.Arm64MlaVe, new IntrinsicInfo(0x2f000000u, IntrinsicType.VectorTernaryRdByElem));
Add(Intrinsic.Arm64MlaV, new IntrinsicInfo(0x0e209400u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64MlsVe, new IntrinsicInfo(0x2f004000u, IntrinsicType.VectorTernaryRdByElem));
Add(Intrinsic.Arm64MlsV, new IntrinsicInfo(0x2e209400u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64MoviV, new IntrinsicInfo(0x0f000400u, IntrinsicType.VectorMovi));
Add(Intrinsic.Arm64MrsFpsr, new IntrinsicInfo(0xd53b4420u, IntrinsicType.GetRegister));
Add(Intrinsic.Arm64MsrFpsr, new IntrinsicInfo(0xd51b4420u, IntrinsicType.SetRegister));
Add(Intrinsic.Arm64MulVe, new IntrinsicInfo(0x0f008000u, IntrinsicType.VectorBinaryByElem));
Add(Intrinsic.Arm64MulV, new IntrinsicInfo(0x0e209c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64MvniV, new IntrinsicInfo(0x2f000400u, IntrinsicType.VectorMvni));
Add(Intrinsic.Arm64NegS, new IntrinsicInfo(0x7e20b800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64NegV, new IntrinsicInfo(0x2e20b800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64NotV, new IntrinsicInfo(0x2e205800u, IntrinsicType.VectorUnaryBitwise));
Add(Intrinsic.Arm64OrnV, new IntrinsicInfo(0x0ee01c00u, IntrinsicType.VectorBinaryBitwise));
Add(Intrinsic.Arm64OrrVi, new IntrinsicInfo(0x0f001400u, IntrinsicType.VectorBinaryBitwiseImm));
Add(Intrinsic.Arm64OrrV, new IntrinsicInfo(0x0ea01c00u, IntrinsicType.VectorBinaryBitwise));
Add(Intrinsic.Arm64PmullV, new IntrinsicInfo(0x0e20e000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64PmulV, new IntrinsicInfo(0x2e209c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64RaddhnV, new IntrinsicInfo(0x2e204000u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64RbitV, new IntrinsicInfo(0x2e605800u, IntrinsicType.VectorUnaryBitwise));
Add(Intrinsic.Arm64Rev16V, new IntrinsicInfo(0x0e201800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64Rev32V, new IntrinsicInfo(0x2e200800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64Rev64V, new IntrinsicInfo(0x0e200800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64RshrnV, new IntrinsicInfo(0x0f008c00u, IntrinsicType.VectorTernaryShrRd));
Add(Intrinsic.Arm64RsubhnV, new IntrinsicInfo(0x2e206000u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64SabalV, new IntrinsicInfo(0x0e205000u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64SabaV, new IntrinsicInfo(0x0e207c00u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64SabdlV, new IntrinsicInfo(0x0e207000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SabdV, new IntrinsicInfo(0x0e207400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SadalpV, new IntrinsicInfo(0x0e206800u, IntrinsicType.VectorBinaryRd));
Add(Intrinsic.Arm64SaddlpV, new IntrinsicInfo(0x0e202800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64SaddlvV, new IntrinsicInfo(0x0e303800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64SaddlV, new IntrinsicInfo(0x0e200000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SaddwV, new IntrinsicInfo(0x0e201000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64ScvtfSFixed, new IntrinsicInfo(0x5f00e400u, IntrinsicType.ScalarFPConvFixed));
Add(Intrinsic.Arm64ScvtfVFixed, new IntrinsicInfo(0x0f00e400u, IntrinsicType.VectorFPConvFixed));
Add(Intrinsic.Arm64ScvtfS, new IntrinsicInfo(0x5e21d800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64ScvtfV, new IntrinsicInfo(0x0e21d800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64ScvtfGpFixed, new IntrinsicInfo(0x1e020000u, IntrinsicType.ScalarFPConvFixedGpr));
Add(Intrinsic.Arm64ScvtfGp, new IntrinsicInfo(0x1e220000u, IntrinsicType.ScalarFPConvGpr));
Add(Intrinsic.Arm64Sha1cV, new IntrinsicInfo(0x5e000000u, IntrinsicType.Vector128Binary));
Add(Intrinsic.Arm64Sha1hV, new IntrinsicInfo(0x5e280800u, IntrinsicType.Vector128Unary));
Add(Intrinsic.Arm64Sha1mV, new IntrinsicInfo(0x5e002000u, IntrinsicType.Vector128Binary));
Add(Intrinsic.Arm64Sha1pV, new IntrinsicInfo(0x5e001000u, IntrinsicType.Vector128Binary));
Add(Intrinsic.Arm64Sha1su0V, new IntrinsicInfo(0x5e003000u, IntrinsicType.Vector128Binary));
Add(Intrinsic.Arm64Sha1su1V, new IntrinsicInfo(0x5e281800u, IntrinsicType.Vector128Unary));
Add(Intrinsic.Arm64Sha256h2V, new IntrinsicInfo(0x5e005000u, IntrinsicType.Vector128Binary));
Add(Intrinsic.Arm64Sha256hV, new IntrinsicInfo(0x5e004000u, IntrinsicType.Vector128Binary));
Add(Intrinsic.Arm64Sha256su0V, new IntrinsicInfo(0x5e282800u, IntrinsicType.Vector128Unary));
Add(Intrinsic.Arm64Sha256su1V, new IntrinsicInfo(0x5e006000u, IntrinsicType.Vector128Binary));
Add(Intrinsic.Arm64ShaddV, new IntrinsicInfo(0x0e200400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64ShllV, new IntrinsicInfo(0x2e213800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64ShlS, new IntrinsicInfo(0x5f005400u, IntrinsicType.ScalarBinaryShl));
Add(Intrinsic.Arm64ShlV, new IntrinsicInfo(0x0f005400u, IntrinsicType.VectorBinaryShl));
Add(Intrinsic.Arm64ShrnV, new IntrinsicInfo(0x0f008400u, IntrinsicType.VectorTernaryShrRd));
Add(Intrinsic.Arm64ShsubV, new IntrinsicInfo(0x0e202400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SliS, new IntrinsicInfo(0x7f005400u, IntrinsicType.ScalarTernaryShlRd));
Add(Intrinsic.Arm64SliV, new IntrinsicInfo(0x2f005400u, IntrinsicType.VectorTernaryShlRd));
Add(Intrinsic.Arm64SmaxpV, new IntrinsicInfo(0x0e20a400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SmaxvV, new IntrinsicInfo(0x0e30a800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64SmaxV, new IntrinsicInfo(0x0e206400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SminpV, new IntrinsicInfo(0x0e20ac00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SminvV, new IntrinsicInfo(0x0e31a800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64SminV, new IntrinsicInfo(0x0e206c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SmlalVe, new IntrinsicInfo(0x0f002000u, IntrinsicType.VectorTernaryRdByElem));
Add(Intrinsic.Arm64SmlalV, new IntrinsicInfo(0x0e208000u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64SmlslVe, new IntrinsicInfo(0x0f006000u, IntrinsicType.VectorTernaryRdByElem));
Add(Intrinsic.Arm64SmlslV, new IntrinsicInfo(0x0e20a000u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64SmovV, new IntrinsicInfo(0x0e002c00u, IntrinsicType.VectorUnaryByElem));
Add(Intrinsic.Arm64SmullVe, new IntrinsicInfo(0x0f00a000u, IntrinsicType.VectorBinaryByElem));
Add(Intrinsic.Arm64SmullV, new IntrinsicInfo(0x0e20c000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SqabsS, new IntrinsicInfo(0x5e207800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64SqabsV, new IntrinsicInfo(0x0e207800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64SqaddS, new IntrinsicInfo(0x5e200c00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64SqaddV, new IntrinsicInfo(0x0e200c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SqdmlalSe, new IntrinsicInfo(0x5f003000u, IntrinsicType.ScalarBinaryByElem));
Add(Intrinsic.Arm64SqdmlalVe, new IntrinsicInfo(0x0f003000u, IntrinsicType.VectorBinaryByElem));
Add(Intrinsic.Arm64SqdmlalS, new IntrinsicInfo(0x5e209000u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64SqdmlalV, new IntrinsicInfo(0x0e209000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SqdmlslSe, new IntrinsicInfo(0x5f007000u, IntrinsicType.ScalarBinaryByElem));
Add(Intrinsic.Arm64SqdmlslVe, new IntrinsicInfo(0x0f007000u, IntrinsicType.VectorBinaryByElem));
Add(Intrinsic.Arm64SqdmlslS, new IntrinsicInfo(0x5e20b000u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64SqdmlslV, new IntrinsicInfo(0x0e20b000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SqdmulhSe, new IntrinsicInfo(0x5f00c000u, IntrinsicType.ScalarBinaryByElem));
Add(Intrinsic.Arm64SqdmulhVe, new IntrinsicInfo(0x0f00c000u, IntrinsicType.VectorBinaryByElem));
Add(Intrinsic.Arm64SqdmulhS, new IntrinsicInfo(0x5e20b400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64SqdmulhV, new IntrinsicInfo(0x0e20b400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SqdmullSe, new IntrinsicInfo(0x5f00b000u, IntrinsicType.ScalarBinaryByElem));
Add(Intrinsic.Arm64SqdmullVe, new IntrinsicInfo(0x0f00b000u, IntrinsicType.VectorBinaryByElem));
Add(Intrinsic.Arm64SqdmullS, new IntrinsicInfo(0x5e20d000u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64SqdmullV, new IntrinsicInfo(0x0e20d000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SqnegS, new IntrinsicInfo(0x7e207800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64SqnegV, new IntrinsicInfo(0x2e207800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64SqrdmulhSe, new IntrinsicInfo(0x5f00d000u, IntrinsicType.ScalarBinaryByElem));
Add(Intrinsic.Arm64SqrdmulhVe, new IntrinsicInfo(0x0f00d000u, IntrinsicType.VectorBinaryByElem));
Add(Intrinsic.Arm64SqrdmulhS, new IntrinsicInfo(0x7e20b400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64SqrdmulhV, new IntrinsicInfo(0x2e20b400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SqrshlS, new IntrinsicInfo(0x5e205c00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64SqrshlV, new IntrinsicInfo(0x0e205c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SqrshrnS, new IntrinsicInfo(0x5f009c00u, IntrinsicType.ScalarTernaryShrRd));
Add(Intrinsic.Arm64SqrshrnV, new IntrinsicInfo(0x0f009c00u, IntrinsicType.VectorTernaryShrRd));
Add(Intrinsic.Arm64SqrshrunS, new IntrinsicInfo(0x7f008c00u, IntrinsicType.ScalarTernaryShrRd));
Add(Intrinsic.Arm64SqrshrunV, new IntrinsicInfo(0x2f008c00u, IntrinsicType.VectorTernaryShrRd));
Add(Intrinsic.Arm64SqshluS, new IntrinsicInfo(0x7f006400u, IntrinsicType.ScalarBinaryShl));
Add(Intrinsic.Arm64SqshluV, new IntrinsicInfo(0x2f006400u, IntrinsicType.VectorBinaryShl));
Add(Intrinsic.Arm64SqshlSi, new IntrinsicInfo(0x5f007400u, IntrinsicType.ScalarBinaryShl));
Add(Intrinsic.Arm64SqshlVi, new IntrinsicInfo(0x0f007400u, IntrinsicType.VectorBinaryShl));
Add(Intrinsic.Arm64SqshlS, new IntrinsicInfo(0x5e204c00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64SqshlV, new IntrinsicInfo(0x0e204c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SqshrnS, new IntrinsicInfo(0x5f009400u, IntrinsicType.ScalarTernaryShrRd));
Add(Intrinsic.Arm64SqshrnV, new IntrinsicInfo(0x0f009400u, IntrinsicType.VectorTernaryShrRd));
Add(Intrinsic.Arm64SqshrunS, new IntrinsicInfo(0x7f008400u, IntrinsicType.ScalarTernaryShrRd));
Add(Intrinsic.Arm64SqshrunV, new IntrinsicInfo(0x2f008400u, IntrinsicType.VectorTernaryShrRd));
Add(Intrinsic.Arm64SqsubS, new IntrinsicInfo(0x5e202c00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64SqsubV, new IntrinsicInfo(0x0e202c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SqxtnS, new IntrinsicInfo(0x5e214800u, IntrinsicType.ScalarBinaryRd));
Add(Intrinsic.Arm64SqxtnV, new IntrinsicInfo(0x0e214800u, IntrinsicType.VectorBinaryRd));
Add(Intrinsic.Arm64SqxtunS, new IntrinsicInfo(0x7e212800u, IntrinsicType.ScalarBinaryRd));
Add(Intrinsic.Arm64SqxtunV, new IntrinsicInfo(0x2e212800u, IntrinsicType.VectorBinaryRd));
Add(Intrinsic.Arm64SrhaddV, new IntrinsicInfo(0x0e201400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SriS, new IntrinsicInfo(0x7f004400u, IntrinsicType.ScalarTernaryShrRd));
Add(Intrinsic.Arm64SriV, new IntrinsicInfo(0x2f004400u, IntrinsicType.VectorTernaryShrRd));
Add(Intrinsic.Arm64SrshlS, new IntrinsicInfo(0x5e205400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64SrshlV, new IntrinsicInfo(0x0e205400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SrshrS, new IntrinsicInfo(0x5f002400u, IntrinsicType.ScalarBinaryShr));
Add(Intrinsic.Arm64SrshrV, new IntrinsicInfo(0x0f002400u, IntrinsicType.VectorBinaryShr));
Add(Intrinsic.Arm64SrsraS, new IntrinsicInfo(0x5f003400u, IntrinsicType.ScalarTernaryShrRd));
Add(Intrinsic.Arm64SrsraV, new IntrinsicInfo(0x0f003400u, IntrinsicType.VectorTernaryShrRd));
Add(Intrinsic.Arm64SshllV, new IntrinsicInfo(0x0f00a400u, IntrinsicType.VectorBinaryShl));
Add(Intrinsic.Arm64SshlS, new IntrinsicInfo(0x5e204400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64SshlV, new IntrinsicInfo(0x0e204400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SshrS, new IntrinsicInfo(0x5f000400u, IntrinsicType.ScalarBinaryShr));
Add(Intrinsic.Arm64SshrV, new IntrinsicInfo(0x0f000400u, IntrinsicType.VectorBinaryShr));
Add(Intrinsic.Arm64SsraS, new IntrinsicInfo(0x5f001400u, IntrinsicType.ScalarTernaryShrRd));
Add(Intrinsic.Arm64SsraV, new IntrinsicInfo(0x0f001400u, IntrinsicType.VectorTernaryShrRd));
Add(Intrinsic.Arm64SsublV, new IntrinsicInfo(0x0e202000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SsubwV, new IntrinsicInfo(0x0e203000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64St1Vms, new IntrinsicInfo(0x0c002000u, IntrinsicType.VectorLdSt));
Add(Intrinsic.Arm64St1Vss, new IntrinsicInfo(0x0d000000u, IntrinsicType.VectorLdStSs));
Add(Intrinsic.Arm64St2Vms, new IntrinsicInfo(0x0c008000u, IntrinsicType.VectorLdSt));
Add(Intrinsic.Arm64St2Vss, new IntrinsicInfo(0x0d200000u, IntrinsicType.VectorLdStSs));
Add(Intrinsic.Arm64St3Vms, new IntrinsicInfo(0x0c004000u, IntrinsicType.VectorLdSt));
Add(Intrinsic.Arm64St3Vss, new IntrinsicInfo(0x0d002000u, IntrinsicType.VectorLdStSs));
Add(Intrinsic.Arm64St4Vms, new IntrinsicInfo(0x0c000000u, IntrinsicType.VectorLdSt));
Add(Intrinsic.Arm64St4Vss, new IntrinsicInfo(0x0d202000u, IntrinsicType.VectorLdStSs));
Add(Intrinsic.Arm64SubhnV, new IntrinsicInfo(0x0e206000u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64SubS, new IntrinsicInfo(0x7e208400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64SubV, new IntrinsicInfo(0x2e208400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64SuqaddS, new IntrinsicInfo(0x5e203800u, IntrinsicType.ScalarBinaryRd));
Add(Intrinsic.Arm64SuqaddV, new IntrinsicInfo(0x0e203800u, IntrinsicType.VectorBinaryRd));
Add(Intrinsic.Arm64TblV, new IntrinsicInfo(0x0e000000u, IntrinsicType.VectorLookupTable));
Add(Intrinsic.Arm64TbxV, new IntrinsicInfo(0x0e001000u, IntrinsicType.VectorLookupTable));
Add(Intrinsic.Arm64Trn1V, new IntrinsicInfo(0x0e002800u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64Trn2V, new IntrinsicInfo(0x0e006800u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UabalV, new IntrinsicInfo(0x2e205000u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64UabaV, new IntrinsicInfo(0x2e207c00u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64UabdlV, new IntrinsicInfo(0x2e207000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UabdV, new IntrinsicInfo(0x2e207400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UadalpV, new IntrinsicInfo(0x2e206800u, IntrinsicType.VectorBinaryRd));
Add(Intrinsic.Arm64UaddlpV, new IntrinsicInfo(0x2e202800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64UaddlvV, new IntrinsicInfo(0x2e303800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64UaddlV, new IntrinsicInfo(0x2e200000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UaddwV, new IntrinsicInfo(0x2e201000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UcvtfSFixed, new IntrinsicInfo(0x7f00e400u, IntrinsicType.ScalarFPConvFixed));
Add(Intrinsic.Arm64UcvtfVFixed, new IntrinsicInfo(0x2f00e400u, IntrinsicType.VectorFPConvFixed));
Add(Intrinsic.Arm64UcvtfS, new IntrinsicInfo(0x7e21d800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64UcvtfV, new IntrinsicInfo(0x2e21d800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64UcvtfGpFixed, new IntrinsicInfo(0x1e030000u, IntrinsicType.ScalarFPConvFixedGpr));
Add(Intrinsic.Arm64UcvtfGp, new IntrinsicInfo(0x1e230000u, IntrinsicType.ScalarFPConvGpr));
Add(Intrinsic.Arm64UhaddV, new IntrinsicInfo(0x2e200400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UhsubV, new IntrinsicInfo(0x2e202400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UmaxpV, new IntrinsicInfo(0x2e20a400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UmaxvV, new IntrinsicInfo(0x2e30a800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64UmaxV, new IntrinsicInfo(0x2e206400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UminpV, new IntrinsicInfo(0x2e20ac00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UminvV, new IntrinsicInfo(0x2e31a800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64UminV, new IntrinsicInfo(0x2e206c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UmlalVe, new IntrinsicInfo(0x2f002000u, IntrinsicType.VectorTernaryRdByElem));
Add(Intrinsic.Arm64UmlalV, new IntrinsicInfo(0x2e208000u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64UmlslVe, new IntrinsicInfo(0x2f006000u, IntrinsicType.VectorTernaryRdByElem));
Add(Intrinsic.Arm64UmlslV, new IntrinsicInfo(0x2e20a000u, IntrinsicType.VectorTernaryRd));
Add(Intrinsic.Arm64UmovV, new IntrinsicInfo(0x0e003c00u, IntrinsicType.VectorUnaryByElem));
Add(Intrinsic.Arm64UmullVe, new IntrinsicInfo(0x2f00a000u, IntrinsicType.VectorBinaryByElem));
Add(Intrinsic.Arm64UmullV, new IntrinsicInfo(0x2e20c000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UqaddS, new IntrinsicInfo(0x7e200c00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64UqaddV, new IntrinsicInfo(0x2e200c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UqrshlS, new IntrinsicInfo(0x7e205c00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64UqrshlV, new IntrinsicInfo(0x2e205c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UqrshrnS, new IntrinsicInfo(0x7f009c00u, IntrinsicType.ScalarTernaryShrRd));
Add(Intrinsic.Arm64UqrshrnV, new IntrinsicInfo(0x2f009c00u, IntrinsicType.VectorTernaryShrRd));
Add(Intrinsic.Arm64UqshlSi, new IntrinsicInfo(0x7f007400u, IntrinsicType.ScalarBinaryShl));
Add(Intrinsic.Arm64UqshlVi, new IntrinsicInfo(0x2f007400u, IntrinsicType.VectorBinaryShl));
Add(Intrinsic.Arm64UqshlS, new IntrinsicInfo(0x7e204c00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64UqshlV, new IntrinsicInfo(0x2e204c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UqshrnS, new IntrinsicInfo(0x7f009400u, IntrinsicType.ScalarTernaryShrRd));
Add(Intrinsic.Arm64UqshrnV, new IntrinsicInfo(0x2f009400u, IntrinsicType.VectorTernaryShrRd));
Add(Intrinsic.Arm64UqsubS, new IntrinsicInfo(0x7e202c00u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64UqsubV, new IntrinsicInfo(0x2e202c00u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UqxtnS, new IntrinsicInfo(0x7e214800u, IntrinsicType.ScalarBinaryRd));
Add(Intrinsic.Arm64UqxtnV, new IntrinsicInfo(0x2e214800u, IntrinsicType.VectorBinaryRd));
Add(Intrinsic.Arm64UrecpeV, new IntrinsicInfo(0x0ea1c800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64UrhaddV, new IntrinsicInfo(0x2e201400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UrshlS, new IntrinsicInfo(0x7e205400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64UrshlV, new IntrinsicInfo(0x2e205400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UrshrS, new IntrinsicInfo(0x7f002400u, IntrinsicType.ScalarBinaryShr));
Add(Intrinsic.Arm64UrshrV, new IntrinsicInfo(0x2f002400u, IntrinsicType.VectorBinaryShr));
Add(Intrinsic.Arm64UrsqrteV, new IntrinsicInfo(0x2ea1c800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64UrsraS, new IntrinsicInfo(0x7f003400u, IntrinsicType.ScalarTernaryShrRd));
Add(Intrinsic.Arm64UrsraV, new IntrinsicInfo(0x2f003400u, IntrinsicType.VectorTernaryShrRd));
Add(Intrinsic.Arm64UshllV, new IntrinsicInfo(0x2f00a400u, IntrinsicType.VectorBinaryShl));
Add(Intrinsic.Arm64UshlS, new IntrinsicInfo(0x7e204400u, IntrinsicType.ScalarBinary));
Add(Intrinsic.Arm64UshlV, new IntrinsicInfo(0x2e204400u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UshrS, new IntrinsicInfo(0x7f000400u, IntrinsicType.ScalarBinaryShr));
Add(Intrinsic.Arm64UshrV, new IntrinsicInfo(0x2f000400u, IntrinsicType.VectorBinaryShr));
Add(Intrinsic.Arm64UsqaddS, new IntrinsicInfo(0x7e203800u, IntrinsicType.ScalarBinaryRd));
Add(Intrinsic.Arm64UsqaddV, new IntrinsicInfo(0x2e203800u, IntrinsicType.VectorBinaryRd));
Add(Intrinsic.Arm64UsraS, new IntrinsicInfo(0x7f001400u, IntrinsicType.ScalarTernaryShrRd));
Add(Intrinsic.Arm64UsraV, new IntrinsicInfo(0x2f001400u, IntrinsicType.VectorTernaryShrRd));
Add(Intrinsic.Arm64UsublV, new IntrinsicInfo(0x2e202000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64UsubwV, new IntrinsicInfo(0x2e203000u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64Uzp1V, new IntrinsicInfo(0x0e001800u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64Uzp2V, new IntrinsicInfo(0x0e005800u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64XtnV, new IntrinsicInfo(0x0e212800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64Zip1V, new IntrinsicInfo(0x0e003800u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64Zip2V, new IntrinsicInfo(0x0e007800u, IntrinsicType.VectorBinary));
}
private static void Add(Intrinsic intrin, IntrinsicInfo info)
{
_intrinTable[(int)intrin] = info;
}
public static IntrinsicInfo GetInfo(Intrinsic intrin)
{
return _intrinTable[(int)intrin];
}
}
}

View File

@ -0,0 +1,59 @@
namespace ARMeilleure.CodeGen.Arm64
{
enum IntrinsicType
{
ScalarUnary,
ScalarUnaryByElem,
ScalarBinary,
ScalarBinaryByElem,
ScalarBinaryFPByElem,
ScalarBinaryRd,
ScalarBinaryShl,
ScalarBinaryShr,
ScalarFcsel,
ScalarFmovi,
ScalarFPCompare,
ScalarFPCompareCond,
ScalarFPConv,
ScalarFPConvFixed,
ScalarFPConvFixedGpr,
ScalarFPConvGpr,
ScalarTernary,
ScalarTernaryFPRdByElem,
ScalarTernaryShlRd,
ScalarTernaryShrRd,
VectorUnary,
VectorUnaryBitwise,
VectorUnaryByElem,
VectorBinary,
VectorBinaryBitwise,
VectorBinaryBitwiseImm,
VectorBinaryByElem,
VectorBinaryFPByElem,
VectorBinaryRd,
VectorBinaryShl,
VectorBinaryShr,
VectorExt,
VectorFmovi,
VectorFPConvFixed,
VectorInsertByElem,
VectorLdSt,
VectorLdStSs,
VectorLookupTable,
VectorMovi,
VectorMvni,
VectorTernaryFPRdByElem,
VectorTernaryRd,
VectorTernaryRdBitwise,
VectorTernaryRdByElem,
VectorTernaryShlRd,
VectorTernaryShrRd,
Vector128Unary,
Vector128Binary,
GetRegister,
SetRegister
}
}

View File

@ -0,0 +1,940 @@
using ARMeilleure.CodeGen.RegisterAllocators;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
namespace ARMeilleure.CodeGen.Arm64
{
class PreAllocator
{
private class ConstantDict
{
private readonly Dictionary<(ulong, OperandType), Operand> _constants;
public ConstantDict()
{
_constants = new Dictionary<(ulong, OperandType), Operand>();
}
public void Add(ulong value, OperandType type, Operand local)
{
_constants.Add((value, type), local);
}
public bool TryGetValue(ulong value, OperandType type, out Operand local)
{
return _constants.TryGetValue((value, type), out local);
}
}
public static void RunPass(CompilerContext cctx, StackAllocator stackAlloc, out int maxCallArgs)
{
maxCallArgs = -1;
Span<Operation> buffer = default;
Operand[] preservedArgs = new Operand[CallingConvention.GetArgumentsOnRegsCount()];
for (BasicBlock block = cctx.Cfg.Blocks.First; block != null; block = block.ListNext)
{
ConstantDict constants = new ConstantDict();
Operation nextNode;
for (Operation node = block.Operations.First; node != default; node = nextNode)
{
nextNode = node.ListNext;
if (node.Instruction == Instruction.Phi)
{
continue;
}
HandleConstantRegCopy(constants, block.Operations, node);
HandleDestructiveRegCopy(block.Operations, node);
switch (node.Instruction)
{
case Instruction.Call:
// Get the maximum number of arguments used on a call.
// On windows, when a struct is returned from the call,
// we also need to pass the pointer where the struct
// should be written on the first argument.
int argsCount = node.SourcesCount - 1;
if (node.Destination != default && node.Destination.Type == OperandType.V128)
{
argsCount++;
}
if (maxCallArgs < argsCount)
{
maxCallArgs = argsCount;
}
// Copy values to registers expected by the function
// being called, as mandated by the ABI.
HandleCall(constants, block.Operations, node);
break;
case Instruction.CompareAndSwap:
case Instruction.CompareAndSwap16:
case Instruction.CompareAndSwap8:
nextNode = HandleCompareAndSwap(block.Operations, node);
break;
case Instruction.LoadArgument:
nextNode = HandleLoadArgument(cctx, ref buffer, block.Operations, preservedArgs, node);
break;
case Instruction.Return:
HandleReturn(block.Operations, node);
break;
case Instruction.Tailcall:
HandleTailcall(constants, block.Operations, stackAlloc, node, node);
break;
}
}
}
}
private static void HandleConstantRegCopy(ConstantDict constants, IntrusiveList<Operation> nodes, Operation node)
{
if (node.SourcesCount == 0 || IsIntrinsicWithConst(node))
{
return;
}
Instruction inst = node.Instruction;
Operand src1 = node.GetSource(0);
Operand src2;
if (src1.Kind == OperandKind.Constant)
{
if (!src1.Type.IsInteger())
{
// Handle non-integer types (FP32, FP64 and V128).
// For instructions without an immediate operand, we do the following:
// - Insert a copy with the constant value (as integer) to a GPR.
// - Insert a copy from the GPR to a XMM register.
// - Replace the constant use with the XMM register.
src1 = AddFloatConstantCopy(constants, nodes, node, src1);
node.SetSource(0, src1);
}
else if (!HasConstSrc1(node, src1.Value))
{
// Handle integer types.
// Most ALU instructions accepts a 32-bits immediate on the second operand.
// We need to ensure the following:
// - If the constant is on operand 1, we need to move it.
// -- But first, we try to swap operand 1 and 2 if the instruction is commutative.
// -- Doing so may allow us to encode the constant as operand 2 and avoid a copy.
// - If the constant is on operand 2, we check if the instruction supports it,
// if not, we also add a copy. 64-bits constants are usually not supported.
if (IsCommutative(node))
{
src2 = node.GetSource(1);
Operand temp = src1;
src1 = src2;
src2 = temp;
node.SetSource(0, src1);
node.SetSource(1, src2);
}
if (src1.Kind == OperandKind.Constant)
{
src1 = AddIntConstantCopy(constants, nodes, node, src1);
node.SetSource(0, src1);
}
}
}
if (node.SourcesCount < 2)
{
return;
}
src2 = node.GetSource(1);
if (src2.Kind == OperandKind.Constant)
{
if (!src2.Type.IsInteger())
{
src2 = AddFloatConstantCopy(constants, nodes, node, src2);
node.SetSource(1, src2);
}
else if (!HasConstSrc2(inst, src2))
{
src2 = AddIntConstantCopy(constants, nodes, node, src2);
node.SetSource(1, src2);
}
}
if (node.SourcesCount < 3 ||
node.Instruction == Instruction.BranchIf ||
node.Instruction == Instruction.Compare ||
node.Instruction == Instruction.VectorInsert ||
node.Instruction == Instruction.VectorInsert16 ||
node.Instruction == Instruction.VectorInsert8)
{
return;
}
for (int srcIndex = 2; srcIndex < node.SourcesCount; srcIndex++)
{
Operand src = node.GetSource(srcIndex);
if (src.Kind == OperandKind.Constant)
{
if (!src.Type.IsInteger())
{
src = AddFloatConstantCopy(constants, nodes, node, src);
node.SetSource(srcIndex, src);
}
else
{
src = AddIntConstantCopy(constants, nodes, node, src);
node.SetSource(srcIndex, src);
}
}
}
}
private static void HandleDestructiveRegCopy(IntrusiveList<Operation> nodes, Operation node)
{
if (node.Destination == default || node.SourcesCount == 0)
{
return;
}
Operand dest = node.Destination;
Operand src1 = node.GetSource(0);
if (IsSameOperandDestSrc1(node) && src1.Kind == OperandKind.LocalVariable)
{
bool useNewLocal = false;
for (int srcIndex = 1; srcIndex < node.SourcesCount; srcIndex++)
{
if (node.GetSource(srcIndex) == dest)
{
useNewLocal = true;
break;
}
}
if (useNewLocal)
{
// Dest is being used as some source already, we need to use a new
// local to store the temporary value, otherwise the value on dest
// local would be overwritten.
Operand temp = Local(dest.Type);
nodes.AddBefore(node, Operation(Instruction.Copy, temp, src1));
node.SetSource(0, temp);
nodes.AddAfter(node, Operation(Instruction.Copy, dest, temp));
node.Destination = temp;
}
else
{
nodes.AddBefore(node, Operation(Instruction.Copy, dest, src1));
node.SetSource(0, dest);
}
}
}
private static void HandleCall(ConstantDict constants, IntrusiveList<Operation> nodes, Operation node)
{
Operation operation = node;
Operand dest = operation.Destination;
List<Operand> sources = new List<Operand>
{
operation.GetSource(0)
};
int argsCount = operation.SourcesCount - 1;
int intMax = CallingConvention.GetArgumentsOnRegsCount();
int vecMax = CallingConvention.GetArgumentsOnRegsCount();
int intCount = 0;
int vecCount = 0;
int stackOffset = 0;
for (int index = 0; index < argsCount; index++)
{
Operand source = operation.GetSource(index + 1);
bool passOnReg;
if (source.Type.IsInteger())
{
passOnReg = intCount < intMax;
}
else if (source.Type == OperandType.V128)
{
passOnReg = intCount + 1 < intMax;
}
else
{
passOnReg = vecCount < vecMax;
}
if (source.Type == OperandType.V128 && passOnReg)
{
// V128 is a struct, we pass each half on a GPR if possible.
Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
Operand argReg2 = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg, source, Const(0)));
nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg2, source, Const(1)));
continue;
}
if (passOnReg)
{
Operand argReg = source.Type.IsInteger()
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
Operation copyOp = Operation(Instruction.Copy, argReg, source);
HandleConstantRegCopy(constants, nodes, nodes.AddBefore(node, copyOp));
sources.Add(argReg);
}
else
{
Operand offset = Const(stackOffset);
Operation spillOp = Operation(Instruction.SpillArg, default, offset, source);
HandleConstantRegCopy(constants, nodes, nodes.AddBefore(node, spillOp));
stackOffset += source.Type.GetSizeInBytes();
}
}
if (dest != default)
{
if (dest.Type == OperandType.V128)
{
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, retLReg));
nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, retHReg, Const(1)));
operation.Destination = default;
}
else
{
Operand retReg = dest.Type.IsInteger()
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
Operation copyOp = Operation(Instruction.Copy, dest, retReg);
nodes.AddAfter(node, copyOp);
operation.Destination = retReg;
}
}
operation.SetSources(sources.ToArray());
}
private static void HandleTailcall(
ConstantDict constants,
IntrusiveList<Operation> nodes,
StackAllocator stackAlloc,
Operation node,
Operation operation)
{
List<Operand> sources = new List<Operand>
{
operation.GetSource(0)
};
int argsCount = operation.SourcesCount - 1;
int intMax = CallingConvention.GetArgumentsOnRegsCount();
int vecMax = CallingConvention.GetArgumentsOnRegsCount();
int intCount = 0;
int vecCount = 0;
// Handle arguments passed on registers.
for (int index = 0; index < argsCount; index++)
{
Operand source = operation.GetSource(1 + index);
bool passOnReg;
if (source.Type.IsInteger())
{
passOnReg = intCount + 1 < intMax;
}
else
{
passOnReg = vecCount < vecMax;
}
if (source.Type == OperandType.V128 && passOnReg)
{
// V128 is a struct, we pass each half on a GPR if possible.
Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
Operand argReg2 = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg, source, Const(0)));
nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg2, source, Const(1)));
continue;
}
if (passOnReg)
{
Operand argReg = source.Type.IsInteger()
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
Operation copyOp = Operation(Instruction.Copy, argReg, source);
HandleConstantRegCopy(constants, nodes, nodes.AddBefore(node, copyOp));
sources.Add(argReg);
}
else
{
throw new NotImplementedException("Spilling is not currently supported for tail calls. (too many arguments)");
}
}
// The target address must be on the return registers, since we
// don't return anything and it is guaranteed to not be a
// callee saved register (which would be trashed on the epilogue).
Operand tcAddress = Gpr(CodeGenCommon.TcAddressRegister, OperandType.I64);
Operation addrCopyOp = Operation(Instruction.Copy, tcAddress, operation.GetSource(0));
nodes.AddBefore(node, addrCopyOp);
sources[0] = tcAddress;
operation.SetSources(sources.ToArray());
}
private static Operation HandleCompareAndSwap(IntrusiveList<Operation> nodes, Operation node)
{
Operand expected = node.GetSource(1);
if (expected.Type == OperandType.V128)
{
Operand dest = node.Destination;
Operand expectedLow = Local(OperandType.I64);
Operand expectedHigh = Local(OperandType.I64);
Operand desiredLow = Local(OperandType.I64);
Operand desiredHigh = Local(OperandType.I64);
Operand actualLow = Local(OperandType.I64);
Operand actualHigh = Local(OperandType.I64);
Operand address = node.GetSource(0);
Operand desired = node.GetSource(2);
void SplitOperand(Operand source, Operand low, Operand high)
{
nodes.AddBefore(node, Operation(Instruction.VectorExtract, low, source, Const(0)));
nodes.AddBefore(node, Operation(Instruction.VectorExtract, high, source, Const(1)));
}
SplitOperand(expected, expectedLow, expectedHigh);
SplitOperand(desired, desiredLow, desiredHigh);
Operation operation = node;
// Update the sources and destinations with split 64-bit halfs of the whole 128-bit values.
// We also need a additional registers that will be used to store temporary information.
operation.SetDestinations(new[] { actualLow, actualHigh, Local(OperandType.I64), Local(OperandType.I64) });
operation.SetSources(new[] { address, expectedLow, expectedHigh, desiredLow, desiredHigh });
// Add some dummy uses of the input operands, as the CAS operation will be a loop,
// so they can't be used as destination operand.
for (int i = 0; i < operation.SourcesCount; i++)
{
Operand src = operation.GetSource(i);
node = nodes.AddAfter(node, Operation(Instruction.Copy, src, src));
}
// Assemble the vector with the 64-bit values at the given memory location.
node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, actualLow));
node = nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, actualHigh, Const(1)));
}
else
{
// We need a additional register where the store result will be written to.
node.SetDestinations(new[] { node.Destination, Local(OperandType.I32) });
// Add some dummy uses of the input operands, as the CAS operation will be a loop,
// so they can't be used as destination operand.
Operation operation = node;
for (int i = 0; i < operation.SourcesCount; i++)
{
Operand src = operation.GetSource(i);
node = nodes.AddAfter(node, Operation(Instruction.Copy, src, src));
}
}
return node.ListNext;
}
private static void HandleReturn(IntrusiveList<Operation> nodes, Operation node)
{
if (node.SourcesCount == 0)
{
return;
}
Operand source = node.GetSource(0);
if (source.Type == OperandType.V128)
{
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
nodes.AddBefore(node, Operation(Instruction.VectorExtract, retLReg, source, Const(0)));
nodes.AddBefore(node, Operation(Instruction.VectorExtract, retHReg, source, Const(1)));
}
else
{
Operand retReg = source.Type.IsInteger()
? Gpr(CallingConvention.GetIntReturnRegister(), source.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), source.Type);
Operation retCopyOp = Operation(Instruction.Copy, retReg, source);
nodes.AddBefore(node, retCopyOp);
}
}
private static Operation HandleLoadArgument(
CompilerContext cctx,
ref Span<Operation> buffer,
IntrusiveList<Operation> nodes,
Operand[] preservedArgs,
Operation node)
{
Operand source = node.GetSource(0);
Debug.Assert(source.Kind == OperandKind.Constant, "Non-constant LoadArgument source kind.");
int index = source.AsInt32();
int intCount = 0;
int vecCount = 0;
for (int cIndex = 0; cIndex < index; cIndex++)
{
OperandType argType = cctx.FuncArgTypes[cIndex];
if (argType.IsInteger())
{
intCount++;
}
else if (argType == OperandType.V128)
{
intCount += 2;
}
else
{
vecCount++;
}
}
bool passOnReg;
if (source.Type.IsInteger())
{
passOnReg = intCount < CallingConvention.GetArgumentsOnRegsCount();
}
else if (source.Type == OperandType.V128)
{
passOnReg = intCount + 1 < CallingConvention.GetArgumentsOnRegsCount();
}
else
{
passOnReg = vecCount < CallingConvention.GetArgumentsOnRegsCount();
}
if (passOnReg)
{
Operand dest = node.Destination;
if (preservedArgs[index] == default)
{
if (dest.Type == OperandType.V128)
{
// V128 is a struct, we pass each half on a GPR if possible.
Operand pArg = Local(OperandType.V128);
Operand argLReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount), OperandType.I64);
Operand argHReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount + 1), OperandType.I64);
Operation copyL = Operation(Instruction.VectorCreateScalar, pArg, argLReg);
Operation copyH = Operation(Instruction.VectorInsert, pArg, pArg, argHReg, Const(1));
cctx.Cfg.Entry.Operations.AddFirst(copyH);
cctx.Cfg.Entry.Operations.AddFirst(copyL);
preservedArgs[index] = pArg;
}
else
{
Operand pArg = Local(dest.Type);
Operand argReg = dest.Type.IsInteger()
? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type);
Operation copyOp = Operation(Instruction.Copy, pArg, argReg);
cctx.Cfg.Entry.Operations.AddFirst(copyOp);
preservedArgs[index] = pArg;
}
}
Operation nextNode;
if (dest.AssignmentsCount == 1)
{
// Let's propagate the argument if we can to avoid copies.
Propagate(ref buffer, dest, preservedArgs[index]);
nextNode = node.ListNext;
}
else
{
Operation argCopyOp = Operation(Instruction.Copy, dest, preservedArgs[index]);
nextNode = nodes.AddBefore(node, argCopyOp);
}
Delete(nodes, node);
return nextNode;
}
else
{
// TODO: Pass on stack.
return node;
}
}
private static void Propagate(ref Span<Operation> buffer, Operand dest, Operand value)
{
ReadOnlySpan<Operation> uses = dest.GetUses(ref buffer);
foreach (Operation use in uses)
{
for (int srcIndex = 0; srcIndex < use.SourcesCount; srcIndex++)
{
Operand useSrc = use.GetSource(srcIndex);
if (useSrc == dest)
{
use.SetSource(srcIndex, value);
}
else if (useSrc.Kind == OperandKind.Memory)
{
MemoryOperand memoryOp = useSrc.GetMemory();
Operand baseAddr = memoryOp.BaseAddress;
Operand index = memoryOp.Index;
bool changed = false;
if (baseAddr == dest)
{
baseAddr = value;
changed = true;
}
if (index == dest)
{
index = value;
changed = true;
}
if (changed)
{
use.SetSource(srcIndex, MemoryOp(
useSrc.Type,
baseAddr,
index,
memoryOp.Scale,
memoryOp.Displacement));
}
}
}
}
}
private static Operand AddFloatConstantCopy(
ConstantDict constants,
IntrusiveList<Operation> nodes,
Operation node,
Operand source)
{
Operand temp = Local(source.Type);
Operand intConst = AddIntConstantCopy(constants, nodes, node, GetIntConst(source));
Operation copyOp = Operation(Instruction.VectorCreateScalar, temp, intConst);
nodes.AddBefore(node, copyOp);
return temp;
}
private static Operand AddIntConstantCopy(
ConstantDict constants,
IntrusiveList<Operation> nodes,
Operation node,
Operand source)
{
if (constants.TryGetValue(source.Value, source.Type, out Operand temp))
{
return temp;
}
temp = Local(source.Type);
Operation copyOp = Operation(Instruction.Copy, temp, source);
nodes.AddBefore(node, copyOp);
constants.Add(source.Value, source.Type, temp);
return temp;
}
private static Operand GetIntConst(Operand value)
{
if (value.Type == OperandType.FP32)
{
return Const(value.AsInt32());
}
else if (value.Type == OperandType.FP64)
{
return Const(value.AsInt64());
}
return value;
}
private static void Delete(IntrusiveList<Operation> nodes, Operation node)
{
node.Destination = default;
for (int index = 0; index < node.SourcesCount; index++)
{
node.SetSource(index, default);
}
nodes.Remove(node);
}
private static Operand Gpr(int register, OperandType type)
{
return Register(register, RegisterType.Integer, type);
}
private static Operand Xmm(int register, OperandType type)
{
return Register(register, RegisterType.Vector, type);
}
private static bool IsSameOperandDestSrc1(Operation operation)
{
switch (operation.Instruction)
{
case Instruction.Extended:
return IsSameOperandDestSrc1(operation.Intrinsic);
case Instruction.VectorInsert:
case Instruction.VectorInsert16:
case Instruction.VectorInsert8:
return true;
}
return false;
}
private static bool IsSameOperandDestSrc1(Intrinsic intrinsic)
{
IntrinsicInfo info = IntrinsicTable.GetInfo(intrinsic & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask));
return info.Type == IntrinsicType.ScalarBinaryRd ||
info.Type == IntrinsicType.ScalarTernaryFPRdByElem ||
info.Type == IntrinsicType.ScalarTernaryShlRd ||
info.Type == IntrinsicType.ScalarTernaryShrRd ||
info.Type == IntrinsicType.VectorBinaryRd ||
info.Type == IntrinsicType.VectorInsertByElem ||
info.Type == IntrinsicType.VectorTernaryRd ||
info.Type == IntrinsicType.VectorTernaryRdBitwise ||
info.Type == IntrinsicType.VectorTernaryFPRdByElem ||
info.Type == IntrinsicType.VectorTernaryRdByElem ||
info.Type == IntrinsicType.VectorTernaryShlRd ||
info.Type == IntrinsicType.VectorTernaryShrRd;
}
private static bool HasConstSrc1(Operation node, ulong value)
{
switch (node.Instruction)
{
case Instruction.Add:
case Instruction.BranchIf:
case Instruction.Compare:
case Instruction.Subtract:
// The immediate encoding of those instructions does not allow Rn to be
// XZR (it will be SP instead), so we can't allow a Rn constant in this case.
return value == 0 && NotConstOrConst0(node.GetSource(1));
case Instruction.BitwiseAnd:
case Instruction.BitwiseExclusiveOr:
case Instruction.BitwiseNot:
case Instruction.BitwiseOr:
case Instruction.ByteSwap:
case Instruction.CountLeadingZeros:
case Instruction.Multiply:
case Instruction.Negate:
case Instruction.RotateRight:
case Instruction.ShiftLeft:
case Instruction.ShiftRightSI:
case Instruction.ShiftRightUI:
return value == 0;
case Instruction.Copy:
case Instruction.LoadArgument:
case Instruction.Spill:
case Instruction.SpillArg:
return true;
case Instruction.Extended:
return value == 0;
}
return false;
}
private static bool NotConstOrConst0(Operand operand)
{
return operand.Kind != OperandKind.Constant || operand.Value == 0;
}
private static bool HasConstSrc2(Instruction inst, Operand operand)
{
ulong value = operand.Value;
switch (inst)
{
case Instruction.Add:
case Instruction.BranchIf:
case Instruction.Compare:
case Instruction.Subtract:
return ConstFitsOnUImm12Sh(value);
case Instruction.BitwiseAnd:
case Instruction.BitwiseExclusiveOr:
case Instruction.BitwiseOr:
return value == 0 || CodeGenCommon.TryEncodeBitMask(operand, out _, out _, out _);
case Instruction.Multiply:
case Instruction.Store:
case Instruction.Store16:
case Instruction.Store8:
return value == 0;
case Instruction.RotateRight:
case Instruction.ShiftLeft:
case Instruction.ShiftRightSI:
case Instruction.ShiftRightUI:
case Instruction.VectorExtract:
case Instruction.VectorExtract16:
case Instruction.VectorExtract8:
return true;
case Instruction.Extended:
// TODO: Check if actual intrinsic is supposed to have consts here?
// Right now we only hit this case for fixed-point int <-> FP conversion instructions.
return true;
}
return false;
}
private static bool IsCommutative(Operation operation)
{
switch (operation.Instruction)
{
case Instruction.Add:
case Instruction.BitwiseAnd:
case Instruction.BitwiseExclusiveOr:
case Instruction.BitwiseOr:
case Instruction.Multiply:
return true;
case Instruction.BranchIf:
case Instruction.Compare:
{
Operand comp = operation.GetSource(2);
Debug.Assert(comp.Kind == OperandKind.Constant);
var compType = (Comparison)comp.AsInt32();
return compType == Comparison.Equal || compType == Comparison.NotEqual;
}
}
return false;
}
private static bool ConstFitsOnUImm12Sh(ulong value)
{
return (value & ~0xfffUL) == 0 || (value & ~0xfff000UL) == 0;
}
private static bool IsIntrinsicWithConst(Operation operation)
{
bool isIntrinsic = IsIntrinsic(operation.Instruction);
if (isIntrinsic)
{
Intrinsic intrinsic = operation.Intrinsic;
IntrinsicInfo info = IntrinsicTable.GetInfo(intrinsic & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask));
// Those have integer inputs that don't support consts.
return info.Type != IntrinsicType.ScalarFPConvGpr &&
info.Type != IntrinsicType.ScalarFPConvFixedGpr &&
info.Type != IntrinsicType.SetRegister;
}
return false;
}
private static bool IsIntrinsic(Instruction inst)
{
return inst == Instruction.Extended;
}
}
}

View File

@ -48,9 +48,21 @@ namespace ARMeilleure.CodeGen
/// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
public T Map<T>()
{
IntPtr codePtr = JitCache.Map(this);
return MapWithPointer<T>(out _);
}
return Marshal.GetDelegateForFunctionPointer<T>(codePtr);
/// <summary>
/// Maps the <see cref="CompiledFunction"/> onto the <see cref="JitCache"/> and returns a delegate of type
/// <typeparamref name="T"/> pointing to the mapped function.
/// </summary>
/// <typeparam name="T">Type of delegate</typeparam>
/// <param name="codePointer">Pointer to the function code in memory</param>
/// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
public T MapWithPointer<T>(out IntPtr codePointer)
{
codePointer = JitCache.Map(this);
return Marshal.GetDelegateForFunctionPointer<T>(codePointer);
}
}
}

View File

@ -90,6 +90,47 @@ namespace ARMeilleure.CodeGen.Optimizations
}
break;
case Instruction.Compare:
if (type == OperandType.I32 &&
operation.GetSource(0).Type == type &&
operation.GetSource(1).Type == type)
{
switch ((Comparison)operation.GetSource(2).Value)
{
case Comparison.Equal:
EvaluateBinaryI32(operation, (x, y) => x == y ? 1 : 0);
break;
case Comparison.NotEqual:
EvaluateBinaryI32(operation, (x, y) => x != y ? 1 : 0);
break;
case Comparison.Greater:
EvaluateBinaryI32(operation, (x, y) => x > y ? 1 : 0);
break;
case Comparison.LessOrEqual:
EvaluateBinaryI32(operation, (x, y) => x <= y ? 1 : 0);
break;
case Comparison.GreaterUI:
EvaluateBinaryI32(operation, (x, y) => (uint)x > (uint)y ? 1 : 0);
break;
case Comparison.LessOrEqualUI:
EvaluateBinaryI32(operation, (x, y) => (uint)x <= (uint)y ? 1 : 0);
break;
case Comparison.GreaterOrEqual:
EvaluateBinaryI32(operation, (x, y) => x >= y ? 1 : 0);
break;
case Comparison.Less:
EvaluateBinaryI32(operation, (x, y) => x < y ? 1 : 0);
break;
case Comparison.GreaterOrEqualUI:
EvaluateBinaryI32(operation, (x, y) => (uint)x >= (uint)y ? 1 : 0);
break;
case Comparison.LessUI:
EvaluateBinaryI32(operation, (x, y) => (uint)x < (uint)y ? 1 : 0);
break;
}
}
break;
case Instruction.Copy:
if (type == OperandType.I32)
{

View File

@ -44,8 +44,8 @@ namespace ARMeilleure.CodeGen.Optimizations
ConstantFolding.RunPass(node);
Simplification.RunPass(node);
if (DestIsLocalVar(node))
{
if (DestIsSingleLocalVar(node))
{
if (IsPropagableCompare(node))
{
modified |= PropagateCompare(ref buffer, node);
@ -99,20 +99,6 @@ namespace ARMeilleure.CodeGen.Optimizations
while (modified);
}
private static Span<Operation> GetUses(ref Span<Operation> buffer, Operand operand)
{
ReadOnlySpan<Operation> uses = operand.Uses;
if (buffer.Length < uses.Length)
{
buffer = Allocators.Default.AllocateSpan<Operation>((uint)uses.Length);
}
uses.CopyTo(buffer);
return buffer.Slice(0, uses.Length);
}
private static bool PropagateCompare(ref Span<Operation> buffer, Operation compOp)
{
// Try to propagate Compare operations into their BranchIf uses, when these BranchIf uses are in the form
@ -160,7 +146,7 @@ namespace ARMeilleure.CodeGen.Optimizations
Comparison compType = (Comparison)comp.AsInt32();
Span<Operation> uses = GetUses(ref buffer, dest);
Span<Operation> uses = dest.GetUses(ref buffer);
foreach (Operation use in uses)
{
@ -199,7 +185,7 @@ namespace ARMeilleure.CodeGen.Optimizations
Operand dest = copyOp.Destination;
Operand source = copyOp.GetSource(0);
Span<Operation> uses = GetUses(ref buffer, dest);
Span<Operation> uses = dest.GetUses(ref buffer);
foreach (Operation use in uses)
{
@ -231,12 +217,12 @@ namespace ARMeilleure.CodeGen.Optimizations
private static bool IsUnused(Operation node)
{
return DestIsLocalVar(node) && node.Destination.UsesCount == 0 && !HasSideEffects(node);
return DestIsSingleLocalVar(node) && node.Destination.UsesCount == 0 && !HasSideEffects(node);
}
private static bool DestIsLocalVar(Operation node)
private static bool DestIsSingleLocalVar(Operation node)
{
return node.Destination != default && node.Destination.Kind == OperandKind.LocalVariable;
return node.DestinationsCount == 1 && node.Destination.Kind == OperandKind.LocalVariable;
}
private static bool HasSideEffects(Operation node)

View File

@ -1,6 +1,6 @@
namespace ARMeilleure.CodeGen.RegisterAllocators
{
struct AllocationResult
readonly struct AllocationResult
{
public int IntUsedRegisters { get; }
public int VecUsedRegisters { get; }

View File

@ -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; }

View File

@ -11,7 +11,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
class HybridAllocator : IRegisterAllocator
{
private struct BlockInfo
private readonly struct BlockInfo
{
public bool HasCall { get; }

View File

@ -17,8 +17,6 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private const int InstructionGap = 2;
private const int InstructionGapMask = InstructionGap - 1;
private const int RegistersCount = 16;
private HashSet<int> _blockEdges;
private LiveRange[] _blockRanges;
private BitMap[] _blockLiveIn;
@ -59,7 +57,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
void PopulateFreePositions(RegisterType type, out int[] positions, out int count)
{
positions = new int[RegistersCount];
positions = new int[masks.RegistersCount];
count = BitOperations.PopCount((uint)masks.GetAvailableRegisters(type));
int mask = masks.GetAvailableRegisters(type);
@ -115,7 +113,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
StackAllocator stackAlloc,
RegisterMasks regMasks)
{
NumberLocals(cfg);
NumberLocals(cfg, regMasks.RegistersCount);
var context = new AllocationContext(stackAlloc, regMasks, _intervals.Count);
@ -134,22 +132,25 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
context.Active.Set(index);
if (current.Register.Type == RegisterType.Integer)
if (current.IsFixedAndUsed)
{
context.IntUsedRegisters |= 1 << current.Register.Index;
}
else /* if (interval.Register.Type == RegisterType.Vector) */
{
context.VecUsedRegisters |= 1 << current.Register.Index;
if (current.Register.Type == RegisterType.Integer)
{
context.IntUsedRegisters |= 1 << current.Register.Index;
}
else /* if (interval.Register.Type == RegisterType.Vector) */
{
context.VecUsedRegisters |= 1 << current.Register.Index;
}
}
continue;
}
AllocateInterval(context, current, index);
AllocateInterval(context, current, index, regMasks.RegistersCount);
}
for (int index = RegistersCount * 2; index < _intervals.Count; index++)
for (int index = regMasks.RegistersCount * 2; index < _intervals.Count; index++)
{
if (!_intervals[index].IsSpilled)
{
@ -163,7 +164,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
return new AllocationResult(context.IntUsedRegisters, context.VecUsedRegisters, context.StackAlloc.TotalSize);
}
private void AllocateInterval(AllocationContext context, LiveInterval current, int cIndex)
private void AllocateInterval(AllocationContext context, LiveInterval current, int cIndex, int registersCount)
{
// Check active intervals that already ended.
foreach (int iIndex in context.Active)
@ -199,17 +200,17 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
if (!TryAllocateRegWithoutSpill(context, current, cIndex))
if (!TryAllocateRegWithoutSpill(context, current, cIndex, registersCount))
{
AllocateRegWithSpill(context, current, cIndex);
AllocateRegWithSpill(context, current, cIndex, registersCount);
}
}
private bool TryAllocateRegWithoutSpill(AllocationContext context, LiveInterval current, int cIndex)
private bool TryAllocateRegWithoutSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount)
{
RegisterType regType = current.Local.Type.ToRegisterType();
Span<int> freePositions = stackalloc int[RegistersCount];
Span<int> freePositions = stackalloc int[registersCount];
context.GetFreePositions(regType, freePositions, out int freePositionsCount);
@ -278,7 +279,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
Debug.Assert(splitChild.GetStart() > current.GetStart(), "Split interval has an invalid start position.");
InsertInterval(splitChild);
InsertInterval(splitChild, registersCount);
}
else
{
@ -302,12 +303,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
return true;
}
private void AllocateRegWithSpill(AllocationContext context, LiveInterval current, int cIndex)
private void AllocateRegWithSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount)
{
RegisterType regType = current.Local.Type.ToRegisterType();
Span<int> usePositions = stackalloc int[RegistersCount];
Span<int> blockedPositions = stackalloc int[RegistersCount];
Span<int> usePositions = stackalloc int[registersCount];
Span<int> blockedPositions = stackalloc int[registersCount];
context.GetFreePositions(regType, usePositions, out _);
context.GetFreePositions(regType, blockedPositions, out _);
@ -386,7 +387,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
Debug.Assert(splitChild.GetStart() > current.GetStart(), "Split interval has an invalid start position.");
InsertInterval(splitChild);
InsertInterval(splitChild, registersCount);
Spill(context, current);
}
@ -396,7 +397,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
// so we only need to split the intervals using the selected register.
current.Register = new Register(selectedReg, regType);
SplitAndSpillOverlappingIntervals(context, current);
SplitAndSpillOverlappingIntervals(context, current, registersCount);
context.Active.Set(cIndex);
}
@ -417,14 +418,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
Debug.Assert(splitChild.GetStart() > current.GetStart(), "Split interval has an invalid start position.");
InsertInterval(splitChild);
InsertInterval(splitChild, registersCount);
}
else
{
Spill(context, splitChild);
}
SplitAndSpillOverlappingIntervals(context, current);
SplitAndSpillOverlappingIntervals(context, current, registersCount);
context.Active.Set(cIndex);
}
@ -460,7 +461,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
return selected;
}
private void SplitAndSpillOverlappingIntervals(AllocationContext context, LiveInterval current)
private void SplitAndSpillOverlappingIntervals(AllocationContext context, LiveInterval current, int registersCount)
{
foreach (int iIndex in context.Active)
{
@ -468,7 +469,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (!interval.IsFixed && interval.Register == current.Register)
{
SplitAndSpillOverlappingInterval(context, current, interval);
SplitAndSpillOverlappingInterval(context, current, interval, registersCount);
context.Active.Clear(iIndex);
}
@ -480,7 +481,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (!interval.IsFixed && interval.Register == current.Register && interval.Overlaps(current))
{
SplitAndSpillOverlappingInterval(context, current, interval);
SplitAndSpillOverlappingInterval(context, current, interval, registersCount);
context.Inactive.Clear(iIndex);
}
@ -490,7 +491,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private void SplitAndSpillOverlappingInterval(
AllocationContext context,
LiveInterval current,
LiveInterval interval)
LiveInterval interval,
int registersCount)
{
// If there's a next use after the start of the current interval,
// we need to split the spilled interval twice, and re-insert it
@ -522,7 +524,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
splitChild = right;
}
InsertInterval(splitChild);
InsertInterval(splitChild, registersCount);
}
else
{
@ -530,13 +532,13 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
private void InsertInterval(LiveInterval interval)
private void InsertInterval(LiveInterval interval, int registersCount)
{
Debug.Assert(interval.UsesCount != 0, "Trying to insert a interval without uses.");
Debug.Assert(!interval.IsEmpty, "Trying to insert a empty interval.");
Debug.Assert(!interval.IsSpilled, "Trying to insert a spilled interval.");
int startIndex = RegistersCount * 2;
int startIndex = registersCount * 2;
int insertIndex = _intervals.BinarySearch(startIndex, _intervals.Count - startIndex, interval, null);
@ -790,12 +792,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
return _operationNodes[position / InstructionGap];
}
private void NumberLocals(ControlFlowGraph cfg)
private void NumberLocals(ControlFlowGraph cfg, int registersCount)
{
_operationNodes = new List<(IntrusiveList<Operation>, Operation)>();
_intervals = new List<LiveInterval>();
for (int index = 0; index < RegistersCount; index++)
for (int index = 0; index < registersCount; index++)
{
_intervals.Add(new LiveInterval(new Register(index, RegisterType.Integer)));
_intervals.Add(new LiveInterval(new Register(index, RegisterType.Vector)));
@ -1041,6 +1043,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
LiveInterval interval = _intervals[GetOperandId(dest)];
if (interval.IsFixed)
{
interval.IsFixedAndUsed = true;
}
interval.SetStart(operationPos + 1);
interval.AddUsePosition(operationPos + 1);
}

View File

@ -27,6 +27,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public Register Register;
public bool IsFixed;
public bool IsFixedAndUsed;
}
private readonly Data* _data;
@ -44,6 +45,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public ref int SpillOffset => ref _data->SpillOffset;
public bool IsFixed => _data->IsFixed;
public ref bool IsFixedAndUsed => ref _data->IsFixedAndUsed;
public bool IsEmpty => FirstRange == default;
public bool IsSplit => Children.Count != 0;
public bool IsSpilled => SpillOffset != -1;
@ -114,7 +116,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
else
{
FirstRange = new LiveRange(position, position + 1);
FirstRange = new LiveRange(position, position + 1);
End = position + 1;
}
}

View File

@ -3,7 +3,7 @@ using System;
namespace ARMeilleure.CodeGen.RegisterAllocators
{
struct RegisterMasks
readonly struct RegisterMasks
{
public int IntAvailableRegisters { get; }
public int VecAvailableRegisters { get; }
@ -11,6 +11,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public int VecCallerSavedRegisters { get; }
public int IntCalleeSavedRegisters { get; }
public int VecCalleeSavedRegisters { get; }
public int RegistersCount { get; }
public RegisterMasks(
int intAvailableRegisters,
@ -18,7 +19,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
int intCallerSavedRegisters,
int vecCallerSavedRegisters,
int intCalleeSavedRegisters,
int vecCalleeSavedRegisters)
int vecCalleeSavedRegisters,
int registersCount)
{
IntAvailableRegisters = intAvailableRegisters;
VecAvailableRegisters = vecAvailableRegisters;
@ -26,6 +28,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
VecCallerSavedRegisters = vecCallerSavedRegisters;
IntCalleeSavedRegisters = intCalleeSavedRegisters;
VecCalleeSavedRegisters = vecCalleeSavedRegisters;
RegistersCount = registersCount;
}
public int GetAvailableRegisters(RegisterType type)

View File

@ -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)
{

View File

@ -16,6 +16,7 @@ namespace ARMeilleure.CodeGen.X86
{
static class CodeGenerator
{
private const int RegistersCount = 16;
private const int PageSize = 0x1000;
private const int StackGuardSize = 0x2000;
@ -143,7 +144,8 @@ namespace ARMeilleure.CodeGen.X86
CallingConvention.GetIntCallerSavedRegisters(),
CallingConvention.GetVecCallerSavedRegisters(),
CallingConvention.GetIntCalleeSavedRegisters(),
CallingConvention.GetVecCalleeSavedRegisters());
CallingConvention.GetVecCalleeSavedRegisters(),
RegistersCount);
AllocationResult allocResult = regAlloc.RunPass(cfg, stackAlloc, regMasks);
@ -1587,6 +1589,12 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
// We can eliminate the move if source is already 32-bit and the registers are the same.
if (dest.Value == source.Value && source.Type == OperandType.I32)
{
return;
}
context.Assembler.Mov(dest, source, OperandType.I32);
}

View File

@ -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; }

View File

@ -1,6 +1,6 @@
namespace ARMeilleure.CodeGen.X86
{
struct IntrinsicInfo
readonly struct IntrinsicInfo
{
public X86Instruction Inst { get; }
public IntrinsicType Type { get; }

View File

@ -5,184 +5,183 @@ namespace ARMeilleure.CodeGen.X86
{
static class IntrinsicTable
{
private const int BadOp = 0;
private static IntrinsicInfo[] _intrinTable;
static IntrinsicTable()
{
_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)

View File

@ -54,6 +54,7 @@ namespace ARMeilleure.CodeGen.X86
Divps,
Divsd,
Divss,
Gf2p8affineqb,
Haddpd,
Haddps,
Idiv,

View File

@ -1,4 +1,4 @@
using ARMeilleure.Diagnostics.EventSources;
using ARMeilleure.Diagnostics;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
@ -80,10 +80,7 @@ namespace ARMeilleure.Common
{
get
{
if (_disposed)
{
throw new ObjectDisposedException(null);
}
ObjectDisposedException.ThrowIf(_disposed, this);
lock (_pages)
{
@ -100,10 +97,7 @@ namespace ARMeilleure.Common
/// <exception cref="ArgumentException">Length of <paramref name="levels"/> is less than 2</exception>
public AddressTable(Level[] levels)
{
if (levels == null)
{
throw new ArgumentNullException(nameof(levels));
}
ArgumentNullException.ThrowIfNull(levels);
if (levels.Length < 2)
{
@ -141,10 +135,7 @@ namespace ARMeilleure.Common
/// <exception cref="ArgumentException"><paramref name="address"/> is not mapped</exception>
public ref TEntry GetValue(ulong address)
{
if (_disposed)
{
throw new ObjectDisposedException(null);
}
ObjectDisposedException.ThrowIf(_disposed, this);
if (!IsValid(address))
{
@ -218,7 +209,7 @@ namespace ARMeilleure.Common
_pages.Add(page);
AddressTableEventSource.Log.Allocated(size, leaf);
TranslatorEventSource.Log.AddressTableAllocated(size, leaf);
return page;
}

View File

@ -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)
{

View File

@ -49,10 +49,7 @@ namespace ARMeilleure.Common
{
get
{
if (_disposed)
{
throw new ObjectDisposedException(null);
}
ObjectDisposedException.ThrowIf(_disposed, this);
return ref _countTable.GetValue(_index);
}

View File

@ -53,10 +53,7 @@ namespace ARMeilleure.Common
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
public int Allocate()
{
if (_disposed)
{
throw new ObjectDisposedException(null);
}
ObjectDisposedException.ThrowIf(_disposed, this);
lock (_allocated)
{
@ -83,10 +80,7 @@ namespace ARMeilleure.Common
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
public void Free(int index)
{
if (_disposed)
{
throw new ObjectDisposedException(null);
}
ObjectDisposedException.ThrowIf(_disposed, this);
lock (_allocated)
{
@ -108,10 +102,7 @@ namespace ARMeilleure.Common
/// <exception cref="ArgumentException">Entry at <paramref name="index"/> is not allocated</exception>
public ref TEntry GetValue(int index)
{
if (_disposed)
{
throw new ObjectDisposedException(null);
}
ObjectDisposedException.ThrowIf(_disposed, this);
lock (_allocated)
{

View File

@ -251,6 +251,13 @@ namespace ARMeilleure.Decoders
return false;
}
// Compare and branch instructions are always conditional.
if (opCode.Instruction.Name == InstName.Cbz ||
opCode.Instruction.Name == InstName.Cbnz)
{
return false;
}
// Note: On ARM32, most instructions have conditional execution,
// so there's no "Always" (unconditional) branch like on ARM64.
// We need to check if the condition is "Always" instead.

View File

@ -151,7 +151,7 @@ namespace ARMeilleure.Decoders
public static bool VectorArgumentsInvalid(bool q, params int[] args)
{
if (q)
if (q)
{
for (int i = 0; i < args.Length; i++)
{

View File

@ -7,5 +7,8 @@
int Msb { get; }
int Lsb { get; }
int SourceMask => (int)(0xFFFFFFFF >> (31 - Msb));
int DestMask => SourceMask & (int)(0xFFFFFFFF << Lsb);
}
}

View File

@ -0,0 +1,7 @@
namespace ARMeilleure.Decoders
{
interface IOpCode32AluImm16 : IOpCode32Alu
{
int Immediate { get; }
}
}

View File

@ -0,0 +1,11 @@
namespace ARMeilleure.Decoders
{
interface IOpCode32AluMla : IOpCode32AluReg
{
int Ra { get; }
bool NHigh { get; }
bool MHigh { get; }
bool R { get; }
}
}

View File

@ -0,0 +1,13 @@
namespace ARMeilleure.Decoders
{
interface IOpCode32AluUmull : IOpCode32, IOpCode32HasSetFlags
{
int RdLo { get; }
int RdHi { get; }
int Rn { get; }
int Rm { get; }
bool NHigh { get; }
bool MHigh { get; }
}
}

View File

@ -3,6 +3,7 @@ namespace ARMeilleure.Decoders
interface IOpCode32Mem : IOpCode32
{
int Rt { get; }
int Rt2 => Rt | 1;
int Rn { get; }
bool WBack { get; }

View File

@ -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);

View File

@ -13,16 +13,13 @@ namespace ARMeilleure.Decoders
Cond = (Condition)((uint)opCode >> 28);
}
public bool IsThumb()
{
return this is OpCodeT16 || this is OpCodeT32;
}
public bool IsThumb { get; protected init; } = false;
public uint GetPc()
{
// Due to backwards compatibility and legacy behavior of ARMv4 CPUs pipeline,
// the PC actually points 2 instructions ahead.
if (IsThumb())
if (IsThumb)
{
// PC is ahead by 4 in thumb mode whether or not the current instruction
// is 16 or 32 bit.

View File

@ -6,12 +6,8 @@
public int Rn { get; }
public int Msb { get; }
public int Lsb { get; }
public int SourceMask => (int)(0xFFFFFFFF >> (31 - Msb));
public int DestMask => SourceMask & (int)(0xFFFFFFFF << Lsb);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluBf(inst, address, opCode);
public OpCode32AluBf(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)

View File

@ -1,6 +1,6 @@
namespace ARMeilleure.Decoders
{
class OpCode32AluImm16 : OpCode32Alu
class OpCode32AluImm16 : OpCode32Alu, IOpCode32AluImm16
{
public int Immediate { get; }

View File

@ -1,6 +1,6 @@
namespace ARMeilleure.Decoders
{
class OpCode32AluMla : OpCode32, IOpCode32AluReg
class OpCode32AluMla : OpCode32, IOpCode32AluMla
{
public int Rn { get; }
public int Rm { get; }

View File

@ -1,6 +1,6 @@
namespace ARMeilleure.Decoders
{
class OpCode32AluUmull : OpCode32, IOpCode32HasSetFlags
class OpCode32AluUmull : OpCode32, IOpCode32AluUmull
{
public int RdLo { get; }
public int RdHi { get; }
@ -11,7 +11,6 @@
public bool MHigh { get; }
public bool? SetFlags { get; }
public DataOp DataOp { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluUmull(inst, address, opCode);
@ -26,7 +25,6 @@
MHigh = ((opCode >> 6) & 0x1) == 1;
SetFlags = ((opCode >> 20) & 0x1) != 0;
DataOp = DataOp.Arithmetic;
}
}
}

View File

@ -7,14 +7,15 @@
public bool F { get; protected set; }
public bool U { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32Simd(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32Simd(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32Simd(inst, address, opCode, true);
public OpCode32Simd(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32Simd(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Size = (opCode >> 20) & 0x3;
Q = ((opCode >> 6) & 0x1) != 0;
F = ((opCode >> 10) & 0x1) != 0;
U = ((opCode >> 24) & 0x1) != 0;
U = ((opCode >> (isThumb ? 28 : 24)) & 0x1) != 0;
Opc = (opCode >> 7) & 0x3;
RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;

View File

@ -47,6 +47,9 @@ namespace ARMeilleure.Decoders
throw new InvalidOperationException();
}
public OpCode32SimdBase(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { }
protected OpCode32SimdBase(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{
IsThumb = isThumb;
}
}
}

View File

@ -5,9 +5,10 @@
/// </summary>
class OpCode32SimdBinary : OpCode32SimdReg
{
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdBinary(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdBinary(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdBinary(inst, address, opCode, true);
public OpCode32SimdBinary(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdBinary(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Size = 3;

View File

@ -2,9 +2,10 @@
{
class OpCode32SimdCmpZ : OpCode32Simd
{
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCmpZ(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCmpZ(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCmpZ(inst, address, opCode, true);
public OpCode32SimdCmpZ(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdCmpZ(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Size = (opCode >> 18) & 0x3;

View File

@ -2,9 +2,10 @@
{
class OpCode32SimdCvtFI : OpCode32SimdS
{
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtFI(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtFI(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtFI(inst, address, opCode, true);
public OpCode32SimdCvtFI(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdCvtFI(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Opc = (opCode >> 7) & 0x1;

View 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);
}
}
}
}

View File

@ -4,9 +4,10 @@
{
public int Index { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupElem(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupElem(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupElem(inst, address, opCode, true);
public OpCode32SimdDupElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdDupElem(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
var opc = (opCode >> 16) & 0xf;

View File

@ -7,10 +7,13 @@
public int Rt { get; }
public bool Q { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupGP(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupGP(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupGP(inst, address, opCode, true);
public OpCode32SimdDupGP(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdDupGP(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{
IsThumb = isThumb;
Size = 2 - (((opCode >> 21) & 0x2) | ((opCode >> 5) & 0x1)); // B:E - 0 for 32, 16 then 8.
if (Size == -1)
{

View File

@ -4,9 +4,10 @@
{
public int Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdExt(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdExt(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdExt(inst, address, opCode, true);
public OpCode32SimdExt(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdExt(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Immediate = (opCode >> 8) & 0xf;
Size = 0;

View File

@ -6,9 +6,10 @@
public long Immediate { get; }
public int Elems => GetBytesCount() >> Size;
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm(inst, address, opCode, true);
public OpCode32SimdImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdImm(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Vd = (opCode >> 12) & 0xf;
Vd |= (opCode >> 18) & 0x10;
@ -22,7 +23,7 @@
imm = ((uint)opCode >> 0) & 0xf;
imm |= ((uint)opCode >> 12) & 0x70;
imm |= ((uint)opCode >> 17) & 0x80;
imm |= ((uint)opCode >> (isThumb ? 21 : 17)) & 0x80;
(Immediate, Size) = OpCodeSimdHelper.GetSimdImmediateAndSize(cMode, op, imm);

View File

@ -7,10 +7,13 @@
public int Size { get; }
public int Elems { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm44(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm44(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm44(inst, address, opCode, true);
public OpCode32SimdImm44(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdImm44(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{
IsThumb = isThumb;
Size = (opCode >> 8) & 0x3;
bool single = Size != 3;

View File

@ -4,9 +4,10 @@
{
public bool U { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdLong(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdLong(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdLong(inst, address, opCode, true);
public OpCode32SimdLong(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdLong(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
int imm3h = (opCode >> 19) & 0x7;
@ -18,7 +19,7 @@
case 4: Size = 2; break;
}
U = ((opCode >> 24) & 0x1) != 0;
U = ((opCode >> (isThumb ? 28 : 24)) & 0x1) != 0;
RegisterSize = RegisterSize.Simd64;

View File

@ -8,10 +8,13 @@
public bool Add { get; }
public int Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemImm(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemImm(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemImm(inst, address, opCode, true);
public OpCode32SimdMemImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdMemImm(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{
IsThumb = isThumb;
Immediate = opCode & 0xff;
Rn = (opCode >> 16) & 0xf;

View File

@ -12,10 +12,13 @@
public bool DoubleWidth { get; }
public bool Add { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemMult(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemMult(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemMult(inst, address, opCode, true);
public OpCode32SimdMemMult(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdMemMult(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{
IsThumb = isThumb;
Rn = (opCode >> 16) & 0xf;
bool isLoad = (opCode & (1 << 20)) != 0;

View File

@ -1,11 +1,10 @@
using ARMeilleure.State;
using System;
namespace ARMeilleure.Decoders
{
class OpCode32SimdMemPair : OpCode32, IOpCode32Simd
{
private static int[] RegsMap =
private static int[] _regsMap =
{
1, 1, 4, 2,
1, 1, 3, 1,
@ -24,10 +23,13 @@ namespace ARMeilleure.Decoders
public int Regs { get; }
public int Increment { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemPair(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemPair(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemPair(inst, address, opCode, true);
public OpCode32SimdMemPair(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdMemPair(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{
IsThumb = isThumb;
Vd = (opCode >> 12) & 0xf;
Vd |= (opCode >> 18) & 0x10;
@ -40,9 +42,9 @@ namespace ARMeilleure.Decoders
WBack = Rm != RegisterAlias.Aarch32Pc;
RegisterIndex = Rm != RegisterAlias.Aarch32Pc && Rm != RegisterAlias.Aarch32Sp;
Regs = RegsMap[(opCode >> 8) & 0xf];
Regs = _regsMap[(opCode >> 8) & 0xf];
Increment = Math.Min(Regs, ((opCode >> 8) & 0x1) + 1);
Increment = ((opCode >> 8) & 0x1) + 1;
}
}
}

View File

@ -15,10 +15,13 @@ namespace ARMeilleure.Decoders
public bool Replicate { get; }
public int Increment { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemSingle(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemSingle(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemSingle(inst, address, opCode, true);
public OpCode32SimdMemSingle(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdMemSingle(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{
IsThumb = isThumb;
Vd = (opCode >> 12) & 0xf;
Vd |= (opCode >> 18) & 0x10;

View File

@ -11,10 +11,13 @@
public int Opc1 { get; }
public int Opc2 { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGp(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGp(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGp(inst, address, opCode, true);
public OpCode32SimdMovGp(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdMovGp(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{
IsThumb = isThumb;
// Which one is used is instruction dependant.
Op = (opCode >> 20) & 0x1;

View File

@ -9,10 +9,13 @@
public int Rt2 { get; }
public int Op { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpDouble(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpDouble(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpDouble(inst, address, opCode, true);
public OpCode32SimdMovGpDouble(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdMovGpDouble(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{
IsThumb = isThumb;
// Which one is used is instruction dependant.
Op = (opCode >> 20) & 0x1;

View File

@ -11,10 +11,13 @@
public int Index { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpElem(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpElem(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpElem(inst, address, opCode, true);
public OpCode32SimdMovGpElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdMovGpElem(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{
IsThumb = isThumb;
Op = (opCode >> 20) & 0x1;
U = ((opCode >> 23) & 1) != 0;

View File

@ -0,0 +1,13 @@
namespace ARMeilleure.Decoders
{
class OpCode32SimdMovn : OpCode32Simd
{
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovn(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovn(inst, address, opCode, true);
public OpCode32SimdMovn(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Size = (opCode >> 18) & 0x3;
}
}
}

View File

@ -8,9 +8,10 @@
public int In => GetQuadwordSubindex(Vn) << (3 - Size);
public int Fn => GetQuadwordSubindex(Vn) << (1 - (Size & 1));
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdReg(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdReg(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdReg(inst, address, opCode, true);
public OpCode32SimdReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdReg(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Vn = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf);

View File

@ -2,11 +2,12 @@
{
class OpCode32SimdRegElem : OpCode32SimdReg
{
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElem(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElem(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElem(inst, address, opCode, true);
public OpCode32SimdRegElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdRegElem(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Q = ((opCode >> 24) & 0x1) != 0;
Q = ((opCode >> (isThumb ? 28 : 24)) & 0x1) != 0;
F = ((opCode >> 8) & 0x1) != 0;
Size = (opCode >> 20) & 0x3;

View File

@ -2,9 +2,10 @@
{
class OpCode32SimdRegElemLong : OpCode32SimdRegElem
{
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElemLong(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElemLong(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElemLong(inst, address, opCode, true);
public OpCode32SimdRegElemLong(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdRegElemLong(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Q = false;
F = false;

View File

@ -4,9 +4,10 @@
{
public bool Polynomial { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegLong(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegLong(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegLong(inst, address, opCode, true);
public OpCode32SimdRegLong(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdRegLong(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Q = false;
RegisterSize = RegisterSize.Simd64;

View File

@ -4,9 +4,10 @@
{
public int Vn { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegS(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegS(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegS(inst, address, opCode, true);
public OpCode32SimdRegS(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdRegS(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
bool single = Size != 3;
if (single)

View File

@ -2,9 +2,10 @@
{
class OpCode32SimdRegWide : OpCode32SimdReg
{
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegWide(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegWide(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegWide(inst, address, opCode, true);
public OpCode32SimdRegWide(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdRegWide(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Q = false;
RegisterSize = RegisterSize.Simd64;

View File

@ -2,9 +2,10 @@
{
class OpCode32SimdRev : OpCode32SimdCmpZ
{
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRev(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRev(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRev(inst, address, opCode, true);
public OpCode32SimdRev(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdRev(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
if (Opc + Size >= 3)
{

View File

@ -8,10 +8,13 @@
public int Opc2 { get; } // opc2 or RM (opc2<1:0>) [Vcvt, Vrint].
public int Size { get; protected set; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdS(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdS(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdS(inst, address, opCode, true);
public OpCode32SimdS(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdS(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{
IsThumb = isThumb;
Opc = (opCode >> 15) & 0x3;
Opc2 = (opCode >> 16) & 0x7;

View File

@ -4,9 +4,10 @@
{
public OpCode32SimdSelMode Cc { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSel(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSel(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSel(inst, address, opCode, true);
public OpCode32SimdSel(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdSel(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Cc = (OpCode32SimdSelMode)((opCode >> 20) & 3);
}

View File

@ -4,9 +4,10 @@
{
public int Shift { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImm(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImm(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImm(inst, address, opCode, true);
public OpCode32SimdShImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdShImm(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
int imm6 = (opCode >> 16) & 0x3f;
int limm6 = ((opCode >> 1) & 0x40) | imm6;

View File

@ -4,9 +4,10 @@
{
public int Shift { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmLong(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmLong(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmLong(inst, address, opCode, true);
public OpCode32SimdShImmLong(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdShImmLong(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Q = false;
RegisterSize = RegisterSize.Simd64;

View File

@ -2,8 +2,9 @@
{
class OpCode32SimdShImmNarrow : OpCode32SimdShImm
{
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmNarrow(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmNarrow(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmNarrow(inst, address, opCode, true);
public OpCode32SimdShImmNarrow(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { }
public OpCode32SimdShImmNarrow(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb) { }
}
}

View File

@ -5,10 +5,13 @@
public int Rt { get; }
public int Sreg { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSpecial(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSpecial(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSpecial(inst, address, opCode, true);
public OpCode32SimdSpecial(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdSpecial(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{
IsThumb = isThumb;
Rt = (opCode >> 12) & 0xf;
Sreg = (opCode >> 16) & 0xf;
}

View File

@ -2,9 +2,10 @@
{
class OpCode32SimdSqrte : OpCode32Simd
{
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSqrte(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSqrte(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSqrte(inst, address, opCode, true);
public OpCode32SimdSqrte(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdSqrte(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Size = (opCode >> 18) & 0x1;
F = ((opCode >> 8) & 0x1) != 0;

View File

@ -4,9 +4,10 @@
{
public int Length { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdTbl(inst, address, opCode);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdTbl(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdTbl(inst, address, opCode, true);
public OpCode32SimdTbl(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
public OpCode32SimdTbl(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Length = (opCode >> 8) & 3;
Size = 0;

View File

@ -8,6 +8,7 @@ namespace ARMeilleure.Decoders
{
Cond = Condition.Al;
IsThumb = true;
OpCodeSizeInBytes = 2;
}
}

View File

@ -4,14 +4,13 @@ namespace ARMeilleure.Decoders
{
public int Rd { get; }
public bool Add => true;
public int Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16Adr(inst, address, opCode);
public OpCodeT16Adr(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rd = (opCode >> 8) & 7;
Rd = (opCode >> 8) & 7;
int imm = (opCode & 0xff) << 2;
Immediate = (int)(GetPc() & 0xfffffffc) + imm;

Some files were not shown because too many files have changed in this diff Show More