mirror of
https://git.ryujinx.app/projects/Kenji-NX.git
synced 2026-09-27 22:38:13 +02:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbf78ba55e |
+21
-90
@@ -1,31 +1,19 @@
|
|||||||
# Remove the line below if you want to inherit .editorconfig settings from higher directories
|
# Remove the line below if you want to inherit .editorconfig settings from higher directories
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
[*]
|
# C# files
|
||||||
|
[*.cs]
|
||||||
|
|
||||||
#### Core EditorConfig Options ####
|
#### Core EditorConfig Options ####
|
||||||
|
|
||||||
# Set default charset
|
|
||||||
charset = utf-8
|
|
||||||
|
|
||||||
# Indentation and spacing
|
# Indentation and spacing
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
indent_style = space
|
indent_style = space
|
||||||
tab_width = 4
|
tab_width = 4
|
||||||
|
|
||||||
# New line preferences
|
# New line preferences
|
||||||
end_of_line = lf
|
end_of_line = crlf
|
||||||
insert_final_newline = true
|
insert_final_newline = false
|
||||||
|
|
||||||
# Markdown, JSON, YAML, props and csproj files
|
|
||||||
[*.{md,json,yml,props,csproj}]
|
|
||||||
|
|
||||||
# Indentation and spacing
|
|
||||||
indent_size = 2
|
|
||||||
tab_width = 2
|
|
||||||
|
|
||||||
# C# files
|
|
||||||
[*.cs]
|
|
||||||
|
|
||||||
#### .NET Coding Conventions ####
|
#### .NET Coding Conventions ####
|
||||||
|
|
||||||
@@ -71,7 +59,7 @@ dotnet_style_prefer_simplified_interpolation = true:suggestion
|
|||||||
dotnet_style_readonly_field = true:suggestion
|
dotnet_style_readonly_field = true:suggestion
|
||||||
|
|
||||||
# Parameter preferences
|
# Parameter preferences
|
||||||
dotnet_code_quality_unused_parameters = all:silent
|
dotnet_code_quality_unused_parameters = all:suggestion
|
||||||
|
|
||||||
#### C# Coding Conventions ####
|
#### C# Coding Conventions ####
|
||||||
|
|
||||||
@@ -97,7 +85,7 @@ csharp_style_expression_bodied_properties = true:silent
|
|||||||
# Pattern matching preferences
|
# Pattern matching preferences
|
||||||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||||
csharp_style_prefer_switch_expression = false:silent
|
csharp_style_prefer_switch_expression = true:suggestion
|
||||||
|
|
||||||
# Null-checking preferences
|
# Null-checking preferences
|
||||||
csharp_style_conditional_delegate_call = true:suggestion
|
csharp_style_conditional_delegate_call = true:suggestion
|
||||||
@@ -106,7 +94,6 @@ csharp_style_conditional_delegate_call = true:suggestion
|
|||||||
csharp_prefer_static_local_function = true:suggestion
|
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_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
|
csharp_style_prefer_readonly_struct = true
|
||||||
csharp_style_prefer_method_group_conversion = true
|
|
||||||
|
|
||||||
# Code-block preferences
|
# Code-block preferences
|
||||||
csharp_prefer_braces = true:silent
|
csharp_prefer_braces = true:silent
|
||||||
@@ -122,7 +109,6 @@ csharp_style_prefer_range_operator = true:suggestion
|
|||||||
csharp_style_throw_expression = true:suggestion
|
csharp_style_throw_expression = true:suggestion
|
||||||
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
|
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
|
||||||
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
|
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
|
||||||
csharp_style_implicit_object_creation_when_type_is_apparent = true
|
|
||||||
|
|
||||||
# 'using' directive preferences
|
# 'using' directive preferences
|
||||||
csharp_using_directive_placement = outside_namespace:silent
|
csharp_using_directive_placement = outside_namespace:silent
|
||||||
@@ -154,6 +140,7 @@ csharp_space_after_dot = false
|
|||||||
csharp_space_after_keywords_in_control_flow_statements = true
|
csharp_space_after_keywords_in_control_flow_statements = true
|
||||||
csharp_space_after_semicolon_in_for_statement = true
|
csharp_space_after_semicolon_in_for_statement = true
|
||||||
csharp_space_around_binary_operators = before_and_after
|
csharp_space_around_binary_operators = before_and_after
|
||||||
|
csharp_space_around_declaration_statements = false
|
||||||
csharp_space_before_colon_in_inheritance_clause = true
|
csharp_space_before_colon_in_inheritance_clause = true
|
||||||
csharp_space_before_comma = false
|
csharp_space_before_comma = false
|
||||||
csharp_space_before_dot = false
|
csharp_space_before_dot = false
|
||||||
@@ -171,31 +158,23 @@ csharp_space_between_square_brackets = false
|
|||||||
|
|
||||||
# Wrapping preferences
|
# Wrapping preferences
|
||||||
csharp_preserve_single_line_blocks = true
|
csharp_preserve_single_line_blocks = true
|
||||||
csharp_preserve_single_line_statements = false
|
csharp_preserve_single_line_statements = true
|
||||||
|
|
||||||
#### Naming styles ####
|
#### Naming styles ####
|
||||||
|
|
||||||
# Naming rules
|
# Naming rules
|
||||||
|
|
||||||
dotnet_naming_rule.interfaces_should_be_prefixed_with_I.severity = suggestion
|
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
|
||||||
dotnet_naming_rule.interfaces_should_be_prefixed_with_I.symbols = interface
|
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
|
||||||
dotnet_naming_rule.interfaces_should_be_prefixed_with_I.style = IPascalCase
|
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
|
||||||
|
|
||||||
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
|
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
|
||||||
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
|
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
|
||||||
dotnet_naming_rule.types_should_be_pascal_case.style = PascalCase
|
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
|
||||||
|
|
||||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
|
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
|
||||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
|
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
|
||||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = PascalCase
|
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
|
||||||
|
|
||||||
dotnet_naming_rule.private_static_readonly_fields_should_be_camel_case_and_prefixed_with__.symbols = private_static_readonly_fields
|
|
||||||
dotnet_naming_rule.private_static_readonly_fields_should_be_camel_case_and_prefixed_with__.severity = suggestion
|
|
||||||
dotnet_naming_rule.private_static_readonly_fields_should_be_camel_case_and_prefixed_with__.style = _camelCase
|
|
||||||
|
|
||||||
dotnet_naming_rule.local_constants_should_be_pascal_case.symbols = local_constants
|
|
||||||
dotnet_naming_rule.local_constants_should_be_pascal_case.severity = suggestion
|
|
||||||
dotnet_naming_rule.local_constants_should_be_pascal_case.style = PascalCase
|
|
||||||
|
|
||||||
# Symbol specifications
|
# Symbol specifications
|
||||||
|
|
||||||
@@ -211,62 +190,14 @@ dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, meth
|
|||||||
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||||
dotnet_naming_symbols.non_field_members.required_modifiers =
|
dotnet_naming_symbols.non_field_members.required_modifiers =
|
||||||
|
|
||||||
dotnet_naming_symbols.private_static_readonly_fields.applicable_kinds = field
|
|
||||||
dotnet_naming_symbols.private_static_readonly_fields.applicable_accessibilities = private
|
|
||||||
dotnet_naming_symbols.private_static_readonly_fields.required_modifiers = static, readonly
|
|
||||||
|
|
||||||
dotnet_naming_symbols.local_constants.applicable_kinds = local
|
|
||||||
dotnet_naming_symbols.local_constants.applicable_accessibilities = local
|
|
||||||
dotnet_naming_symbols.local_constants.required_modifiers = const
|
|
||||||
|
|
||||||
# Naming styles
|
# Naming styles
|
||||||
|
|
||||||
dotnet_naming_style._camelCase.required_prefix = _
|
dotnet_naming_style.pascal_case.required_prefix =
|
||||||
dotnet_naming_style._camelCase.required_suffix =
|
dotnet_naming_style.pascal_case.required_suffix =
|
||||||
dotnet_naming_style._camelCase.word_separator =
|
dotnet_naming_style.pascal_case.word_separator =
|
||||||
dotnet_naming_style._camelCase.capitalization = camel_case
|
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||||
|
|
||||||
dotnet_naming_style.PascalCase.required_prefix =
|
dotnet_naming_style.begins_with_i.required_prefix = I
|
||||||
dotnet_naming_style.PascalCase.required_suffix =
|
dotnet_naming_style.begins_with_i.required_suffix =
|
||||||
dotnet_naming_style.PascalCase.word_separator =
|
dotnet_naming_style.begins_with_i.word_separator =
|
||||||
dotnet_naming_style.PascalCase.capitalization = pascal_case
|
dotnet_naming_style.begins_with_i.capitalization = pascal_case
|
||||||
|
|
||||||
dotnet_naming_style.IPascalCase.required_prefix = I
|
|
||||||
dotnet_naming_style.IPascalCase.required_suffix =
|
|
||||||
dotnet_naming_style.IPascalCase.word_separator =
|
|
||||||
dotnet_naming_style.IPascalCase.capitalization = pascal_case
|
|
||||||
|
|
||||||
# TODO:
|
|
||||||
# .NET 8 migration (new warnings are caused by the NET 8 C# compiler and analyzer)
|
|
||||||
# The following info messages might need to be fixed in the source code instead of hiding the actual message
|
|
||||||
# Without the following lines, dotnet format would fail
|
|
||||||
# Disable "Collection initialization can be simplified"
|
|
||||||
dotnet_diagnostic.IDE0028.severity = none
|
|
||||||
dotnet_diagnostic.IDE0300.severity = none
|
|
||||||
dotnet_diagnostic.IDE0301.severity = none
|
|
||||||
dotnet_diagnostic.IDE0302.severity = none
|
|
||||||
dotnet_diagnostic.IDE0305.severity = none
|
|
||||||
# Disable "'new' expression can be simplified"
|
|
||||||
dotnet_diagnostic.IDE0090.severity = none
|
|
||||||
# Disable "Use primary constructor"
|
|
||||||
dotnet_diagnostic.IDE0290.severity = none
|
|
||||||
# Disable "Member '' does not access instance data and can be marked as static"
|
|
||||||
dotnet_diagnostic.CA1822.severity = none
|
|
||||||
# Disable "Change type of field '' from '' to '' for improved performance"
|
|
||||||
dotnet_diagnostic.CA1859.severity = none
|
|
||||||
# Disable "Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array"
|
|
||||||
dotnet_diagnostic.CA1861.severity = none
|
|
||||||
# Disable "Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'"
|
|
||||||
dotnet_diagnostic.CA1862.severity = none
|
|
||||||
|
|
||||||
[src/Ryujinx/UI/ViewModels/**.cs]
|
|
||||||
# Disable "mark members as static" rule for ViewModels
|
|
||||||
dotnet_diagnostic.CA1822.severity = none
|
|
||||||
|
|
||||||
[src/Ryujinx.HLE/HOS/Services/**.cs]
|
|
||||||
# Disable "mark members as static" rule for services
|
|
||||||
dotnet_diagnostic.CA1822.severity = none
|
|
||||||
|
|
||||||
[src/Ryujinx.Tests/Cpu/*.cs]
|
|
||||||
# Disable naming rules for CPU tests
|
|
||||||
dotnet_diagnostic.IDE1006.severity = none
|
|
||||||
@@ -23,7 +23,7 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: Log file
|
label: Log file
|
||||||
description: A log file will help our developers to better diagnose and fix the issue.
|
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. They can also be accessed by opening Ryujinx, then going to File > Open Logs Folder. You can drag and drop the log on to the text area (do not copy paste).
|
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:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
name: Feature Request
|
name: Feature Request
|
||||||
description: Suggest a new feature for Ryujinx.
|
description: Suggest a new feature for Ryujinx.
|
||||||
title: "[Feature Request]"
|
title: "[Feature Request]"
|
||||||
labels: enhancement
|
|
||||||
body:
|
body:
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: overview
|
id: overview
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"problemMatcher": [
|
|
||||||
{
|
|
||||||
"owner": "csc",
|
|
||||||
"pattern": [
|
|
||||||
{
|
|
||||||
"regexp": "^((?:\\\\|/)(?:[^\\\\/:]+(?:\\\\|/))+[^\\\\/]+)\\((\\d+),(\\d+)\\):\\s+([a-zA-Z]+)\\s+([^:]+):\\s+([^[]+)\\s+\\[",
|
|
||||||
"file": 1,
|
|
||||||
"line": 2,
|
|
||||||
"column": 3,
|
|
||||||
"severity": 4,
|
|
||||||
"code": 5,
|
|
||||||
"message": 6
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
+3
-19
@@ -7,34 +7,18 @@ updates:
|
|||||||
labels:
|
labels:
|
||||||
- "infra"
|
- "infra"
|
||||||
reviewers:
|
reviewers:
|
||||||
- TSRBerry
|
- marysaka
|
||||||
commit-message:
|
commit-message:
|
||||||
prefix: "ci"
|
prefix: "ci"
|
||||||
|
|
||||||
- package-ecosystem: nuget
|
- package-ecosystem: nuget
|
||||||
directory: /
|
directory: /
|
||||||
open-pull-requests-limit: 10
|
open-pull-requests-limit: 5
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
labels:
|
labels:
|
||||||
- "infra"
|
- "infra"
|
||||||
reviewers:
|
reviewers:
|
||||||
- TSRBerry
|
- marysaka
|
||||||
commit-message:
|
commit-message:
|
||||||
prefix: nuget
|
prefix: nuget
|
||||||
groups:
|
|
||||||
Avalonia:
|
|
||||||
patterns:
|
|
||||||
- "*Avalonia*"
|
|
||||||
Silk.NET:
|
|
||||||
patterns:
|
|
||||||
- "Silk.NET*"
|
|
||||||
OpenTK:
|
|
||||||
patterns:
|
|
||||||
- "OpenTK*"
|
|
||||||
SixLabors:
|
|
||||||
patterns:
|
|
||||||
- "SixLabors*"
|
|
||||||
NUnit:
|
|
||||||
patterns:
|
|
||||||
- "NUnit*"
|
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
audio:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: 'src/Ryujinx.Audio*/**'
|
|
||||||
|
|
||||||
cpu:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: ['src/ARMeilleure/**', 'src/Ryujinx.Cpu/**', 'src/Ryujinx.Memory/**']
|
|
||||||
|
|
||||||
gpu:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: ['src/Ryujinx.Graphics.*/**', 'src/Spv.Generator/**', 'src/Ryujinx.ShaderTools/**']
|
|
||||||
|
|
||||||
'graphics-backend:opengl':
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: 'src/Ryujinx.Graphics.OpenGL/**'
|
|
||||||
|
|
||||||
'graphics-backend:vulkan':
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: ['src/Ryujinx.Graphics.Vulkan/**', 'src/Spv.Generator/**']
|
|
||||||
|
|
||||||
gui:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: ['src/Ryujinx/**', 'src/Ryujinx.UI.Common/**', 'src/Ryujinx.UI.LocaleGenerator/**', 'src/Ryujinx.Gtk3/**']
|
|
||||||
|
|
||||||
horizon:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: ['src/Ryujinx.HLE/**', 'src/Ryujinx.Horizon/**']
|
|
||||||
|
|
||||||
kernel:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: 'src/Ryujinx.HLE/HOS/Kernel/**'
|
|
||||||
|
|
||||||
infra:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: ['.github/**', 'distribution/**', 'Directory.Packages.props']
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
|
|
||||||
cpu:
|
|
||||||
- gdkchan
|
|
||||||
- riperiperi
|
|
||||||
- LDj3SNuD
|
|
||||||
|
|
||||||
gpu:
|
|
||||||
- gdkchan
|
|
||||||
- riperiperi
|
|
||||||
|
|
||||||
gui:
|
|
||||||
- Ack77
|
|
||||||
- emmauss
|
|
||||||
- TSRBerry
|
|
||||||
|
|
||||||
horizon:
|
|
||||||
- gdkchan
|
|
||||||
- Ack77
|
|
||||||
- TSRBerry
|
|
||||||
|
|
||||||
infra:
|
|
||||||
- TSRBerry
|
|
||||||
|
|
||||||
default:
|
|
||||||
- '@developers'
|
|
||||||
+69
-73
@@ -1,7 +1,26 @@
|
|||||||
name: Build job
|
name: Build job
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_dispatch:
|
||||||
|
inputs: {}
|
||||||
|
#push:
|
||||||
|
# branches: [ master ]
|
||||||
|
# paths-ignore:
|
||||||
|
# - '.github/*'
|
||||||
|
# - '.github/ISSUE_TEMPLATE/**'
|
||||||
|
# - '*.yml'
|
||||||
|
# - 'README.md'
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
paths-ignore:
|
||||||
|
- '.github/*'
|
||||||
|
- '.github/ISSUE_TEMPLATE/**'
|
||||||
|
- '*.yml'
|
||||||
|
- 'README.md'
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: pr-checks-${{ github.event.number }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||||
@@ -10,94 +29,87 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: ${{ matrix.platform.name }} (${{ matrix.configuration }})
|
name: ${{ matrix.OS_NAME }} (${{ matrix.configuration }})
|
||||||
runs-on: ${{ matrix.platform.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||||
configuration: [Debug, Release]
|
configuration: [Debug, Release]
|
||||||
platform:
|
include:
|
||||||
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
- os: ubuntu-latest
|
||||||
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
|
OS_NAME: Linux x64
|
||||||
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
|
DOTNET_RUNTIME_IDENTIFIER: linux-x64
|
||||||
- { name: osx-x64, os: macos-13, zip_os_name: osx_x64 }
|
RELEASE_ZIP_OS_NAME: linux_x64
|
||||||
|
|
||||||
|
- os: macOS-latest
|
||||||
|
OS_NAME: macOS x64
|
||||||
|
DOTNET_RUNTIME_IDENTIFIER: osx-x64
|
||||||
|
RELEASE_ZIP_OS_NAME: osx_x64
|
||||||
|
|
||||||
|
- os: windows-latest
|
||||||
|
OS_NAME: Windows x64
|
||||||
|
DOTNET_RUNTIME_IDENTIFIER: win10-x64
|
||||||
|
RELEASE_ZIP_OS_NAME: win_x64
|
||||||
|
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v4
|
- uses: actions/setup-dotnet@v3
|
||||||
with:
|
with:
|
||||||
global-json-file: global.json
|
global-json-file: global.json
|
||||||
|
|
||||||
- name: Overwrite csc problem matcher
|
|
||||||
run: echo "::add-matcher::.github/csc.json"
|
|
||||||
|
|
||||||
- name: Get git short hash
|
- name: Get git short hash
|
||||||
id: git_short_hash
|
id: git_short_hash
|
||||||
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Change config filename
|
|
||||||
run: sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
shell: bash
|
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
|
||||||
|
|
||||||
- name: Change config filename for macOS
|
|
||||||
run: sed -r -i '' 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
shell: bash
|
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os == 'macos-13'
|
|
||||||
|
|
||||||
- name: Build
|
- 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
|
- name: Test
|
||||||
uses: TSRBerry/unstable-commands@v1
|
run: dotnet test --no-build -c "${{ matrix.configuration }}"
|
||||||
with:
|
|
||||||
commands: dotnet test --no-build -c "${{ matrix.configuration }}"
|
|
||||||
timeout-minutes: 10
|
|
||||||
retry-codes: 139
|
|
||||||
if: matrix.platform.name != 'linux-arm64'
|
|
||||||
|
|
||||||
- name: Publish Ryujinx
|
- name: Publish Ryujinx
|
||||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx --self-contained true
|
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 src/Ryujinx --self-contained true
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||||
|
|
||||||
- name: Publish Ryujinx.Headless.SDL2
|
- name: Publish Ryujinx.Headless.SDL2
|
||||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -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 src/Ryujinx.Headless.SDL2 --self-contained true
|
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 src/Ryujinx.Headless.SDL2 --self-contained true
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||||
|
|
||||||
- name: Publish Ryujinx.Gtk3
|
- name: Publish Ryujinx.Ava
|
||||||
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish_gtk -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Gtk3 --self-contained true
|
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 src/Ryujinx.Ava --self-contained true
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||||
|
|
||||||
- name: Set executable bit
|
- name: Set executable bit
|
||||||
run: |
|
run: |
|
||||||
chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh
|
chmod +x ./publish/Ryujinx ./publish/Ryujinx.sh
|
||||||
chmod +x ./publish_sdl2_headless/Ryujinx.Headless.SDL2 ./publish_sdl2_headless/Ryujinx.sh
|
chmod +x ./publish_sdl2_headless/Ryujinx.Headless.SDL2 ./publish_sdl2_headless/Ryujinx.sh
|
||||||
chmod +x ./publish_gtk/Ryujinx.Gtk3 ./publish_gtk/Ryujinx.sh
|
chmod +x ./publish_ava/Ryujinx.Ava ./publish_ava/Ryujinx.sh
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os == 'ubuntu-latest'
|
if: github.event_name == 'pull_request' && matrix.os == 'ubuntu-latest'
|
||||||
|
|
||||||
- name: Upload Ryujinx artifact
|
- name: Upload Ryujinx artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
|
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||||
path: publish
|
path: publish
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||||
|
|
||||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
- name: Upload Ryujinx.Headless.SDL2 artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
|
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
|
path: publish_sdl2_headless
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||||
|
|
||||||
- name: Upload Ryujinx.Gtk3 artifact
|
- name: Upload Ryujinx.Ava artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: gtk-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
|
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||||
path: publish_gtk
|
path: publish_ava
|
||||||
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
|
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||||
|
|
||||||
build_macos:
|
build_macos:
|
||||||
name: macOS Universal (${{ matrix.configuration }})
|
name: macOS Universal (${{ matrix.configuration }})
|
||||||
@@ -108,9 +120,9 @@ jobs:
|
|||||||
configuration: [ Debug, Release ]
|
configuration: [ Debug, Release ]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v4
|
- uses: actions/setup-dotnet@v3
|
||||||
with:
|
with:
|
||||||
global-json-file: global.json
|
global-json-file: global.json
|
||||||
|
|
||||||
@@ -135,29 +147,13 @@ jobs:
|
|||||||
id: git_short_hash
|
id: git_short_hash
|
||||||
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
run: echo "result=$(git rev-parse --short "${{ github.sha }}")" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Change config filename
|
- name: Publish macOS
|
||||||
run: sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
shell: bash
|
|
||||||
if: github.event_name == 'pull_request'
|
|
||||||
|
|
||||||
- name: Publish macOS Ryujinx
|
|
||||||
run: |
|
run: |
|
||||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp publish ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
./distribution/macos/create_macos_build.sh . publish_tmp publish_ava ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
||||||
|
|
||||||
- name: Publish macOS Ryujinx.Headless.SDL2
|
- name: Upload Ryujinx.Ava artifact
|
||||||
run: |
|
uses: actions/upload-artifact@v3
|
||||||
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
|
||||||
|
|
||||||
- name: Upload Ryujinx artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
||||||
path: "publish/*.tar.gz"
|
path: "publish_ava/*.tar.gz"
|
||||||
if: github.event_name == 'pull_request'
|
|
||||||
|
|
||||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
|
||||||
path: "publish_headless/*.tar.gz"
|
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request'
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
name: Perform checks
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
paths:
|
|
||||||
- '**'
|
|
||||||
- '!.github/**'
|
|
||||||
- '!*.yml'
|
|
||||||
- '!*.config'
|
|
||||||
- '!*.md'
|
|
||||||
- '.github/workflows/*.yml'
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
checks: write
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: pr-checks-${{ github.event.number }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
format:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v4
|
|
||||||
with:
|
|
||||||
global-json-file: global.json
|
|
||||||
|
|
||||||
- name: Overwrite csc problem matcher
|
|
||||||
run: echo "::add-matcher::.github/csc.json"
|
|
||||||
|
|
||||||
- run: dotnet restore
|
|
||||||
|
|
||||||
- name: Print dotnet format version
|
|
||||||
run: dotnet format --version
|
|
||||||
|
|
||||||
- name: Run dotnet format whitespace
|
|
||||||
run: |
|
|
||||||
dotnet format whitespace --verify-no-changes --report ./whitespace-report.json -v d
|
|
||||||
|
|
||||||
# For some unknown reason this step sometimes fails with exit code 139 (segfault?),
|
|
||||||
# so in that case we'll try again (3 tries max).
|
|
||||||
- name: Run dotnet format style
|
|
||||||
uses: TSRBerry/unstable-commands@v1
|
|
||||||
with:
|
|
||||||
commands: dotnet format style --severity info --verify-no-changes --report ./style-report.json -v d
|
|
||||||
timeout-minutes: 5
|
|
||||||
retry-codes: 139
|
|
||||||
|
|
||||||
# For some unknown reason this step sometimes fails with exit code 139 (segfault?),
|
|
||||||
# so in that case we'll try again (3 tries max).
|
|
||||||
- name: Run dotnet format analyzers
|
|
||||||
uses: TSRBerry/unstable-commands@v1
|
|
||||||
with:
|
|
||||||
commands: dotnet format analyzers --severity info --verify-no-changes --report ./analyzers-report.json -v d
|
|
||||||
timeout-minutes: 5
|
|
||||||
retry-codes: 139
|
|
||||||
|
|
||||||
- name: Upload report
|
|
||||||
if: failure()
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: dotnet-format
|
|
||||||
path: ./*-report.json
|
|
||||||
|
|
||||||
pr_build:
|
|
||||||
uses: ./.github/workflows/build.yml
|
|
||||||
needs: format
|
|
||||||
secrets: inherit
|
|
||||||
@@ -24,11 +24,11 @@ jobs:
|
|||||||
RYUJINX_VERSION: "${{ inputs.ryujinx_version }}"
|
RYUJINX_VERSION: "${{ inputs.ryujinx_version }}"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
path: Ryujinx
|
path: Ryujinx
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v4
|
- uses: actions/setup-dotnet@v3
|
||||||
with:
|
with:
|
||||||
global-json-file: Ryujinx/global.json
|
global-json-file: Ryujinx/global.json
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo "git_hash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
|
echo "git_hash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
repository: flathub/org.ryujinx.Ryujinx
|
repository: flathub/org.ryujinx.Ryujinx
|
||||||
token: ${{ secrets.RYUJINX_BOT_PAT }}
|
token: ${{ secrets.RYUJINX_BOT_PAT }}
|
||||||
@@ -49,77 +49,37 @@ jobs:
|
|||||||
run: python -m pip install PyYAML lxml
|
run: python -m pip install PyYAML lxml
|
||||||
|
|
||||||
- name: Restore Nuget packages
|
- name: Restore Nuget packages
|
||||||
# With .NET 8.0.100, Microsoft.NET.ILLink.Tasks isn't restored by default and only seems to appears when publishing.
|
run: dotnet restore Ryujinx/${{ env.RYUJINX_PROJECT_FILE }}
|
||||||
# So we just publish to grab the dependencies
|
|
||||||
run: |
|
|
||||||
dotnet publish -c Release -r linux-x64 Ryujinx/${{ env.RYUJINX_PROJECT_FILE }} --self-contained
|
|
||||||
dotnet publish -c Release -r linux-arm64 Ryujinx/${{ env.RYUJINX_PROJECT_FILE }} --self-contained
|
|
||||||
|
|
||||||
- name: Generate nuget_sources.json
|
- name: Generate nuget_sources.json
|
||||||
shell: python
|
shell: python
|
||||||
run: |
|
run: |
|
||||||
import hashlib
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import base64
|
import base64
|
||||||
import binascii
|
import binascii
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import urllib.request
|
|
||||||
|
|
||||||
sources = []
|
sources = []
|
||||||
|
|
||||||
|
for path in Path(os.environ['NUGET_PACKAGES']).glob('**/*.nupkg.sha512'):
|
||||||
def create_source_from_external(name, version):
|
|
||||||
full_dir_path = Path(os.environ["NUGET_PACKAGES"]).joinpath(name).joinpath(version)
|
|
||||||
os.makedirs(full_dir_path, exist_ok=True)
|
|
||||||
|
|
||||||
filename = "{}.{}.nupkg".format(name, version)
|
|
||||||
url = "https://api.nuget.org/v3-flatcontainer/{}/{}/{}".format(
|
|
||||||
name, version, filename
|
|
||||||
)
|
|
||||||
|
|
||||||
print(f"Processing {url}...")
|
|
||||||
response = urllib.request.urlopen(url)
|
|
||||||
sha512 = hashlib.sha512(response.read()).hexdigest()
|
|
||||||
|
|
||||||
return {
|
|
||||||
"type": "file",
|
|
||||||
"url": url,
|
|
||||||
"sha512": sha512,
|
|
||||||
"dest": os.environ["NUGET_SOURCES_DESTDIR"],
|
|
||||||
"dest-filename": filename,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
has_added_x64_apphost = False
|
|
||||||
|
|
||||||
for path in Path(os.environ["NUGET_PACKAGES"]).glob("**/*.nupkg.sha512"):
|
|
||||||
name = path.parent.parent.name
|
name = path.parent.parent.name
|
||||||
version = path.parent.name
|
version = path.parent.name
|
||||||
filename = "{}.{}.nupkg".format(name, version)
|
filename = '{}.{}.nupkg'.format(name, version)
|
||||||
url = "https://api.nuget.org/v3-flatcontainer/{}/{}/{}".format(
|
url = 'https://api.nuget.org/v3-flatcontainer/{}/{}/{}'.format(name, version, filename)
|
||||||
name, version, filename
|
|
||||||
)
|
|
||||||
|
|
||||||
with path.open() as fp:
|
with path.open() as fp:
|
||||||
sha512 = binascii.hexlify(base64.b64decode(fp.read())).decode("ascii")
|
sha512 = binascii.hexlify(base64.b64decode(fp.read())).decode('ascii')
|
||||||
|
|
||||||
sources.append(
|
sources.append({
|
||||||
{
|
'type': 'file',
|
||||||
"type": "file",
|
'url': url,
|
||||||
"url": url,
|
'sha512': sha512,
|
||||||
"sha512": sha512,
|
'dest': os.environ['NUGET_SOURCES_DESTDIR'],
|
||||||
"dest": os.environ["NUGET_SOURCES_DESTDIR"],
|
'dest-filename': filename,
|
||||||
"dest-filename": filename,
|
})
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
# .NET will not add current installed application host to the list, force inject it here.
|
with open('flathub/nuget_sources.json', 'w') as fp:
|
||||||
if not has_added_x64_apphost and name.startswith('microsoft.netcore.app.host'):
|
|
||||||
sources.append(create_source_from_external("microsoft.netcore.app.host.linux-x64", version))
|
|
||||||
has_added_x64_apphost = True
|
|
||||||
|
|
||||||
with open("flathub/nuget_sources.json", "w") as fp:
|
|
||||||
json.dump(sources, fp, indent=4)
|
json.dump(sources, fp, indent=4)
|
||||||
|
|
||||||
- name: Update flatpak metadata
|
- name: Update flatpak metadata
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
name: Mako
|
|
||||||
on:
|
|
||||||
discussion:
|
|
||||||
types: [created, edited, answered, unanswered, category_changed]
|
|
||||||
discussion_comment:
|
|
||||||
types: [created, edited]
|
|
||||||
gollum:
|
|
||||||
issue_comment:
|
|
||||||
types: [created, edited]
|
|
||||||
issues:
|
|
||||||
types: [opened, edited, reopened, pinned, milestoned, demilestoned, assigned, unassigned, labeled, unlabeled]
|
|
||||||
pull_request_target:
|
|
||||||
types: [opened, edited, reopened, synchronize, ready_for_review, assigned, unassigned]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
tasks:
|
|
||||||
name: Run Ryujinx tasks
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
discussions: write
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
if: github.event_name == 'pull_request_target'
|
|
||||||
with:
|
|
||||||
# Ensure we pin the source origin as pull_request_target run under forks.
|
|
||||||
fetch-depth: 0
|
|
||||||
repository: Ryujinx/Ryujinx
|
|
||||||
ref: master
|
|
||||||
|
|
||||||
- name: Run Mako command
|
|
||||||
uses: Ryujinx/Ryujinx-Mako@master
|
|
||||||
with:
|
|
||||||
command: exec-ryujinx-tasks
|
|
||||||
args: --event-name "${{ github.event_name }}" --event-path "${{ github.event_path }}" -w "${{ github.workspace }}" "${{ github.repository }}" "${{ github.run_id }}"
|
|
||||||
app_id: ${{ secrets.MAKO_APP_ID }}
|
|
||||||
private_key: ${{ secrets.MAKO_PRIVATE_KEY }}
|
|
||||||
installation_id: ${{ secrets.MAKO_INSTALLATION_ID }}
|
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
name: Comment PR artifacts links
|
name: Comment PR artifacts links
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_run:
|
workflow_run:
|
||||||
workflows: ['Perform checks']
|
workflows: ['Build job']
|
||||||
types: [completed]
|
types: [completed]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pr_comment:
|
pr_comment:
|
||||||
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
||||||
@@ -39,24 +37,24 @@ jobs:
|
|||||||
return core.error(`No artifacts found`);
|
return core.error(`No artifacts found`);
|
||||||
}
|
}
|
||||||
let body = `Download the artifacts for this pull request:\n`;
|
let body = `Download the artifacts for this pull request:\n`;
|
||||||
let hidden_gtk_artifacts = `\n\n <details><summary>Old GUI (GTK3)</summary>\n`;
|
let hidden_avalonia_artifacts = `\n\n <details><summary>Experimental GUI (Avalonia)</summary>\n`;
|
||||||
let hidden_headless_artifacts = `\n\n <details><summary>GUI-less (SDL2)</summary>\n`;
|
let hidden_headless_artifacts = `\n\n <details><summary>GUI-less (SDL2)</summary>\n`;
|
||||||
let hidden_debug_artifacts = `\n\n <details><summary>Only for Developers</summary>\n`;
|
let hidden_debug_artifacts = `\n\n <details><summary>Only for Developers</summary>\n`;
|
||||||
for (const art of artifacts) {
|
for (const art of artifacts) {
|
||||||
if(art.name.includes('Debug')) {
|
if(art.name.includes('Debug')) {
|
||||||
hidden_debug_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
hidden_debug_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
||||||
} else if(art.name.includes('gtk-ryujinx')) {
|
} else if(art.name.includes('ava-ryujinx')) {
|
||||||
hidden_gtk_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
hidden_avalonia_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
||||||
} else if(art.name.includes('sdl2-ryujinx-headless')) {
|
} else if(art.name.includes('sdl2-ryujinx-headless')) {
|
||||||
hidden_headless_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
hidden_headless_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
||||||
} else {
|
} else {
|
||||||
body += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
body += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hidden_gtk_artifacts += `\n</details>`;
|
hidden_avalonia_artifacts += `\n</details>`;
|
||||||
hidden_headless_artifacts += `\n</details>`;
|
hidden_headless_artifacts += `\n</details>`;
|
||||||
hidden_debug_artifacts += `\n</details>`;
|
hidden_debug_artifacts += `\n</details>`;
|
||||||
body += hidden_gtk_artifacts;
|
body += hidden_avalonia_artifacts;
|
||||||
body += hidden_headless_artifacts;
|
body += hidden_headless_artifacts;
|
||||||
body += hidden_debug_artifacts;
|
body += hidden_debug_artifacts;
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
name: "Pull Request Triage"
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types: [opened, ready_for_review]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
triage:
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
# Grab sources to get latest labeler.yml
|
|
||||||
- name: Fetch sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
# Ensure we pin the source origin as pull_request_target run under forks.
|
|
||||||
fetch-depth: 0
|
|
||||||
repository: Ryujinx/Ryujinx
|
|
||||||
ref: master
|
|
||||||
|
|
||||||
- name: Update labels based on changes
|
|
||||||
uses: actions/labeler@v5
|
|
||||||
with:
|
|
||||||
sync-labels: true
|
|
||||||
dot: true
|
|
||||||
@@ -6,11 +6,10 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches: [ master ]
|
branches: [ master ]
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '.github/**'
|
- '.github/*'
|
||||||
|
- '.github/ISSUE_TEMPLATE/**'
|
||||||
- '*.yml'
|
- '*.yml'
|
||||||
- '*.json'
|
- 'README.md'
|
||||||
- '*.config'
|
|
||||||
- '*.md'
|
|
||||||
|
|
||||||
concurrency: release
|
concurrency: release
|
||||||
|
|
||||||
@@ -25,7 +24,7 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
tag:
|
tag:
|
||||||
name: Create tag
|
name: Create tag
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Get version info
|
- name: Get version info
|
||||||
id: version_info
|
id: version_info
|
||||||
@@ -44,37 +43,30 @@ jobs:
|
|||||||
sha: context.sha
|
sha: context.sha
|
||||||
})
|
})
|
||||||
|
|
||||||
- name: Create release
|
|
||||||
uses: ncipollo/release-action@v1
|
|
||||||
with:
|
|
||||||
name: ${{ steps.version_info.outputs.build_version }}
|
|
||||||
tag: ${{ steps.version_info.outputs.build_version }}
|
|
||||||
body: "For more information about this release please check out the official [Changelog](https://github.com/Ryujinx/Ryujinx/wiki/Changelog)."
|
|
||||||
omitBodyDuringUpdate: true
|
|
||||||
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
|
|
||||||
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
|
|
||||||
token: ${{ secrets.RELEASE_TOKEN }}
|
|
||||||
|
|
||||||
release:
|
release:
|
||||||
name: Release for ${{ matrix.platform.name }}
|
name: Release ${{ matrix.OS_NAME }}
|
||||||
runs-on: ${{ matrix.platform.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
|
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
platform:
|
os: [ ubuntu-latest, windows-latest ]
|
||||||
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
|
include:
|
||||||
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
|
- os: ubuntu-latest
|
||||||
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
|
OS_NAME: Linux x64
|
||||||
steps:
|
DOTNET_RUNTIME_IDENTIFIER: linux-x64
|
||||||
- uses: actions/checkout@v4
|
RELEASE_ZIP_OS_NAME: linux_x64
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v4
|
- os: windows-latest
|
||||||
|
OS_NAME: Windows x64
|
||||||
|
DOTNET_RUNTIME_IDENTIFIER: win10-x64
|
||||||
|
RELEASE_ZIP_OS_NAME: win_x64
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- uses: actions/setup-dotnet@v3
|
||||||
with:
|
with:
|
||||||
global-json-file: global.json
|
global-json-file: global.json
|
||||||
|
|
||||||
- name: Overwrite csc problem matcher
|
|
||||||
run: echo "::add-matcher::.github/csc.json"
|
|
||||||
|
|
||||||
- name: Get version info
|
- name: Get version info
|
||||||
id: version_info
|
id: version_info
|
||||||
run: |
|
run: |
|
||||||
@@ -89,7 +81,6 @@ jobs:
|
|||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Create output dir
|
- name: Create output dir
|
||||||
@@ -97,36 +88,42 @@ jobs:
|
|||||||
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
run: |
|
run: |
|
||||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained true
|
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_gtk/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained true
|
||||||
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained true
|
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained true
|
||||||
|
dotnet publish -c Release -r "${{ matrix.DOTNET_RUNTIME_IDENTIFIER }}" -o ./publish_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Ava --self-contained true
|
||||||
|
|
||||||
- name: Packing Windows builds
|
- name: Packing Windows builds
|
||||||
if: matrix.platform.os == 'windows-latest'
|
if: matrix.os == 'windows-latest'
|
||||||
run: |
|
run: |
|
||||||
pushd publish_ava
|
pushd publish_gtk
|
||||||
cp publish/Ryujinx.exe publish/Ryujinx.Ava.exe
|
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
|
||||||
7z a ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
|
|
||||||
7z a ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
pushd publish_sdl2_headless
|
pushd publish_sdl2_headless
|
||||||
7z a ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
|
7z a ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
|
||||||
|
popd
|
||||||
|
|
||||||
|
pushd publish_ava
|
||||||
|
7z a ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip publish
|
||||||
popd
|
popd
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Packing Linux builds
|
- name: Packing Linux builds
|
||||||
if: matrix.platform.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
run: |
|
run: |
|
||||||
pushd publish_ava
|
pushd publish_gtk
|
||||||
cp publish/Ryujinx publish/Ryujinx.Ava
|
chmod +x publish/Ryujinx.sh publish/Ryujinx
|
||||||
chmod +x publish/Ryujinx.sh publish/Ryujinx.Ava publish/Ryujinx
|
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
|
||||||
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
|
|
||||||
tar -czvf ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
pushd publish_sdl2_headless
|
pushd publish_sdl2_headless
|
||||||
chmod +x publish/Ryujinx.sh publish/Ryujinx.Headless.SDL2
|
chmod +x publish/Ryujinx.sh publish/Ryujinx.Headless.SDL2
|
||||||
tar -czvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
|
tar -czvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
|
||||||
|
popd
|
||||||
|
|
||||||
|
pushd publish_ava
|
||||||
|
chmod +x publish/Ryujinx.sh publish/Ryujinx.Ava
|
||||||
|
tar -czvf ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
|
||||||
popd
|
popd
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
@@ -149,17 +146,17 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
|
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: actions/setup-dotnet@v4
|
- uses: actions/setup-dotnet@v3
|
||||||
with:
|
with:
|
||||||
global-json-file: global.json
|
global-json-file: global.json
|
||||||
|
|
||||||
- name: Setup LLVM 15
|
- name: Setup LLVM 14
|
||||||
run: |
|
run: |
|
||||||
wget https://apt.llvm.org/llvm.sh
|
wget https://apt.llvm.org/llvm.sh
|
||||||
chmod +x llvm.sh
|
chmod +x llvm.sh
|
||||||
sudo ./llvm.sh 15
|
sudo ./llvm.sh 14
|
||||||
|
|
||||||
- name: Install rcodesign
|
- name: Install rcodesign
|
||||||
run: |
|
run: |
|
||||||
@@ -185,22 +182,17 @@ jobs:
|
|||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
||||||
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
|
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Publish macOS Ryujinx
|
- name: Publish macOS
|
||||||
run: |
|
run: |
|
||||||
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release
|
./distribution/macos/create_macos_build.sh . publish_tmp publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release
|
||||||
|
|
||||||
- name: Publish macOS Ryujinx.Headless.SDL2
|
|
||||||
run: |
|
|
||||||
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release
|
|
||||||
|
|
||||||
- name: Pushing new release
|
- name: Pushing new release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
with:
|
with:
|
||||||
name: ${{ steps.version_info.outputs.build_version }}
|
name: ${{ steps.version_info.outputs.build_version }}
|
||||||
artifacts: "publish_ava/*.tar.gz, publish_headless/*.tar.gz"
|
artifacts: "publish_ava/*.tar.gz"
|
||||||
tag: ${{ steps.version_info.outputs.build_version }}
|
tag: ${{ steps.version_info.outputs.build_version }}
|
||||||
body: "For more information about this release please check out the official [Changelog](https://github.com/Ryujinx/Ryujinx/wiki/Changelog)."
|
body: "For more information about this release please check out the official [Changelog](https://github.com/Ryujinx/Ryujinx/wiki/Changelog)."
|
||||||
omitBodyDuringUpdate: true
|
omitBodyDuringUpdate: true
|
||||||
|
|||||||
@@ -173,6 +173,3 @@ PublishProfiles/
|
|||||||
|
|
||||||
# Glade backup files
|
# Glade backup files
|
||||||
*.glade~
|
*.glade~
|
||||||
|
|
||||||
# Log files
|
|
||||||
/logs/
|
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
[submodule "src/KenjinxAndroid/app/src/main/cpp/libraries/adrenotools"]
|
|
||||||
path = src/KenjinxAndroid/app/src/main/cpp/libraries/adrenotools
|
|
||||||
url = https://git.ryujinx.app/kenji-nx/libadrenotools.git
|
|
||||||
[submodule "src/KenjinxAndroid/app/src/main/cpp/libraries/openal"]
|
|
||||||
path = src/KenjinxAndroid/app/src/main/cpp/libraries/openal
|
|
||||||
url = https://git.ryujinx.app/kenji-nx/openal-soft.git
|
|
||||||
[submodule "src/KenjinxAndroid/app/src/main/cpp/libraries/adrenotools/lib/linkernsbypass"]
|
|
||||||
path = src/KenjinxAndroid/app/src/main/cpp/libraries/adrenotools/lib/linkernsbypass
|
|
||||||
url = https://git.ryujinx.app/kenji-nx/liblinkernsbypass.git
|
|
||||||
-124
@@ -1,124 +0,0 @@
|
|||||||
# Contribution to Kenji-NX
|
|
||||||
|
|
||||||
You can contribute to Kenji-NX with PRs, testing of PRs and issues. Contributing code and other implementations is greatly appreciated alongside simply filing issues for problems you encounter.
|
|
||||||
Please read the entire document before continuing as it can potentially save everyone involved a significant amount of time.
|
|
||||||
|
|
||||||
# Quick Links
|
|
||||||
|
|
||||||
* [Code Style Documentation](docs/coding-guidelines/coding-style.md)
|
|
||||||
* [Pull Request Guidelines](docs/workflow/pr-guide.md)
|
|
||||||
|
|
||||||
## Reporting Issues
|
|
||||||
|
|
||||||
We always welcome bug reports, feature proposals and overall feedback. Here are a few tips on how you can make reporting your issue as effective as possible.
|
|
||||||
|
|
||||||
### Finding Existing Issues
|
|
||||||
|
|
||||||
Before filing a new issue, please search our [open issues](https://git.ryujinx.app/kenji-nx/ryujinx/-/issues) to check if it already exists.
|
|
||||||
|
|
||||||
If you do find an existing issue, please include your own feedback in the discussion. Do consider upvoting (👍 reaction) the original post, as this helps us prioritize popular issues in our backlog.
|
|
||||||
|
|
||||||
### Writing a Good Feature Request
|
|
||||||
|
|
||||||
Please review any feature requests already opened to both check it has not already been suggested, and to familiarize yourself with the format. When ready to submit a proposal, please go [here](https://git.ryujinx.app/kenji-nx/ryujinx/-/issues).
|
|
||||||
|
|
||||||
### Writing a Good Bug Report
|
|
||||||
|
|
||||||
Good bug reports make it easier for maintainers to verify and root cause the underlying problem. The better a bug report, the faster the problem will be resolved.
|
|
||||||
Ideally, a bug report should contain the following information:
|
|
||||||
|
|
||||||
* A high-level description of the problem.
|
|
||||||
* A _minimal reproduction_, i.e. the smallest time commitment/configuration required to reproduce the wrong behavior. This can be in the form of a small homebrew application, or by providing a save file and reproduction steps for a specific game.
|
|
||||||
* A description of the _expected behavior_, contrasted with the _actual behavior_ observed.
|
|
||||||
* Information on the environment: OS/distro, CPU, GPU (including driver), RAM etc.
|
|
||||||
* A Ryujinx log file of the run instance where the issue occurred. Log files can be found in `[Executable Folder]/Logs` and are named chronologically.
|
|
||||||
* Additional information, e.g. is it a regression from previous versions? Are there any known workarounds?
|
|
||||||
|
|
||||||
When ready to submit a bug report, please go [here](https://git.ryujinx.app/kenji-nx/ryujinx/-/issues.
|
|
||||||
|
|
||||||
## Contributing Changes
|
|
||||||
|
|
||||||
Project maintainers will merge changes that both improve the project and meet our standards for code quality.
|
|
||||||
|
|
||||||
The [Pull Request Guide](docs/workflow/pr-guide.md) and [License](LICENSE.txt) docs define additional guidance.
|
|
||||||
|
|
||||||
### DOs and DON'Ts
|
|
||||||
|
|
||||||
Please do:
|
|
||||||
|
|
||||||
* **DO** follow our [coding style](docs/coding-guidelines/coding-style.md) (C# code-specific).
|
|
||||||
* **DO** give priority to the current style of the project or file you're changing even if it diverges from the general guidelines.
|
|
||||||
* **DO** keep the discussions focused. When a new or related topic comes up
|
|
||||||
it's often better to create new issue than to side track the discussion.
|
|
||||||
* **DO** clearly state on an issue that you are going to take on implementing it.
|
|
||||||
* **DO** blog and tweet (or whatever) about your contributions, frequently!
|
|
||||||
|
|
||||||
Please do not:
|
|
||||||
|
|
||||||
* **DON'T** make PRs for style changes.
|
|
||||||
* **DON'T** surprise us with big pull requests. Instead, file an issue and talk with us on Discord to start
|
|
||||||
a discussion so we can agree on a direction before you invest a large amount
|
|
||||||
of time.
|
|
||||||
* **DON'T** commit code that you didn't write. If you find code that you think is a good fit to add to Ryujinx, file an issue or talk to us on Discord to start a discussion before proceeding.
|
|
||||||
* **DON'T** submit PRs that alter licensing related files or headers. If you believe there's a problem with them, file an issue and we'll be happy to discuss it.
|
|
||||||
|
|
||||||
### Suggested Workflow
|
|
||||||
|
|
||||||
We use and recommend the following workflow:
|
|
||||||
|
|
||||||
1. Create or find an issue for your work.
|
|
||||||
- You can skip this step for trivial changes.
|
|
||||||
- Get agreement from the team and the community that your proposed change is a good one if it is of significant size or changes core functionality.
|
|
||||||
- Clearly state that you are going to take on implementing it, if that's the case. You can request that the issue be assigned to you. Note: The issue filer and the implementer don't have to be the same person.
|
|
||||||
2. Create a personal fork of the repository on GitHub (if you don't already have one).
|
|
||||||
3. In your fork, create a branch off of main (`git checkout -b mybranch`).
|
|
||||||
- Branches are useful since they isolate your changes from incoming changes from upstream. They also enable you to create multiple PRs from the same fork.
|
|
||||||
4. Make and commit your changes to your branch.
|
|
||||||
- [Build Instructions](https://git.ryujinx.app/kenji-nx/ryujinx#building) explains how to build and test.
|
|
||||||
- Commit messages should be clear statements of action and intent.
|
|
||||||
6. Build the repository with your changes.
|
|
||||||
- Make sure that the builds are clean.
|
|
||||||
- Make sure that `dotnet format` has been run and any corrections tested and committed.
|
|
||||||
7. Create a pull request (PR) against the Ryujinx/Ryujinx repository's **main** branch.
|
|
||||||
- State in the description what issue or improvement your change is addressing.
|
|
||||||
8. Wait for feedback or approval of your changes from the core development team
|
|
||||||
- Details about the pull request [review procedure](docs/workflow/ci/pr-guide.md).
|
|
||||||
9. When the team members have signed off, and all checks are green, your PR will be merged.
|
|
||||||
- The next official build will automatically include your change.
|
|
||||||
- You can delete the branch you used for making the change.
|
|
||||||
|
|
||||||
### Commit Messages
|
|
||||||
|
|
||||||
Please format commit messages as follows (based on [A Note About Git Commit Messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)):
|
|
||||||
|
|
||||||
```
|
|
||||||
Summarize change in 50 characters or less
|
|
||||||
|
|
||||||
Provide more detail after the first line. Leave one blank line below the
|
|
||||||
summary and wrap all lines at 72 characters or less.
|
|
||||||
|
|
||||||
If the change fixes an issue, leave another blank line after the final
|
|
||||||
paragraph and indicate which issue is fixed in the specific format
|
|
||||||
below.
|
|
||||||
|
|
||||||
Fix #42
|
|
||||||
```
|
|
||||||
|
|
||||||
Also do your best to factor commits appropriately, not too large with unrelated things in the same commit, and not too small with the same small change applied N times in N different commits.
|
|
||||||
|
|
||||||
### PR Feedback
|
|
||||||
|
|
||||||
Ryujinx team and community members will provide feedback on your change. Community feedback is highly valued. You may see the absence of team feedback if the community has already provided good review feedback.
|
|
||||||
|
|
||||||
Two Ryujinx team members must review and approve every PR prior to merge. They will often reply with "LGTM, see nit". That means that the PR will be merged once the feedback is resolved. "LGTM" == "looks good to me".
|
|
||||||
|
|
||||||
There are lots of thoughts and [approaches](https://github.com/antlr/antlr4-cpp/blob/master/CONTRIBUTING.md#emoji) for how to efficiently discuss changes. It is best to be clear and explicit with your feedback. Please be patient with people who might not understand the finer details about your approach to feedback.
|
|
||||||
|
|
||||||
#### Copying Changes from Other Projects
|
|
||||||
|
|
||||||
Ryujinx uses some implementations and frameworks from other projects. The following rules must be followed for PRs that include changes from another project:
|
|
||||||
|
|
||||||
- The license of the file is [permissive](https://en.wikipedia.org/wiki/Permissive_free_software_licence).
|
|
||||||
- The license of the file is left in-tact.
|
|
||||||
- The contribution is correctly attributed in the [3rd party notices](distribution/legal/THIRDPARTY.md) file in the repository, as needed.
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
+41
-44
@@ -3,54 +3,51 @@
|
|||||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageVersion Include="Avalonia" Version="11.3.13" />
|
<PackageVersion Include="Avalonia" Version="0.10.21" />
|
||||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.13" />
|
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="0.10.21" />
|
||||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.13" />
|
<PackageVersion Include="Avalonia.Desktop" Version="0.10.21" />
|
||||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.13" />
|
<PackageVersion Include="Avalonia.Diagnostics" Version="0.10.21" />
|
||||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.3.13" />
|
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="0.10.21" />
|
||||||
<PackageVersion Include="Svg.Controls.Avalonia" Version="11.3.9.5" />
|
<PackageVersion Include="Avalonia.Svg" Version="0.10.18" />
|
||||||
<PackageVersion Include="Svg.Controls.Skia.Avalonia" Version="11.3.9.5" />
|
<PackageVersion Include="Avalonia.Svg.Skia" Version="0.10.18" />
|
||||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageVersion Include="Concentus" Version="2.2.2" />
|
<PackageVersion Include="Concentus" Version="1.1.7" />
|
||||||
<PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" />
|
<PackageVersion Include="DiscordRichPresence" Version="1.1.3.18" />
|
||||||
<PackageVersion Include="DynamicData" Version="9.4.31" />
|
<PackageVersion Include="DynamicData" Version="7.14.2" />
|
||||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.4.1" />
|
<PackageVersion Include="FluentAvaloniaUI" Version="1.4.5" />
|
||||||
<PackageVersion Include="Gommon" Version="2.8.1.1" />
|
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
|
||||||
<PackageVersion Include="Humanizer" Version="3.0.10" />
|
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
|
||||||
|
<PackageVersion Include="jp2masa.Avalonia.Flexbox" Version="0.2.0" />
|
||||||
|
<PackageVersion Include="LibHac" Version="0.18.0" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
|
||||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.17.0" />
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.1" />
|
||||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
|
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
|
||||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
|
|
||||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||||
<PackageVersion Include="NetCoreServer" Version="8.0.7" />
|
<PackageVersion Include="NUnit" Version="3.13.3" />
|
||||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
|
<PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
|
||||||
<PackageVersion Include="NUnit" Version="4.5.1" />
|
<PackageVersion Include="OpenTK.Core" Version="4.7.7" />
|
||||||
<PackageVersion Include="NUnit3TestAdapter" Version="6.2.0" />
|
<PackageVersion Include="OpenTK.Graphics" Version="4.7.7" />
|
||||||
<PackageVersion Include="OpenTK.Core" Version="4.9.4" />
|
<PackageVersion Include="OpenTK.OpenAL" Version="4.7.7" />
|
||||||
<PackageVersion Include="OpenTK.Graphics" Version="4.9.4" />
|
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.7.7" />
|
||||||
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.9.4" />
|
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
||||||
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.9.4" />
|
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build13" />
|
||||||
<PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" />
|
|
||||||
<PackageVersion Include="Ryujinx.Audio.OpenAL" Version="1.25.2" />
|
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Linux" Version="6.1.3-build5" />
|
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.macOS" Version="5.0.3-build14" />
|
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.Windows" Version="6.1.3-build5" />
|
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||||
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.128" />
|
<PackageVersion Include="Ryujinx.GtkSharp" Version="3.24.24.59-ryujinx" />
|
||||||
<PackageVersion Include="Ryujinx.SDL3-CS" Version="2026.707.0" />
|
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.26.3-build25" />
|
||||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||||
<PackageVersion Include="Silk.NET.Shaderc" Version="2.23.0" />
|
<PackageVersion Include="Silk.NET.Vulkan" Version="2.16.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.23.0" />
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.16.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.23.0" />
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.16.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.23.0" />
|
<PackageVersion Include="SixLabors.ImageSharp" Version="1.0.4" />
|
||||||
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
|
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
|
||||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
|
<PackageVersion Include="SPB" Version="0.0.4-build28" />
|
||||||
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
<PackageVersion Include="System.Drawing.Common" Version="7.0.0" />
|
||||||
<PackageVersion Include="System.IO.Hashing" Version="9.0.12" />
|
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.30.1" />
|
||||||
<PackageVersion Include="System.Management" Version="9.0.12" />
|
<PackageVersion Include="System.IO.Hashing" Version="7.0.0" />
|
||||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.1.0" />
|
<PackageVersion Include="System.Management" Version="7.0.1" />
|
||||||
<PackageVersion Include="Rxmxnx.PInvoke.Extensions" Version="2.9.0" />
|
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
||||||
|
<PackageVersion Include="XamlNameReferenceGenerator" Version="1.6.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) Kenji-NX Team and Contributors
|
Copyright (c) Ryujinx Team and Contributors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
|||||||
@@ -1,126 +1,143 @@
|
|||||||
|
|
||||||
<h1 align="center">
|
<h1 align="center">
|
||||||
<br>
|
<br>
|
||||||
<img src="https://git.ryujinx.app/projects/Kenji-NX/raw/branch/master/distribution/misc/Logo.png" alt="Kenji-NX">
|
<a href="https://ryujinx.org/"><img src="https://i.imgur.com/WcCj6Rt.png" alt="Ryujinx" width="150"></a>
|
||||||
<br>
|
<br>
|
||||||
<b>Kenji-NX</b>
|
<b>Ryujinx</b>
|
||||||
<br>
|
<br>
|
||||||
|
<sub><sup><b>(REE-YOU-JINX)</b></sup></sub>
|
||||||
[](https://git.ryujinx.app/projects/Kenji-NX/releases/latest)
|
|
||||||
[](https://git.ryujinx.app/Kenji-NX/android/releases/latest)
|
|
||||||
<br>
|
<br>
|
||||||
[](https://discord.gg/zBSAuZfKqe)
|
|
||||||
|
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
Kenji-NX is an open-source Nintendo Switch emulator, originally created by gdkchan, written in C#.
|
<p align="center">
|
||||||
|
Ryujinx is an open-source Nintendo Switch emulator, created by gdkchan, written in C#.
|
||||||
This emulator aims at providing excellent accuracy and performance, a user-friendly interface and consistent builds.
|
This emulator aims at providing excellent accuracy and performance, a user-friendly interface and consistent builds.
|
||||||
It was written from scratch and development on the project began in September 2017.
|
It was written from scratch and development on the project began in September 2017. Ryujinx is available on Github under the <a href="https://github.com/Ryujinx/Ryujinx/blob/master/LICENSE.txt" target="_blank">MIT license</a>. <br />
|
||||||
Kenji-NX is available on GitHub under the [MIT license](LICENSE.txt).
|
|
||||||
|
|
||||||
On October 1st 2024, Ryujinx was discontinued as the creator was forced to abandon the project.
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://github.com/Ryujinx/Ryujinx/actions/workflows/release.yml">
|
||||||
|
<img src="https://github.com/Ryujinx/Ryujinx/actions/workflows/release.yml/badge.svg"
|
||||||
|
alt="">
|
||||||
|
</a>
|
||||||
|
<a href="https://crwd.in/ryujinx">
|
||||||
|
<img src="https://badges.crowdin.net/ryujinx/localized.svg"
|
||||||
|
alt="">
|
||||||
|
</a>
|
||||||
|
<a href="https://discord.com/invite/VkQYXAZ">
|
||||||
|
<img src="https://img.shields.io/discord/410208534861447168?color=5865F2&label=Ryujinx&logo=discord&logoColor=white"
|
||||||
|
alt="Discord">
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<img src="https://raw.githubusercontent.com/Ryujinx/Ryujinx-Website/master/public/assets/images/shell.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
This fork is not a Ryujinx revival project; it aims to be a middle ground between GreemDev's [Ryujinx](https://git.ryujinx.app/projects/Ryubing) fork and the more preservative [ryujinx-mirror](https://git.ryujinx.app/archive/ryujinx-mirror) fork.
|
<h5 align="center">
|
||||||
It brings over many of the front-facing features from the aforementioned forks with *additional* contributions from KeatonTheBot and others.
|
|
||||||
|
</h5>
|
||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
|
||||||
As of May 2024, Ryujinx has been tested on approximately 4,300 titles;
|
As of April 2023, Ryujinx has been tested on approximately 4,050 titles; over 4,000 boot past menus and into gameplay, with roughly 3,400 of those being considered playable.
|
||||||
over 4,100 boot past menus and into gameplay, with roughly 3,550 of those being considered playable.
|
You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues). Anyone is free to submit a new game test or update an existing game test entry; simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue. Use the search function to see if a game has been tested already!
|
||||||
|
|
||||||
Anyone is free to submit a new game test or update an existing game test entry;
|
|
||||||
simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue.
|
|
||||||
Use the search function to see if a game has been tested already!
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
To run this emulator, your PC must be equipped with at least 8GiB of RAM;
|
To run this emulator, your PC must be equipped with at least 8GiB of RAM; failing to meet this requirement may result in a poor gameplay experience or unexpected crashes.
|
||||||
failing to meet this requirement may result in a poor gameplay experience or unexpected crashes.
|
|
||||||
|
See our [Setup & Configuration Guide](https://github.com/Ryujinx/Ryujinx/wiki/Ryujinx-Setup-&-Configuration-Guide) on how to set up the emulator.
|
||||||
|
|
||||||
|
For our Local Wireless and LAN builds, see our [Multiplayer: Local Play/Local Wireless Guide
|
||||||
|
](https://github.com/Ryujinx/Ryujinx/wiki/Multiplayer-(LDN-Local-Wireless)-Guide).
|
||||||
|
|
||||||
|
Avalonia UI comes with translations for various languages. See [Crowdin](https://crwd.in/ryujinx) for more information.
|
||||||
|
|
||||||
## Latest build
|
## Latest build
|
||||||
|
|
||||||
<s>These builds are compiled automatically for each commit on the master branch.
|
These builds are compiled automatically for each commit on the master branch. While we strive to ensure optimal stability and performance prior to pushing an update, our automated builds **may be unstable or completely broken.**
|
||||||
While we strive to ensure optimal stability and performance prior to pushing an update, our automated builds **may be unstable or completely broken**.</s>
|
|
||||||
|
|
||||||
Automated builds are temporarily disabled, but builds for all platforms will be manually compiled and uploaded until the workflows are fixed.
|
If you want to see details on updates to the emulator, you can visit our [Changelog](https://github.com/Ryujinx/Ryujinx/wiki/Changelog).
|
||||||
|
|
||||||
## Documentation
|
The latest automatic build for Windows, macOS, and Linux can be found on the [Official Website](https://ryujinx.org/download).
|
||||||
|
|
||||||
If you are planning to contribute or just want to learn more about this project please read through our [documentation](docs/README.md).
|
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
If you wish to build the emulator yourself, follow these steps:
|
If you wish to build the emulator yourself, follow these steps:
|
||||||
|
|
||||||
### Step 1
|
### Step 1
|
||||||
|
Install the X64 version of [.NET 7.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/7.0).
|
||||||
Install the [.NET 10.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/10.0).
|
|
||||||
Make sure your SDK version is higher or equal to the required version specified in [global.json](global.json).
|
|
||||||
|
|
||||||
### Step 2
|
### Step 2
|
||||||
|
Either use `git clone https://github.com/Ryujinx/Ryujinx` on the command line to clone the repository or use Code --> Download zip button to get the files.
|
||||||
Either use `git clone https://git.ryujinx.app/projects/Kenji-NX` on the command line to clone the repository or use Code --> Download zip button to get the files.
|
|
||||||
|
|
||||||
### Step 3
|
### Step 3
|
||||||
|
|
||||||
To build Kenji-NX, open a command prompt inside the project directory.
|
To build Ryujinx, open a command prompt inside the project directory. You can quickly access it on Windows by holding shift in File Explorer, then right clicking and selecting `Open command window here`. Then type the following command:
|
||||||
You can quickly access it on Windows by holding shift in File Explorer, then right clicking and selecting `Open command window here`.
|
`dotnet build -c Release -o build`
|
||||||
Then type the following command: `dotnet build -c Release -o build`
|
|
||||||
the built files will be found in the newly created build directory.
|
the built files will be found in the newly created build directory.
|
||||||
|
|
||||||
System files are stored in the `Ryujinx` folder.
|
Ryujinx system files are stored in the `Ryujinx` folder. This folder is located in the user folder, which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
|
||||||
This folder is located in the user folder, which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Audio**
|
- **Audio**
|
||||||
|
|
||||||
Audio output is entirely supported, audio input (microphone) isn't supported.
|
Audio output is entirely supported, audio input (microphone) isn't supported. We use C# wrappers for [OpenAL](https://openal-soft.org/), and [SDL2](https://www.libsdl.org/) & [libsoundio](http://libsound.io/) as fallbacks.
|
||||||
We use C# wrappers for [OpenAL](https://openal-soft.org/), and [SDL2](https://www.libsdl.org/) & [libsoundio](http://libsound.io/) as fallbacks.
|
|
||||||
|
|
||||||
- **CPU**
|
- **CPU**
|
||||||
|
|
||||||
The CPU emulator, ARMeilleure, emulates an ARMv8 CPU and currently has support for most 64-bit ARMv8 and some of the ARMv7 (and older) instructions, including partial 32-bit support.
|
The CPU emulator, ARMeilleure, emulates an ARMv8 CPU and currently has support for most 64-bit ARMv8 and some of the ARMv7 (and older) instructions, including partial 32-bit support. It translates the ARM code to a custom IR, performs a few optimizations, and turns that into x86 code.
|
||||||
It translates the ARM code to a custom IR, performs a few optimizations, and turns that into x86 code.
|
There are three memory manager options available depending on the user's preference, leveraging both software-based (slower) and host-mapped modes (much faster). The fastest option (host, unchecked) is set by default.
|
||||||
There are three memory manager options available depending on the user's preference, leveraging both software-based (slower) and host-mapped modes (much faster).
|
Ryujinx also features an optional Profiled Persistent Translation Cache, which essentially caches translated functions so that they do not need to be translated every time the game loads. The net result is a significant reduction in load times (the amount of time between launching a game and arriving at the title screen) for nearly every game. NOTE: this feature is enabled by default in the Options menu > System tab. You must launch the game at least twice to the title screen or beyond before performance improvements are unlocked on the third launch! These improvements are permanent and do not require any extra launches going forward.
|
||||||
The fastest option (host, unchecked) is set by default.
|
|
||||||
Kenji-NX also features an optional Profiled Persistent Translation Cache, which essentially caches translated functions so that they do not need to be translated every time the game loads.
|
|
||||||
The net result is a significant reduction in load times (the amount of time between launching a game and arriving at the title screen) for nearly every game.
|
|
||||||
NOTE: This feature is enabled by default in the Options menu > System tab.
|
|
||||||
You must launch the game at least twice to the title screen or beyond before performance improvements are unlocked on the third launch!
|
|
||||||
These improvements are permanent and do not require any extra launches going forward.
|
|
||||||
|
|
||||||
- **GPU**
|
- **GPU**
|
||||||
|
|
||||||
The GPU emulator emulates the Switch's Maxwell GPU using either the OpenGL (version 4.5 minimum), Vulkan, or Metal (via MoltenVK) APIs through a custom build of OpenTK or Silk.NET respectively.
|
The GPU emulator emulates the Switch's Maxwell GPU using either the OpenGL (version 4.5 minimum), Vulkan, or Metal (via MoltenVK) APIs through a custom build of OpenTK or Silk.NET respectively. There are currently six graphics enhancements available to the end user in Ryujinx: Disk Shader Caching, Resolution Scaling, Anti-Aliasing, Scaling Filters (including FSR), Anisotropic Filtering and Aspect Ratio Adjustment. These enhancements can be adjusted or toggled as desired in the GUI.
|
||||||
There are currently six graphics enhancements available to the end user in Kenji-NX: Disk Shader Caching, Resolution Scaling, Anti-Aliasing, Scaling Filters (including FSR), Anisotropic Filtering and Aspect Ratio Adjustment.
|
|
||||||
These enhancements can be adjusted or toggled as desired in the GUI.
|
|
||||||
|
|
||||||
- **Input**
|
- **Input**
|
||||||
|
|
||||||
We currently have support for keyboard, mouse, touch input, JoyCon input support, and nearly all controllers.
|
We currently have support for keyboard, mouse, touch input, JoyCon input support, and nearly all controllers. Motion controls are natively supported in most cases; for dual-JoyCon motion support, DS4Windows or BetterJoy are currently required.
|
||||||
Motion controls are natively supported in most cases; for dual-JoyCon motion support, DS4Windows or BetterJoy are currently required.
|
|
||||||
In all scenarios, you can set up everything inside the input configuration menu.
|
In all scenarios, you can set up everything inside the input configuration menu.
|
||||||
|
|
||||||
- **DLC & Modifications**
|
- **DLC & Modifications**
|
||||||
|
|
||||||
Kenji-NX is able to manage add-on content/downloadable content through the GUI.
|
Ryujinx is able to manage add-on content/downloadable content through the GUI. Mods (romfs, exefs, and runtime mods such as cheats) are also supported; the GUI contains a shortcut to open the respective mods folder for a particular game.
|
||||||
Mods (romfs, exefs, and runtime mods such as cheats) are also supported;
|
|
||||||
the GUI contains a shortcut to open the respective mods folder for a particular game.
|
|
||||||
|
|
||||||
- **Configuration**
|
- **Configuration**
|
||||||
|
|
||||||
The emulator has settings for enabling or disabling some logging, remapping controllers, and more.
|
The emulator has settings for enabling or disabling some logging, remapping controllers, and more. You can configure all of them through the graphical interface or manually through the config file, `Config.json`, found in the user folder which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
|
||||||
You can configure all of them through the graphical interface or manually through the config file, `Config.json`, found in the user folder which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
|
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
|
||||||
|
If you have contributions, suggestions, need emulator support or just want to get in touch with the team, join our [Discord server](https://discord.com/invite/Ryujinx). You may also review our [FAQ](https://github.com/Ryujinx/Ryujinx/wiki/Frequently-Asked-Questions).
|
||||||
|
|
||||||
|
## Donations
|
||||||
|
|
||||||
|
If you'd like to support the project financially, Ryujinx has an active Patreon campaign.
|
||||||
|
|
||||||
|
<a href="https://www.patreon.com/ryujinx">
|
||||||
|
<img src="https://images.squarespace-cdn.com/content/v1/560c1d39e4b0b4fae0c9cf2a/1567548955044-WVD994WZP76EWF15T0L3/Patreon+Button.png?format=500w" width="150">
|
||||||
|
</a>
|
||||||
|
|
||||||
|
All developers working on the project do so in their free time, but the project has several expenses:
|
||||||
|
* Hackable Nintendo Switch consoles to reverse-engineer the hardware
|
||||||
|
* Additional computer hardware for testing purposes (e.g. GPUs to diagnose graphical bugs, etc.)
|
||||||
|
* Licenses for various software development tools (e.g. Jetbrains, IDA)
|
||||||
|
* Web hosting and infrastructure maintenance (e.g. LDN servers)
|
||||||
|
|
||||||
|
All funds received through Patreon are considered a donation to support the project. Patrons receive early access to progress reports and exclusive access to developer interviews.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This software is licensed under the terms of the [MIT license](LICENSE.txt).
|
This software is licensed under the terms of the <a href="https://github.com/Ryujinx/Ryujinx/blob/master/LICENSE.txt" target="_blank">MIT license.</a></i><br />
|
||||||
This project makes use of code authored by the libvpx project, licensed under BSD and the ffmpeg project, licensed under LGPLv3.
|
This project makes use of code authored by the libvpx project, licensed under BSD and the ffmpeg project, licensed under LGPLv3.
|
||||||
See [LICENSE.txt](LICENSE.txt) and [THIRDPARTY.md](distribution/legal/THIRDPARTY.md) for more details.
|
See [LICENSE.txt](LICENSE.txt) and [THIRDPARTY.md](distribution/legal/THIRDPARTY.md) for more details.
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
- [LibHac](https://git.ryujinx.app/projects/LibHac) is used for our file-system.
|
- [LibHac](https://github.com/Thealexbarney/LibHac) is used for our file-system.
|
||||||
- [AmiiboAPI](https://www.amiiboapi.com) is used in our Amiibo emulation.
|
- [AmiiboAPI](https://www.amiiboapi.com) is used in our Amiibo emulation.
|
||||||
- [ldn_mitm](https://github.com/spacemeowx2/ldn_mitm) is used for one of our available multiplayer modes.
|
|
||||||
- [ShellLink](https://github.com/securifybv/ShellLink) is used for Windows shortcut generation.
|
|
||||||
|
|||||||
+15
-17
@@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.1.32228.430
|
VisualStudioVersion = 17.1.32228.430
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests", "src\Ryujinx.Tests\Ryujinx.Tests.csproj", "{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{074045D4-3ED2-4711-9169-E385F2BFB5A0}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibKenjinx", "src\LibKenjinx\LibKenjinx.csproj", "{AF58C1D5-DE16-429B-B155-7CE83B4E8FA6}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests", "src\Ryujinx.Tests\Ryujinx.Tests.csproj", "{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests.Unicorn", "src\Ryujinx.Tests.Unicorn\Ryujinx.Tests.Unicorn.csproj", "{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests.Unicorn", "src\Ryujinx.Tests.Unicorn\Ryujinx.Tests.Unicorn.csproj", "{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}"
|
||||||
EndProject
|
EndProject
|
||||||
@@ -34,9 +34,7 @@ EndProject
|
|||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
.editorconfig = .editorconfig
|
.editorconfig = .editorconfig
|
||||||
Directory.Build.props = Directory.Build.props
|
|
||||||
Directory.Packages.props = Directory.Packages.props
|
Directory.Packages.props = Directory.Packages.props
|
||||||
nuget.config = nuget.config
|
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Memory", "src\Ryujinx.Memory\Ryujinx.Memory.csproj", "{A5E6C691-9E22-4263-8F40-42F002CE66BE}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Memory", "src\Ryujinx.Memory\Ryujinx.Memory.csproj", "{A5E6C691-9E22-4263-8F40-42F002CE66BE}"
|
||||||
@@ -67,11 +65,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.SDL2.Common", "src\
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "src\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "src\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Headless.SDL2", "src\Ryujinx.Headless.SDL2\Ryujinx.Headless.SDL2.csproj", "{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}"
|
||||||
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmpeg", "src\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj", "{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmpeg", "src\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj", "{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Ava", "src\Ryujinx.Ava\Ryujinx.Ava.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.UI.Common", "src\Ryujinx.UI.Common\Ryujinx.UI.Common.csproj", "{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Ui.Common", "src\Ryujinx.Ui.Common\Ryujinx.Ui.Common.csproj", "{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Generators", "src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj", "{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Generators", "src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj", "{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}"
|
||||||
EndProject
|
EndProject
|
||||||
@@ -79,7 +79,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vulkan", "
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spv.Generator", "src\Spv.Generator\Spv.Generator.csproj", "{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spv.Generator", "src\Spv.Generator\Spv.Generator.csproj", "{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.UI.LocaleGenerator", "src\Ryujinx.UI.LocaleGenerator\Ryujinx.UI.LocaleGenerator.csproj", "{77D01AD9-2C98-478E-AE1D-8F7100738FB4}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Ui.LocaleGenerator", "src\Ryujinx.Ui.LocaleGenerator\Ryujinx.Ui.LocaleGenerator.csproj", "{77D01AD9-2C98-478E-AE1D-8F7100738FB4}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Common", "src\Ryujinx.Horizon.Common\Ryujinx.Horizon.Common.csproj", "{77F96ECE-4952-42DB-A528-DED25572A573}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Common", "src\Ryujinx.Horizon.Common\Ryujinx.Horizon.Common.csproj", "{77F96ECE-4952-42DB-A528-DED25572A573}"
|
||||||
EndProject
|
EndProject
|
||||||
@@ -87,22 +87,20 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon", "src\Ryuj
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
|
|
||||||
EndProject
|
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.Build.0 = Release|Any CPU
|
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{AF58C1D5-DE16-429B-B155-7CE83B4E8FA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{AF58C1D5-DE16-429B-B155-7CE83B4E8FA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{AF58C1D5-DE16-429B-B155-7CE83B4E8FA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{AF58C1D5-DE16-429B-B155-7CE83B4E8FA6}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@@ -207,6 +205,10 @@ Global
|
|||||||
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.Build.0 = Release|Any CPU
|
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@@ -247,10 +249,6 @@ Global
|
|||||||
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.Build.0 = Release|Any CPU
|
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForOtherTypes/@EntryValue">UseExplicitType</s:String>
|
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForOtherTypes/@EntryValue">UseExplicitType</s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForSimpleTypes/@EntryValue">UseExplicitType</s:String>
|
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForSimpleTypes/@EntryValue">UseExplicitType</s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="I" Suffix="" Style="AaBb" /></Policy></s:String>
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="I" Suffix="" Style="AaBb" /></Policy></s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=a0b4bc4d_002Dd13b_002D4a37_002Db37e_002Dc9c6864e4302/@EntryIndexedValue"><Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Types and namespaces"><ElementKinds><Kind Name="NAMESPACE" /><Kind Name="CLASS" /><Kind Name="STRUCT" /><Kind Name="ENUM" /><Kind Name="DELEGATE" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="I" Suffix="" Style="AaBb" /></Policy></Policy></s:String>
|
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean>
|
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=ASET/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=ASET/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Astc/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Astc/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Luma/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Luma/@EntryIndexedValue">True</s:Boolean>
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
<Solution>
|
|
||||||
<Folder Name="/Solution Items/">
|
|
||||||
<File Path=".editorconfig" />
|
|
||||||
<File Path="Directory.Build.props" />
|
|
||||||
<File Path="Directory.Packages.props" />
|
|
||||||
<File Path="nuget.config" />
|
|
||||||
</Folder>
|
|
||||||
<Project Path="src/ARMeilleure/ARMeilleure.csproj" />
|
|
||||||
<Project Path="src/LibKenjinx/LibKenjinx.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Audio.Backends.OpenAL/Ryujinx.Audio.Backends.OpenAL.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Audio.Backends.SDL3/Ryujinx.Audio.Backends.SDL3.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Audio.Backends.SoundIo/Ryujinx.Audio.Backends.SoundIo.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Audio/Ryujinx.Audio.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Common/Ryujinx.Common.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Cpu/Ryujinx.Cpu.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Graphics.Device/Ryujinx.Graphics.Device.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Graphics.GAL/Ryujinx.Graphics.GAL.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Graphics.Gpu/Ryujinx.Graphics.Gpu.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Graphics.Host1x/Ryujinx.Graphics.Host1x.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Graphics.Nvdec.FFmpeg/Ryujinx.Graphics.Nvdec.FFmpeg.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Graphics.Nvdec.Vp9/Ryujinx.Graphics.Nvdec.Vp9.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Graphics.Nvdec/Ryujinx.Graphics.Nvdec.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Graphics.OpenGL/Ryujinx.Graphics.OpenGL.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Graphics.Shader/Ryujinx.Graphics.Shader.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Graphics.Texture/Ryujinx.Graphics.Texture.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Graphics.Vic/Ryujinx.Graphics.Vic.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Graphics.Video/Ryujinx.Graphics.Video.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Graphics.Vulkan/Ryujinx.Graphics.Vulkan.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.HLE.Generators/Ryujinx.HLE.Generators.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.HLE/Ryujinx.HLE.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Horizon.Common/Ryujinx.Horizon.Common.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Horizon.Generators/Ryujinx.Horizon.Generators.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Horizon.Kernel.Generators/Ryujinx.Horizon.Kernel.Generators.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Horizon/Ryujinx.Horizon.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Input.SDL3/Ryujinx.Input.SDL3.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Input/Ryujinx.Input.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Memory/Ryujinx.Memory.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.SDL3.Common/Ryujinx.SDL3.Common.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.ShaderTools/Ryujinx.ShaderTools.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Tests.Memory/Ryujinx.Tests.Memory.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Tests.Unicorn/Ryujinx.Tests.Unicorn.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.Tests/Ryujinx.Tests.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj" />
|
|
||||||
<Project Path="src/Ryujinx.UI.LocaleGenerator/Ryujinx.UI.LocaleGenerator.csproj" />
|
|
||||||
<Project Path="src/Ryujinx/Ryujinx.csproj" />
|
|
||||||
<Project Path="src/Spv.Generator/Spv.Generator.csproj" />
|
|
||||||
</Solution>
|
|
||||||
@@ -682,32 +682,3 @@
|
|||||||
END OF TERMS AND CONDITIONS
|
END OF TERMS AND CONDITIONS
|
||||||
```
|
```
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
# ShellLink (MIT)
|
|
||||||
<details>
|
|
||||||
<summary>See License</summary>
|
|
||||||
|
|
||||||
```
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2017 Yorick Koster, Securify B.V.
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ Version=1.0
|
|||||||
Name=Ryujinx
|
Name=Ryujinx
|
||||||
Type=Application
|
Type=Application
|
||||||
Icon=Ryujinx
|
Icon=Ryujinx
|
||||||
Exec=Ryujinx.sh %f
|
Exec=env DOTNET_EnableAlternateStackCheck=1 Ryujinx %f
|
||||||
Comment=A Nintendo Switch Emulator
|
Comment=A Nintendo Switch Emulator
|
||||||
GenericName=Nintendo Switch Emulator
|
GenericName=Nintendo Switch Emulator
|
||||||
Terminal=false
|
Terminal=false
|
||||||
|
|||||||
Executable → Regular
+6
-9
@@ -1,23 +1,20 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
SCRIPT_DIR=$(dirname "$(realpath "$0")")
|
SCRIPT_DIR=$(dirname "$(realpath "$0")")
|
||||||
|
RYUJINX_BIN="Ryujinx"
|
||||||
|
|
||||||
|
if [ -f "$SCRIPT_DIR/Ryujinx.Ava" ]; then
|
||||||
|
RYUJINX_BIN="Ryujinx.Ava"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -f "$SCRIPT_DIR/Ryujinx.Headless.SDL2" ]; then
|
if [ -f "$SCRIPT_DIR/Ryujinx.Headless.SDL2" ]; then
|
||||||
RYUJINX_BIN="Ryujinx.Headless.SDL2"
|
RYUJINX_BIN="Ryujinx.Headless.SDL2"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -f "$SCRIPT_DIR/Ryujinx" ]; then
|
|
||||||
RYUJINX_BIN="Ryujinx"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$RYUJINX_BIN" ]; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
COMMAND="env DOTNET_EnableAlternateStackCheck=1"
|
COMMAND="env DOTNET_EnableAlternateStackCheck=1"
|
||||||
|
|
||||||
if command -v gamemoderun > /dev/null 2>&1; then
|
if command -v gamemoderun > /dev/null 2>&1; then
|
||||||
COMMAND="$COMMAND gamemoderun"
|
COMMAND="$COMMAND gamemoderun"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec $COMMAND "$SCRIPT_DIR/$RYUJINX_BIN" "$@"
|
$COMMAND "$SCRIPT_DIR/$RYUJINX_BIN" "$@"
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
[Desktop Entry]
|
|
||||||
Version=1.0
|
|
||||||
Name={0}
|
|
||||||
Type=Application
|
|
||||||
Icon={1}
|
|
||||||
Exec={2} %f
|
|
||||||
Comment=Nintendo Switch application
|
|
||||||
GenericName=Nintendo Switch Emulator
|
|
||||||
Terminal=false
|
|
||||||
Categories=Game;Emulator;
|
|
||||||
Keywords=Switch;Nintendo;Emulator;
|
|
||||||
StartupWMClass=Ryujinx
|
|
||||||
PrefersNonDefaultGPU=true
|
|
||||||
@@ -10,9 +10,6 @@
|
|||||||
<string>Ryujinx</string>
|
<string>Ryujinx</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>Ryujinx.icns</string>
|
<string>Ryujinx.icns</string>
|
||||||
<key>CFBundleDocumentTypes</key>
|
|
||||||
<array>
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleTypeExtensions</key>
|
<key>CFBundleTypeExtensions</key>
|
||||||
<array>
|
<array>
|
||||||
<string>nca</string>
|
<string>nca</string>
|
||||||
@@ -21,14 +18,6 @@
|
|||||||
<string>nsp</string>
|
<string>nsp</string>
|
||||||
<string>xci</string>
|
<string>xci</string>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleTypeName</key>
|
|
||||||
<string>Nintendo Switch File</string>
|
|
||||||
<key>CFBundleTypeRole</key>
|
|
||||||
<string>Viewer</string>
|
|
||||||
<key>LSHandlerRank</key>
|
|
||||||
<string>Default</string>
|
|
||||||
</dict>
|
|
||||||
</array>
|
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>org.ryujinx.Ryujinx</string>
|
<string>org.ryujinx.Ryujinx</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
@@ -50,120 +39,10 @@
|
|||||||
<key>CSResourcesFileMapped</key>
|
<key>CSResourcesFileMapped</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>Copyright © 2018 - 2023 Ryujinx Team and Contributors.</string>
|
<string>Copyright © 2018 - 2022 Ryujinx Team and Contributors.</string>
|
||||||
<key>LSApplicationCategoryType</key>
|
<key>LSApplicationCategoryType</key>
|
||||||
<string>public.app-category.games</string>
|
<string>public.app-category.games</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>12.0</string>
|
<string>11.0</string>
|
||||||
<key>UTExportedTypeDeclarations</key>
|
|
||||||
<array>
|
|
||||||
<dict>
|
|
||||||
<key>UTTypeDescription</key>
|
|
||||||
<string>Extensible Application Markup Language</string>
|
|
||||||
<key>UTTypeConformsTo</key>
|
|
||||||
<array>
|
|
||||||
<string>public.xml</string>
|
|
||||||
</array>
|
|
||||||
<key>UTTypeIdentifier</key>
|
|
||||||
<string>com.ryujinx.xaml</string>
|
|
||||||
<key>UTTypeTagSpecification</key>
|
|
||||||
<dict>
|
|
||||||
<key>public.filename-extension</key>
|
|
||||||
<array>
|
|
||||||
<string>xaml</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>UTTypeDescription</key>
|
|
||||||
<string>Nintendo Submission Package</string>
|
|
||||||
<key>UTTypeConformsTo</key>
|
|
||||||
<array>
|
|
||||||
<string>public.data</string>
|
|
||||||
</array>
|
|
||||||
<key>UTTypeIdentifier</key>
|
|
||||||
<string>com.ryujinx.nsp</string>
|
|
||||||
<key>UTTypeTagSpecification</key>
|
|
||||||
<dict>
|
|
||||||
<key>public.filename-extension</key>
|
|
||||||
<array>
|
|
||||||
<string>nsp</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>UTTypeDescription</key>
|
|
||||||
<string>Nintendo Switch Cartridge</string>
|
|
||||||
<key>UTTypeConformsTo</key>
|
|
||||||
<array>
|
|
||||||
<string>public.data</string>
|
|
||||||
</array>
|
|
||||||
<key>UTTypeIdentifier</key>
|
|
||||||
<string>com.ryujinx.xci</string>
|
|
||||||
<key>UTTypeTagSpecification</key>
|
|
||||||
<dict>
|
|
||||||
<key>public.filename-extension</key>
|
|
||||||
<array>
|
|
||||||
<string>xci</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>UTTypeDescription</key>
|
|
||||||
<string>Nintendo Content Archive</string>
|
|
||||||
<key>UTTypeConformsTo</key>
|
|
||||||
<array>
|
|
||||||
<string>public.data</string>
|
|
||||||
</array>
|
|
||||||
<key>UTTypeIdentifier</key>
|
|
||||||
<string>com.ryujinx.nca</string>
|
|
||||||
<key>UTTypeTagSpecification</key>
|
|
||||||
<dict>
|
|
||||||
<key>public.filename-extension</key>
|
|
||||||
<array>
|
|
||||||
<string>nca</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>UTTypeDescription</key>
|
|
||||||
<string>Nintendo Relocatable Object</string>
|
|
||||||
<key>UTTypeConformsTo</key>
|
|
||||||
<array>
|
|
||||||
<string>public.data</string>
|
|
||||||
</array>
|
|
||||||
<key>UTTypeIdentifier</key>
|
|
||||||
<string>com.ryujinx.nro</string>
|
|
||||||
<key>UTTypeTagSpecification</key>
|
|
||||||
<dict>
|
|
||||||
<key>public.filename-extension</key>
|
|
||||||
<array>
|
|
||||||
<string>nro</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<dict>
|
|
||||||
<key>UTTypeDescription</key>
|
|
||||||
<string>Nintendo Shared Object</string>
|
|
||||||
<key>UTTypeConformsTo</key>
|
|
||||||
<array>
|
|
||||||
<string>public.data</string>
|
|
||||||
</array>
|
|
||||||
<key>UTTypeIdentifier</key>
|
|
||||||
<string>com.ryujinx.nso</string>
|
|
||||||
<key>UTTypeTagSpecification</key>
|
|
||||||
<dict>
|
|
||||||
<key>public.filename-extension</key>
|
|
||||||
<array>
|
|
||||||
<string>nso</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</array>
|
|
||||||
<key>LSEnvironment</key>
|
|
||||||
<dict>
|
|
||||||
<key>DOTNET_DefaultStackSize</key>
|
|
||||||
<string>200000</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ mkdir "$APP_BUNDLE_DIRECTORY/Contents/Frameworks"
|
|||||||
mkdir "$APP_BUNDLE_DIRECTORY/Contents/MacOS"
|
mkdir "$APP_BUNDLE_DIRECTORY/Contents/MacOS"
|
||||||
mkdir "$APP_BUNDLE_DIRECTORY/Contents/Resources"
|
mkdir "$APP_BUNDLE_DIRECTORY/Contents/Resources"
|
||||||
|
|
||||||
# Copy executable and nsure executable can be executed
|
# Copy executables first
|
||||||
cp "$PUBLISH_DIRECTORY/Ryujinx" "$APP_BUNDLE_DIRECTORY/Contents/MacOS/Ryujinx"
|
cp "$PUBLISH_DIRECTORY/Ryujinx.Ava" "$APP_BUNDLE_DIRECTORY/Contents/MacOS/Ryujinx"
|
||||||
chmod u+x "$APP_BUNDLE_DIRECTORY/Contents/MacOS/Ryujinx"
|
chmod u+x "$APP_BUNDLE_DIRECTORY/Contents/MacOS/Ryujinx"
|
||||||
|
|
||||||
# Then all libraries
|
# Then all libraries
|
||||||
|
|||||||
+10
-17
@@ -22,9 +22,9 @@ EXTRA_ARGS=$8
|
|||||||
|
|
||||||
if [ "$VERSION" == "1.1.0" ];
|
if [ "$VERSION" == "1.1.0" ];
|
||||||
then
|
then
|
||||||
RELEASE_TAR_FILE_NAME=ryujinx-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.app.tar
|
RELEASE_TAR_FILE_NAME=test-ava-ryujinx-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.app.tar
|
||||||
else
|
else
|
||||||
RELEASE_TAR_FILE_NAME=ryujinx-$VERSION-macos_universal.app.tar
|
RELEASE_TAR_FILE_NAME=test-ava-ryujinx-$VERSION-macos_universal.app.tar
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ARM64_APP_BUNDLE="$TEMP_DIRECTORY/output_arm64/Ryujinx.app"
|
ARM64_APP_BUNDLE="$TEMP_DIRECTORY/output_arm64/Ryujinx.app"
|
||||||
@@ -35,12 +35,12 @@ EXECUTABLE_SUB_PATH=Contents/MacOS/Ryujinx
|
|||||||
rm -rf "$TEMP_DIRECTORY"
|
rm -rf "$TEMP_DIRECTORY"
|
||||||
mkdir -p "$TEMP_DIRECTORY"
|
mkdir -p "$TEMP_DIRECTORY"
|
||||||
|
|
||||||
DOTNET_COMMON_ARGS=(-p:DebugType=embedded -p:Version="$VERSION" -p:SourceRevisionId="$SOURCE_REVISION_ID" --self-contained true $EXTRA_ARGS)
|
DOTNET_COMMON_ARGS="-p:DebugType=embedded -p:Version=$VERSION -p:SourceRevisionId=$SOURCE_REVISION_ID --self-contained true $EXTRA_ARGS"
|
||||||
|
|
||||||
dotnet restore
|
dotnet restore
|
||||||
dotnet build -c "$CONFIGURATION" src/Ryujinx
|
dotnet build -c $CONFIGURATION src/Ryujinx.Ava
|
||||||
dotnet publish -c "$CONFIGURATION" -r osx-arm64 -o "$TEMP_DIRECTORY/publish_arm64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx
|
dotnet publish -c $CONFIGURATION -r osx-arm64 -o "$TEMP_DIRECTORY/publish_arm64" $DOTNET_COMMON_ARGS src/Ryujinx.Ava
|
||||||
dotnet publish -c "$CONFIGURATION" -r osx-x64 -o "$TEMP_DIRECTORY/publish_x64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx
|
dotnet publish -c $CONFIGURATION -r osx-x64 -o "$TEMP_DIRECTORY/publish_x64" $DOTNET_COMMON_ARGS src/Ryujinx.Ava
|
||||||
|
|
||||||
# Get rid of the support library for ARMeilleure for x64 (that's only for arm64)
|
# Get rid of the support library for ARMeilleure for x64 (that's only for arm64)
|
||||||
rm -rf "$TEMP_DIRECTORY/publish_x64/libarmeilleure-jitsupport.dylib"
|
rm -rf "$TEMP_DIRECTORY/publish_x64/libarmeilleure-jitsupport.dylib"
|
||||||
@@ -104,17 +104,10 @@ fi
|
|||||||
|
|
||||||
echo "Creating archive"
|
echo "Creating archive"
|
||||||
pushd "$OUTPUT_DIRECTORY"
|
pushd "$OUTPUT_DIRECTORY"
|
||||||
tar --exclude "Ryujinx.app/Contents/MacOS/Ryujinx" -cvf "$RELEASE_TAR_FILE_NAME" Ryujinx.app 1> /dev/null
|
tar --exclude "Ryujinx.app/Contents/MacOS/Ryujinx" -cvf $RELEASE_TAR_FILE_NAME Ryujinx.app 1> /dev/null
|
||||||
python3 "$BASE_DIR/distribution/misc/add_tar_exec.py" "$RELEASE_TAR_FILE_NAME" "Ryujinx.app/Contents/MacOS/Ryujinx" "Ryujinx.app/Contents/MacOS/Ryujinx"
|
python3 "$BASE_DIR/distribution/misc/add_tar_exec.py" $RELEASE_TAR_FILE_NAME "Ryujinx.app/Contents/MacOS/Ryujinx" "Ryujinx.app/Contents/MacOS/Ryujinx"
|
||||||
gzip -9 < "$RELEASE_TAR_FILE_NAME" > "$RELEASE_TAR_FILE_NAME.gz"
|
gzip -9 < $RELEASE_TAR_FILE_NAME > $RELEASE_TAR_FILE_NAME.gz
|
||||||
rm "$RELEASE_TAR_FILE_NAME"
|
rm $RELEASE_TAR_FILE_NAME
|
||||||
|
|
||||||
# Create legacy update package for Avalonia to not left behind old testers.
|
|
||||||
if [ "$VERSION" != "1.1.0" ];
|
|
||||||
then
|
|
||||||
cp $RELEASE_TAR_FILE_NAME.gz test-ava-ryujinx-$VERSION-macos_universal.app.tar.gz
|
|
||||||
fi
|
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
echo "Done"
|
echo "Done"
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [ "$#" -lt 7 ]; then
|
|
||||||
echo "usage <BASE_DIR> <TEMP_DIRECTORY> <OUTPUT_DIRECTORY> <ENTITLEMENTS_FILE_PATH> <VERSION> <SOURCE_REVISION_ID> <CONFIGURATION> <EXTRA_ARGS>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p "$1"
|
|
||||||
mkdir -p "$2"
|
|
||||||
mkdir -p "$3"
|
|
||||||
|
|
||||||
BASE_DIR=$(readlink -f "$1")
|
|
||||||
TEMP_DIRECTORY=$(readlink -f "$2")
|
|
||||||
OUTPUT_DIRECTORY=$(readlink -f "$3")
|
|
||||||
ENTITLEMENTS_FILE_PATH=$(readlink -f "$4")
|
|
||||||
VERSION=$5
|
|
||||||
SOURCE_REVISION_ID=$6
|
|
||||||
CONFIGURATION=$7
|
|
||||||
EXTRA_ARGS=$8
|
|
||||||
|
|
||||||
if [ "$VERSION" == "1.1.0" ];
|
|
||||||
then
|
|
||||||
RELEASE_TAR_FILE_NAME=sdl2-ryujinx-headless-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.tar
|
|
||||||
else
|
|
||||||
RELEASE_TAR_FILE_NAME=sdl2-ryujinx-headless-$VERSION-macos_universal.tar
|
|
||||||
fi
|
|
||||||
|
|
||||||
ARM64_OUTPUT="$TEMP_DIRECTORY/publish_arm64"
|
|
||||||
X64_OUTPUT="$TEMP_DIRECTORY/publish_x64"
|
|
||||||
UNIVERSAL_OUTPUT="$OUTPUT_DIRECTORY/publish"
|
|
||||||
EXECUTABLE_SUB_PATH=Ryujinx.Headless.SDL2
|
|
||||||
|
|
||||||
rm -rf "$TEMP_DIRECTORY"
|
|
||||||
mkdir -p "$TEMP_DIRECTORY"
|
|
||||||
|
|
||||||
DOTNET_COMMON_ARGS=(-p:DebugType=embedded -p:Version="$VERSION" -p:SourceRevisionId="$SOURCE_REVISION_ID" --self-contained true $EXTRA_ARGS)
|
|
||||||
|
|
||||||
dotnet restore
|
|
||||||
dotnet build -c "$CONFIGURATION" src/Ryujinx.Headless.SDL2
|
|
||||||
dotnet publish -c "$CONFIGURATION" -r osx-arm64 -o "$TEMP_DIRECTORY/publish_arm64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx.Headless.SDL2
|
|
||||||
dotnet publish -c "$CONFIGURATION" -r osx-x64 -o "$TEMP_DIRECTORY/publish_x64" "${DOTNET_COMMON_ARGS[@]}" src/Ryujinx.Headless.SDL2
|
|
||||||
|
|
||||||
# Get rid of the support library for ARMeilleure for x64 (that's only for arm64)
|
|
||||||
rm -rf "$TEMP_DIRECTORY/publish_x64/libarmeilleure-jitsupport.dylib"
|
|
||||||
|
|
||||||
# Get rid of libsoundio from arm64 builds as we don't have a arm64 variant
|
|
||||||
# TODO: remove this once done
|
|
||||||
rm -rf "$TEMP_DIRECTORY/publish_arm64/libsoundio.dylib"
|
|
||||||
|
|
||||||
rm -rf "$OUTPUT_DIRECTORY"
|
|
||||||
mkdir -p "$OUTPUT_DIRECTORY"
|
|
||||||
|
|
||||||
# Let's copy one of the two different outputs and remove the executable
|
|
||||||
cp -R "$ARM64_OUTPUT/" "$UNIVERSAL_OUTPUT"
|
|
||||||
rm "$UNIVERSAL_OUTPUT/$EXECUTABLE_SUB_PATH"
|
|
||||||
|
|
||||||
# Make it libraries universal
|
|
||||||
python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_OUTPUT" "$X64_OUTPUT" "$UNIVERSAL_OUTPUT" "**/*.dylib"
|
|
||||||
|
|
||||||
if ! [ -x "$(command -v lipo)" ];
|
|
||||||
then
|
|
||||||
if ! [ -x "$(command -v llvm-lipo-14)" ];
|
|
||||||
then
|
|
||||||
LIPO=llvm-lipo
|
|
||||||
else
|
|
||||||
LIPO=llvm-lipo-14
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
LIPO=lipo
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Make the executable universal
|
|
||||||
$LIPO "$ARM64_OUTPUT/$EXECUTABLE_SUB_PATH" "$X64_OUTPUT/$EXECUTABLE_SUB_PATH" -output "$UNIVERSAL_OUTPUT/$EXECUTABLE_SUB_PATH" -create
|
|
||||||
|
|
||||||
# Now sign it
|
|
||||||
if ! [ -x "$(command -v codesign)" ];
|
|
||||||
then
|
|
||||||
if ! [ -x "$(command -v rcodesign)" ];
|
|
||||||
then
|
|
||||||
echo "Cannot find rcodesign on your system, please install rcodesign."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# NOTE: Currently require https://github.com/indygreg/apple-platform-rs/pull/44 to work on other OSes.
|
|
||||||
# cargo install --git "https://github.com/marysaka/apple-platform-rs" --branch "fix/adhoc-app-bundle" apple-codesign --bin "rcodesign"
|
|
||||||
echo "Using rcodesign for ad-hoc signing"
|
|
||||||
for FILE in "$UNIVERSAL_OUTPUT"/*; do
|
|
||||||
if [[ $(file "$FILE") == *"Mach-O"* ]]; then
|
|
||||||
rcodesign sign --entitlements-xml-path "$ENTITLEMENTS_FILE_PATH" "$FILE"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo "Using codesign for ad-hoc signing"
|
|
||||||
for FILE in "$UNIVERSAL_OUTPUT"/*; do
|
|
||||||
if [[ $(file "$FILE") == *"Mach-O"* ]]; then
|
|
||||||
codesign --entitlements "$ENTITLEMENTS_FILE_PATH" -f --deep -s - "$FILE"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Creating archive"
|
|
||||||
pushd "$OUTPUT_DIRECTORY"
|
|
||||||
tar --exclude "publish/Ryujinx.Headless.SDL2" -cvf "$RELEASE_TAR_FILE_NAME" publish 1> /dev/null
|
|
||||||
python3 "$BASE_DIR/distribution/misc/add_tar_exec.py" "$RELEASE_TAR_FILE_NAME" "publish/Ryujinx.Headless.SDL2" "publish/Ryujinx.Headless.SDL2"
|
|
||||||
gzip -9 < "$RELEASE_TAR_FILE_NAME" > "$RELEASE_TAR_FILE_NAME.gz"
|
|
||||||
rm "$RELEASE_TAR_FILE_NAME"
|
|
||||||
popd
|
|
||||||
|
|
||||||
echo "Done"
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
launch_arch="$(uname -m)"
|
|
||||||
if [ "$(sysctl -in sysctl.proc_translated)" = "1" ]
|
|
||||||
then
|
|
||||||
launch_arch="arm64"
|
|
||||||
fi
|
|
||||||
|
|
||||||
arch -$launch_arch {0} {1}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
|
||||||
<string>English</string>
|
|
||||||
<key>CFBundleExecutable</key>
|
|
||||||
<string>{0}</string>
|
|
||||||
<key>CFBundleGetInfoString</key>
|
|
||||||
<string>{1}</string>
|
|
||||||
<key>CFBundleIconFile</key>
|
|
||||||
<string>{2}</string>
|
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
|
||||||
<string>6.0</string>
|
|
||||||
<key>CFBundleVersion</key>
|
|
||||||
<string>1.0</string>
|
|
||||||
<key>NSHighResolutionCapable</key>
|
|
||||||
<true/>
|
|
||||||
<key>CSResourcesFileMapped</key>
|
|
||||||
<true/>
|
|
||||||
<key>NSHumanReadableCopyright</key>
|
|
||||||
<string>Copyright © 2018 - 2023 Ryujinx Team and Contributors.</string>
|
|
||||||
<key>LSApplicationCategoryType</key>
|
|
||||||
<string>public.app-category.games</string>
|
|
||||||
<key>LSMinimumSystemVersion</key>
|
|
||||||
<string>11.0</string>
|
|
||||||
<key>UIPrerenderedIcon</key>
|
|
||||||
<true/>
|
|
||||||
<key>LSEnvironment</key>
|
|
||||||
<dict>
|
|
||||||
<key>DOTNET_DefaultStackSize</key>
|
|
||||||
<string>200000</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -5,7 +5,7 @@ set -e
|
|||||||
INSTALL_DIRECTORY=$1
|
INSTALL_DIRECTORY=$1
|
||||||
NEW_APP_DIRECTORY=$2
|
NEW_APP_DIRECTORY=$2
|
||||||
APP_PID=$3
|
APP_PID=$3
|
||||||
APP_ARGUMENTS=("${@:4}")
|
APP_ARGUMENTS="${@:4}"
|
||||||
|
|
||||||
error_handler() {
|
error_handler() {
|
||||||
local lineno="$1"
|
local lineno="$1"
|
||||||
@@ -33,7 +33,7 @@ trap 'error_handler ${LINENO}' ERR
|
|||||||
|
|
||||||
attempt=0
|
attempt=0
|
||||||
while true; do
|
while true; do
|
||||||
if lsof -p "$APP_PID" +r 1 &>/dev/null || ps -p "$APP_PID" &>/dev/null; then
|
if lsof -p $APP_PID +r 1 &>/dev/null || ps -p "$APP_PID" &>/dev/null; then
|
||||||
if [ "$attempt" -eq 4 ]; then
|
if [ "$attempt" -eq 4 ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -53,5 +53,5 @@ mv "$NEW_APP_DIRECTORY" "$INSTALL_DIRECTORY"
|
|||||||
if [ "$#" -le 3 ]; then
|
if [ "$#" -le 3 ]; then
|
||||||
open -a "$INSTALL_DIRECTORY"
|
open -a "$INSTALL_DIRECTORY"
|
||||||
else
|
else
|
||||||
open -a "$INSTALL_DIRECTORY" --args "${APP_ARGUMENTS[@]}"
|
open -a "$INSTALL_DIRECTORY" --args "$APP_ARGUMENTS"
|
||||||
fi
|
fi
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 255.76 255.76"><defs><style>.cls-1{fill:#02c5e5;}.cls-2{fill:#ff5f55;}.cls-3{fill:none;}</style></defs><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><g id="Ebene_2-2" data-name="Ebene 2"><g id="Ebene_1-2-2" data-name="Ebene 1-2"><path class="cls-1" d="M80.63,0V220.39H44.37c-14,0-35.74-20.74-35.74-39.13V40.13C8.63,19.19,31.36,0,49.06,0Z"/><path class="cls-2" d="M175.13,35.37V255.76h36.26c14,0,35.74-20.74,35.74-39.13V75.5c0-20.94-22.73-40.13-40.43-40.13Z"/><polygon class="cls-1" points="124.34 137.96 122.58 145.57 90.64 145.57 92.89 137.96 124.34 137.96"/><polygon class="cls-2" points="160.29 137.96 157.84 145.57 122.58 145.57 124.34 137.96 160.29 137.96"/><polygon class="cls-1" points="130.39 111.86 128.62 119.47 95.14 119.47 97.39 111.86 130.39 111.86"/><polygon class="cls-2" points="164.79 111.86 162.34 119.47 128.62 119.47 130.39 111.86 164.79 111.86"/><polygon class="cls-1" points="104.24 167.99 122.83 87.77 129.78 87.77 111.19 167.99 104.24 167.99"/><polygon class="cls-2" points="128.18 167.99 146.77 87.77 153.89 87.77 135.3 167.99 128.18 167.99"/></g><rect class="cls-3" width="255.76" height="255.76"/></g></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -1,35 +0,0 @@
|
|||||||
# Documents Index
|
|
||||||
|
|
||||||
This repo includes several documents that explain both high-level and low-level concepts about Kenji-NX and its functions. These are very useful for contributors, to get context that can be very difficult to acquire from just reading code.
|
|
||||||
|
|
||||||
Intro to Kenji-NX
|
|
||||||
==================
|
|
||||||
|
|
||||||
Kenji-NX is an open-source Nintendo Switch emulator written in C#. It is based on Ryujinx, which was originally created by gdkchan.
|
|
||||||
* The CPU emulator, ARMeilleure, emulates an ARMv8 CPU and currently has support for most 64-bit ARMv8 and some of the ARMv7 (and older) instructions.
|
|
||||||
* The GPU emulator emulates the Switch's Maxwell GPU using either the OpenGL (version 4.5 minimum), Vulkan, or Metal (via MoltenVK) APIs through a custom build of OpenTK or Silk.NET respectively.
|
|
||||||
* Audio output is entirely supported via C# wrappers for SDL3, with OpenAL & libsoundio as fallbacks.
|
|
||||||
|
|
||||||
Getting Started
|
|
||||||
===============
|
|
||||||
|
|
||||||
- [Installing the .NET SDK](https://dotnet.microsoft.com/download)
|
|
||||||
- [Official .NET Docs](https://docs.microsoft.com/dotnet/core/)
|
|
||||||
|
|
||||||
Contributing (Building, testing, benchmarking, profiling, etc.)
|
|
||||||
===============
|
|
||||||
|
|
||||||
If you want to contribute a code change to this repo, start here.
|
|
||||||
|
|
||||||
- [Contributor Guide](../CONTRIBUTING.md)
|
|
||||||
|
|
||||||
Coding Guidelines
|
|
||||||
=================
|
|
||||||
|
|
||||||
- [C# coding style](coding-guidelines/coding-style.md)
|
|
||||||
- [Service Implementation Guidelines - WIP](https://gist.github.com/gdkchan/84ba88cd50efbe58d1babfaa7cd7c455)
|
|
||||||
|
|
||||||
Project Docs
|
|
||||||
=================
|
|
||||||
|
|
||||||
To be added. Many project files will contain basic XML docs for key functions and classes in the meantime.
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
# C# Coding Style
|
|
||||||
|
|
||||||
The general rule we follow is "use Visual Studio defaults".
|
|
||||||
Using an IDE that supports the `.editorconfig` standard will make this much simpler.
|
|
||||||
|
|
||||||
1. We use [Allman style](http://en.wikipedia.org/wiki/Indent_style#Allman_style) braces, where each brace begins on a new line. A single line statement block can go without braces but the block must be properly indented on its own line and must not be nested in other statement blocks that use braces (See rule 18 for more details). One exception is that a `using` statement is permitted to be nested within another `using` statement by starting on the following line at the same indentation level, even if the nested `using` contains a controlled block.
|
|
||||||
2. We use four spaces of indentation (no tabs).
|
|
||||||
3. We use `_camelCase` for internal and private fields and use `readonly` where possible. Prefix internal and private instance fields with `_`, static fields with `s_` and thread static fields with `t_`. When used on static fields, `readonly` should come after `static` (e.g. `static readonly` not `readonly static`). Public fields should be used sparingly and should use PascalCasing with no prefix when used.
|
|
||||||
4. We avoid `this.` unless absolutely necessary.
|
|
||||||
5. We always specify the visibility, even if it's the default (e.g.
|
|
||||||
`private string _foo` not `string _foo`). Visibility should be the first modifier (e.g.
|
|
||||||
`public abstract` not `abstract public`).
|
|
||||||
6. Namespace imports should be specified at the top of the file, *outside* of `namespace` declarations.
|
|
||||||
7. Avoid more than one empty line at any time. For example, do not have two
|
|
||||||
blank lines between members of a type.
|
|
||||||
8. Avoid spurious free spaces.
|
|
||||||
For example avoid `if (someVar == 0)...`, where the dots mark the spurious free spaces.
|
|
||||||
Consider enabling "View White Space (Ctrl+R, Ctrl+W)" or "Edit -> Advanced -> View White Space" if using Visual Studio to aid detection.
|
|
||||||
9. If a file happens to differ in style from these guidelines (e.g. private members are named `m_member`
|
|
||||||
rather than `_member`), the existing style in that file takes precedence.
|
|
||||||
10. We only use `var` when the type is explicitly named on the right-hand side, typically due to either `new` or an explicit cast, e.g. `var stream = new FileStream(...)` not `var stream = OpenStandardInput()`.
|
|
||||||
- Similarly, target-typed `new()` can only be used when the type is explicitly named on the left-hand side, in a variable definition statement or a field definition statement. e.g. `FileStream stream = new(...);`, but not `stream = new(...);` (where the type was specified on a previous line).
|
|
||||||
11. We use language keywords instead of BCL types (e.g. `int, string, float` instead of `Int32, String, Single`, etc) for both type references as well as method calls (e.g. `int.Parse` instead of `Int32.Parse`). See issue [#13976](https://github.com/dotnet/runtime/issues/13976) for examples.
|
|
||||||
12. We use PascalCasing to name all our constant local variables and fields. The only exception is for interop code where the constant value should exactly match the name and value of the code you are calling via interop.
|
|
||||||
13. We use PascalCasing for all method names, including local functions.
|
|
||||||
14. We use ```nameof(...)``` instead of ```"..."``` whenever possible and relevant.
|
|
||||||
15. Fields should be specified at the top within type declarations.
|
|
||||||
16. When including non-ASCII characters in the source code use Unicode escape sequences (\uXXXX) instead of literal characters. Literal non-ASCII characters occasionally get garbled by a tool or editor.
|
|
||||||
17. When using labels (for goto), indent the label one less than the current indentation.
|
|
||||||
18. When using a single-statement if, we follow these conventions:
|
|
||||||
- Never use single-line form (for example: `if (source == null) throw new ArgumentNullException("source");`)
|
|
||||||
- Using braces is always accepted, and required if any block of an `if`/`else if`/.../`else` compound statement uses braces or if a single statement body spans multiple lines.
|
|
||||||
- Braces may be omitted only if the body of *every* block associated with an `if`/`else if`/.../`else` compound statement is placed on a single line.
|
|
||||||
19. Make all internal and private types static or sealed unless derivation from them is required. As with any implementation detail, they can be changed if/when derivation is required in the future.
|
|
||||||
20. XML docs should be used when writing interfaces or when a class/method is deemed sufficient in scope or complexity.
|
|
||||||
21. So-called [Magic Numbers](https://en.wikipedia.org/wiki/Magic_number_(programming)) should be defined as named constants before use (for example `for (int i = 56; i < 68; i++)` could read `for (int i = _currentAge; i < _retireAge; i++)`).
|
|
||||||
This may be ignored for trivial or syntactically common statements.
|
|
||||||
|
|
||||||
An [EditorConfig](https://editorconfig.org "EditorConfig homepage") file (`.editorconfig`) has been provided at the root of the runtime repository, enabling C# auto-formatting conforming to the above guidelines.
|
|
||||||
|
|
||||||
### Example File:
|
|
||||||
|
|
||||||
``ShaderCache.cs:``
|
|
||||||
|
|
||||||
```C#
|
|
||||||
using Ryujinx.Common.Configuration;
|
|
||||||
using Ryujinx.Common.Logging;
|
|
||||||
using Ryujinx.Graphics.GAL;
|
|
||||||
using Ryujinx.Graphics.Gpu.Engine.Threed;
|
|
||||||
using Ryujinx.Graphics.Gpu.Engine.Types;
|
|
||||||
using Ryujinx.Graphics.Gpu.Image;
|
|
||||||
using Ryujinx.Graphics.Gpu.Memory;
|
|
||||||
using Ryujinx.Graphics.Gpu.Shader.DiskCache;
|
|
||||||
using Ryujinx.Graphics.Shader;
|
|
||||||
using Ryujinx.Graphics.Shader.Translation;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Shader
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Memory cache of shader code.
|
|
||||||
/// </summary>
|
|
||||||
class ShaderCache : IDisposable
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Default flags used on the shader translation process.
|
|
||||||
/// </summary>
|
|
||||||
public const TranslationFlags DefaultFlags = TranslationFlags.DebugMode;
|
|
||||||
|
|
||||||
private readonly struct TranslatedShader
|
|
||||||
{
|
|
||||||
public readonly CachedShaderStage Shader;
|
|
||||||
public readonly ShaderProgram Program;
|
|
||||||
|
|
||||||
public TranslatedShader(CachedShaderStage shader, ShaderProgram program)
|
|
||||||
{
|
|
||||||
Shader = shader;
|
|
||||||
Program = program;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
...
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Processes the queue of shaders that must save their binaries to the disk cache.
|
|
||||||
/// </summary>
|
|
||||||
public void ProcessShaderCacheQueue()
|
|
||||||
{
|
|
||||||
// Check to see if the binaries for previously compiled shaders are ready, and save them out.
|
|
||||||
|
|
||||||
while (_programsToSaveQueue.TryPeek(out ProgramToSave programToSave))
|
|
||||||
{
|
|
||||||
ProgramLinkStatus result = programToSave.HostProgram.CheckProgramLink(false);
|
|
||||||
|
|
||||||
if (result != ProgramLinkStatus.Incomplete)
|
|
||||||
{
|
|
||||||
if (result == ProgramLinkStatus.Success)
|
|
||||||
{
|
|
||||||
_cacheWriter.AddShader(programToSave.CachedProgram, programToSave.BinaryCode ?? programToSave.HostProgram.GetBinary());
|
|
||||||
}
|
|
||||||
|
|
||||||
_programsToSaveQueue.Dequeue();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For other languages, our current best guidance is consistency. When editing files, keep new code and changes consistent with the style in the files. For new files, it should conform to the style for that component. If there is a completely new component, anything that is reasonably broadly accepted is fine.
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 905 KiB |
@@ -1,51 +0,0 @@
|
|||||||
# Pull Request Guide
|
|
||||||
|
|
||||||
## Contributing Rules
|
|
||||||
|
|
||||||
All contributions to Kenji-NX repository are made via pull requests (PRs) rather than through direct commits. The pull requests are reviewed and merged by the maintainers after a review and at least two approvals from the core development team.
|
|
||||||
|
|
||||||
To merge pull requests, you must have write permissions in the repository.
|
|
||||||
|
|
||||||
## Quick Code Review Rules
|
|
||||||
|
|
||||||
* Do not mix unrelated changes in one pull request. For example, a code style change should never be mixed with a bug fix.
|
|
||||||
* All changes should follow the existing code style. You can read more about our code style at [docs/coding-guidelines](../coding-guidelines/coding-style.md).
|
|
||||||
* Adding external dependencies is to be avoided unless not doing so would introduce _significant_ complexity. Any dependency addition should be justified and discussed before merge.
|
|
||||||
* Use Draft pull requests for changes you are still working on but want early CI loop feedback. When you think your changes are ready for review, [change the status](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/changing-the-stage-of-a-pull-request) of your pull request.
|
|
||||||
* Rebase your changes when required or directly requested. Changes should always be commited on top of the upstream branch, not the other way around.
|
|
||||||
* If you are asked to make changes during the review process do them as a new commit.
|
|
||||||
* Only resolve GitHub conversations with reviewers once they have been addressed with a commit, or via a mutual agreement.
|
|
||||||
|
|
||||||
## Pull Request Ownership
|
|
||||||
|
|
||||||
Every pull request will automatically have labels and reviewers assigned. The label not only indicates the code segment which the change touches but also the area reviewers to be assigned.
|
|
||||||
|
|
||||||
If during the code review process a merge conflict occurs, the PR author is responsible for its resolution. Help will be provided if necessary although GitHub makes this easier by allowing simple conflict resolution using the [conflict-editor](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/resolving-a-merge-conflict-on-github).
|
|
||||||
|
|
||||||
## Review Turnaround Times
|
|
||||||
|
|
||||||
Kenji-NX is a project that is maintained by volunteers on a completely free-time basis. As such we cannot guarantee any particular timeframe for pull request review and approval. Weeks to months are common for larger (>500 line) PRs but there are some additional best practises to avoid review purgatory.
|
|
||||||
|
|
||||||
* Make the reviewers life easier wherever possible. Make use of descriptive commit names, code comments and XML docs where applicable.
|
|
||||||
* If there is disagreement on feedback then always lean on the side of the development team and community over any personal opinion.
|
|
||||||
* We're human. We miss things. We forget things. If there has been radio silence on your changes for a substantial period of time then do not hesitate to reach out directly either with something simple like "bump" on GitHub or a directly on Discord.
|
|
||||||
|
|
||||||
To re-iterate, make the review as easy for us as possible, respond promptly and be comfortable to interact directly with us for anything else.
|
|
||||||
|
|
||||||
## Merging Pull Requests
|
|
||||||
|
|
||||||
Anyone with write access can merge a pull request manually when the following conditions have been met:
|
|
||||||
|
|
||||||
* The PR has been approved by two reviewers and any other objections are addressed.
|
|
||||||
* You can request follow-up reviews from the original reviewers if they requested changes.
|
|
||||||
|
|
||||||
Typically, PRs are merged as one commit (squash merges). It creates a simpler history than a Merge Commit. "Special circumstances" are rare, and typically mean that there are a series of cleanly separated changes that will be too hard to understand if squashed together, or for some reason we want to preserve the ability to dissect them.
|
|
||||||
|
|
||||||
## Blocking Pull Request Merging
|
|
||||||
|
|
||||||
If for whatever reason you would like to move your pull request back to an in-progress status to avoid merging it in the current form, you can turn the PR into a draft PR by selecting the option under the reviewers section. Alternatively, you can do that by adding [WIP] prefix to the pull request title.
|
|
||||||
|
|
||||||
## Old Pull Request Policy
|
|
||||||
|
|
||||||
From time to time we will review older PRs and check them for relevance. If we find the PR is inactive or no longer applies, we will close it. As the PR owner, you can simply reopen it if you feel your closed PR needs our attention.
|
|
||||||
|
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"sdk": {
|
"sdk": {
|
||||||
"version": "9.0.100",
|
"version": "7.0.200",
|
||||||
"rollForward": "latestFeature"
|
"rollForward": "latestFeature"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-17
@@ -1,23 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<packageSources>
|
<packageSources>
|
||||||
<clear />
|
<clear />
|
||||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||||
<!-- Only needed when using pre-release versions of Ryujinx.LibHac. -->
|
|
||||||
<add key="LibHacAlpha" value="https://git.ryujinx.app/api/packages/projects/nuget/index.json" />
|
|
||||||
<!--<add key="Silk.NET" value="https://gitlab.com/api/v4/projects/51457475/packages/nuget/index.json" />-->
|
|
||||||
</packageSources>
|
</packageSources>
|
||||||
<packageSourceMapping>
|
|
||||||
<!-- key value for <packageSource> should match key values from <packageSources> element -->
|
|
||||||
<!-- These are defined and .NET still yells about multiple package sources with no mappings. Not sure what to do, this is in the docs lol -->
|
|
||||||
<packageSource key="nuget.org">
|
|
||||||
<package pattern="*" />
|
|
||||||
</packageSource>
|
|
||||||
<packageSource key="LibHacAlpha">
|
|
||||||
<package pattern="Ryujinx.LibHac" />
|
|
||||||
</packageSource>
|
|
||||||
<!--<packageSource key="Silk.NET">
|
|
||||||
<package pattern="Silk.*" />
|
|
||||||
</packageSource>-->
|
|
||||||
</packageSourceMapping>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<RuntimeIdentifiers>osx-arm64</RuntimeIdentifiers>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Memory\Ryujinx.Memory.csproj" />
|
<ProjectReference Include="..\Ryujinx.Memory\Ryujinx.Memory.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ContentWithTargetPath Include="Native\libs\libarmeilleure-jitsupport.dylib" Condition="'$(RuntimeIdentifier)' == 'osx-arm64'">
|
<ContentWithTargetPath Include="Native\libs\libarmeilleure-jitsupport.dylib" Condition="'$(RuntimeIdentifier)' == '' OR '$(RuntimeIdentifier)' == 'osx-arm64'">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<TargetPath>libarmeilleure-jitsupport.dylib</TargetPath>
|
<TargetPath>libarmeilleure-jitsupport.dylib</TargetPath>
|
||||||
</ContentWithTargetPath>
|
</ContentWithTargetPath>
|
||||||
@@ -23,8 +23,4 @@
|
|||||||
</AssemblyAttribute>
|
</AssemblyAttribute>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Humanizer" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using ARMeilleure.Common;
|
using ARMeilleure.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
@@ -23,7 +23,10 @@ namespace ARMeilleure
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static ArenaAllocator GetAllocator(ref ArenaAllocator alloc, uint pageSize, uint pageCount)
|
private static ArenaAllocator GetAllocator(ref ArenaAllocator alloc, uint pageSize, uint pageCount)
|
||||||
{
|
{
|
||||||
alloc ??= new ArenaAllocator(pageSize, pageCount);
|
if (alloc == null)
|
||||||
|
{
|
||||||
|
alloc = new ArenaAllocator(pageSize, pageCount);
|
||||||
|
}
|
||||||
|
|
||||||
return alloc;
|
return alloc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
public static void RunPass(ControlFlowGraph cfg)
|
public static void RunPass(ControlFlowGraph cfg)
|
||||||
{
|
{
|
||||||
Dictionary<ulong, Operand> constants = new();
|
var constants = new Dictionary<ulong, Operand>();
|
||||||
|
|
||||||
Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source)
|
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
|
// 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).
|
// to avoid overflow of the counts field (that is limited to 16 bits).
|
||||||
if (!constants.TryGetValue(source.Value, out Operand constant) || constant.UsesCount > MaxConstantUses)
|
if (!constants.TryGetValue(source.Value, out var constant) || constant.UsesCount > MaxConstantUses)
|
||||||
{
|
{
|
||||||
constant = Local(source.Type);
|
constant = Local(source.Type);
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
2 => Multiplier.x4,
|
2 => Multiplier.x4,
|
||||||
3 => Multiplier.x8,
|
3 => Multiplier.x8,
|
||||||
4 => Multiplier.x16,
|
4 => Multiplier.x16,
|
||||||
_ => Multiplier.x1,
|
_ => Multiplier.x1
|
||||||
};
|
};
|
||||||
|
|
||||||
baseOp = indexOnSrc2 ? src1 : src2;
|
baseOp = indexOnSrc2 ? src1 : src2;
|
||||||
@@ -254,7 +254,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
private static bool IsMemoryLoadOrStore(Instruction inst)
|
private static bool IsMemoryLoadOrStore(Instruction inst)
|
||||||
{
|
{
|
||||||
return inst is Instruction.Load or Instruction.Store;
|
return inst == Instruction.Load || inst == Instruction.Store;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ConstTooLong(Operand constOp, OperandType accessType)
|
private static bool ConstTooLong(Operand constOp, OperandType accessType)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Gt = 12,
|
Gt = 12,
|
||||||
Le = 13,
|
Le = 13,
|
||||||
Al = 14,
|
Al = 14,
|
||||||
Nv = 15,
|
Nv = 15
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ComparisonArm64Extensions
|
static class ComparisonArm64Extensions
|
||||||
@@ -29,7 +29,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
{
|
{
|
||||||
return comp switch
|
return comp switch
|
||||||
{
|
{
|
||||||
#pragma warning disable IDE0055 // Disable formatting
|
|
||||||
Comparison.Equal => ArmCondition.Eq,
|
Comparison.Equal => ArmCondition.Eq,
|
||||||
Comparison.NotEqual => ArmCondition.Ne,
|
Comparison.NotEqual => ArmCondition.Ne,
|
||||||
Comparison.Greater => ArmCondition.Gt,
|
Comparison.Greater => ArmCondition.Gt,
|
||||||
@@ -40,9 +39,8 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Comparison.Less => ArmCondition.Lt,
|
Comparison.Less => ArmCondition.Lt,
|
||||||
Comparison.GreaterOrEqualUI => ArmCondition.GeUn,
|
Comparison.GreaterOrEqualUI => ArmCondition.GeUn,
|
||||||
Comparison.LessUI => ArmCondition.LtUn,
|
Comparison.LessUI => ArmCondition.LtUn,
|
||||||
#pragma warning restore IDE0055
|
|
||||||
|
|
||||||
_ => throw new ArgumentException(null, nameof(comp)),
|
_ => throw new ArgumentException(null, nameof(comp))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Sxtb = 4,
|
Sxtb = 4,
|
||||||
Sxth = 5,
|
Sxth = 5,
|
||||||
Sxtw = 6,
|
Sxtw = 6,
|
||||||
Sxtx = 7,
|
Sxtx = 7
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Lsl = 0,
|
Lsl = 0,
|
||||||
Lsr = 1,
|
Lsr = 1,
|
||||||
Asr = 2,
|
Asr = 2,
|
||||||
Ror = 3,
|
Ror = 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,7 +123,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
public void Cset(Operand rd, ArmCondition condition)
|
public void Cset(Operand rd, ArmCondition condition)
|
||||||
{
|
{
|
||||||
Operand zr = Factory.Register(ZrRegister, RegisterType.Integer, rd.Type);
|
var zr = Factory.Register(ZrRegister, RegisterType.Integer, rd.Type);
|
||||||
Csinc(rd, zr, zr, (ArmCondition)((int)condition ^ 1));
|
Csinc(rd, zr, zr, (ArmCondition)((int)condition ^ 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -992,7 +992,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
{
|
{
|
||||||
OperandType.FP32 => 0,
|
OperandType.FP32 => 0,
|
||||||
OperandType.FP64 => 1,
|
OperandType.FP64 => 1,
|
||||||
_ => 2,
|
_ => 2
|
||||||
};
|
};
|
||||||
|
|
||||||
instruction = vecInst | ((uint)opc << 30);
|
instruction = vecInst | ((uint)opc << 30);
|
||||||
@@ -1124,11 +1124,10 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
OperandType.FP32 => 2,
|
OperandType.FP32 => 2,
|
||||||
OperandType.FP64 => 3,
|
OperandType.FP64 => 3,
|
||||||
OperandType.V128 => 4,
|
OperandType.V128 => 4,
|
||||||
_ => throw new ArgumentException($"Invalid type {type}."),
|
_ => throw new ArgumentException($"Invalid type {type}.")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable IDE0051 // Remove unused private member
|
|
||||||
private void WriteInt16(short value)
|
private void WriteInt16(short value)
|
||||||
{
|
{
|
||||||
WriteUInt16((ushort)value);
|
WriteUInt16((ushort)value);
|
||||||
@@ -1143,7 +1142,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
{
|
{
|
||||||
_stream.WriteByte(value);
|
_stream.WriteByte(value);
|
||||||
}
|
}
|
||||||
#pragma warning restore IDE0051
|
|
||||||
|
|
||||||
private void WriteUInt16(ushort value)
|
private void WriteUInt16(ushort value)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
// Any value AND all ones will be equal itself, so it's effectively a no-op.
|
// 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 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.
|
// Any value XOR all ones will be equal its inverse, so one can just use MVN.
|
||||||
if (value is 0 or ulong.MaxValue)
|
if (value == 0 || value == ulong.MaxValue)
|
||||||
{
|
{
|
||||||
immN = 0;
|
immN = 0;
|
||||||
immS = 0;
|
immS = 0;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
private const int CbnzInstLength = 4;
|
private const int CbnzInstLength = 4;
|
||||||
private const int LdrLitInstLength = 4;
|
private const int LdrLitInstLength = 4;
|
||||||
|
|
||||||
private readonly Stream _stream;
|
private Stream _stream;
|
||||||
|
|
||||||
public int StreamOffset => (int)_stream.Length;
|
public int StreamOffset => (int)_stream.Length;
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
private readonly Dictionary<BasicBlock, long> _visitedBlocks;
|
private readonly Dictionary<BasicBlock, long> _visitedBlocks;
|
||||||
private readonly Dictionary<BasicBlock, List<(ArmCondition Condition, long BranchPos)>> _pendingBranches;
|
private readonly Dictionary<BasicBlock, List<(ArmCondition Condition, long BranchPos)>> _pendingBranches;
|
||||||
|
|
||||||
private readonly struct ConstantPoolEntry
|
private struct ConstantPoolEntry
|
||||||
{
|
{
|
||||||
public readonly int Offset;
|
public readonly int Offset;
|
||||||
public readonly Symbol Symbol;
|
public readonly Symbol Symbol;
|
||||||
@@ -42,7 +42,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
{
|
{
|
||||||
Offset = offset;
|
Offset = offset;
|
||||||
Symbol = symbol;
|
Symbol = symbol;
|
||||||
LdrOffsets = [];
|
LdrOffsets = new List<(Operand, int)>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
private readonly bool _relocatable;
|
private readonly bool _relocatable;
|
||||||
|
|
||||||
public CodeGenContext(AllocationResult allocResult, int maxCallArgs, bool relocatable)
|
public CodeGenContext(AllocationResult allocResult, int maxCallArgs, int blocksCount, bool relocatable)
|
||||||
{
|
{
|
||||||
_stream = MemoryStreamManager.Shared.GetStream();
|
_stream = MemoryStreamManager.Shared.GetStream();
|
||||||
|
|
||||||
@@ -91,12 +91,12 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
long target = _stream.Position;
|
long target = _stream.Position;
|
||||||
|
|
||||||
if (_pendingBranches.TryGetValue(block, out List<(ArmCondition Condition, long BranchPos)> list))
|
if (_pendingBranches.TryGetValue(block, out var list))
|
||||||
{
|
{
|
||||||
foreach ((ArmCondition condition, long branchPos) in list)
|
foreach (var tuple in list)
|
||||||
{
|
{
|
||||||
_stream.Seek(branchPos, SeekOrigin.Begin);
|
_stream.Seek(tuple.BranchPos, SeekOrigin.Begin);
|
||||||
WriteBranch(condition, target);
|
WriteBranch(tuple.Condition, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
_stream.Seek(target, SeekOrigin.Begin);
|
_stream.Seek(target, SeekOrigin.Begin);
|
||||||
@@ -119,7 +119,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!_pendingBranches.TryGetValue(target, out List<(ArmCondition Condition, long BranchPos)> list))
|
if (!_pendingBranches.TryGetValue(target, out var list))
|
||||||
{
|
{
|
||||||
list = new List<(ArmCondition, long)>();
|
list = new List<(ArmCondition, long)>();
|
||||||
_pendingBranches.Add(target, list);
|
_pendingBranches.Add(target, list);
|
||||||
@@ -237,7 +237,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
long originalPosition = _stream.Position;
|
long originalPosition = _stream.Position;
|
||||||
|
|
||||||
_stream.Seek(0, SeekOrigin.Begin);
|
_stream.Seek(0, SeekOrigin.Begin);
|
||||||
_stream.ReadExactly(code, 0, code.Length);
|
_stream.Read(code, 0, code.Length);
|
||||||
_stream.Seek(originalPosition, SeekOrigin.Begin);
|
_stream.Seek(originalPosition, SeekOrigin.Begin);
|
||||||
|
|
||||||
RelocInfo relocInfo;
|
RelocInfo relocInfo;
|
||||||
@@ -266,7 +266,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
relocInfo = new RelocInfo([]);
|
relocInfo = new RelocInfo(Array.Empty<RelocEntry>());
|
||||||
}
|
}
|
||||||
|
|
||||||
return (code, relocInfo);
|
return (code, relocInfo);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
using static ARMeilleure.IntermediateRepresentation.Operand;
|
using static ARMeilleure.IntermediateRepresentation.Operand;
|
||||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
|
|
||||||
@@ -30,16 +31,15 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
{
|
{
|
||||||
Byte,
|
Byte,
|
||||||
Hword,
|
Hword,
|
||||||
Auto,
|
Auto
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Action<CodeGenContext, Operation>[] _instTable;
|
private static Action<CodeGenContext, Operation>[] _instTable;
|
||||||
|
|
||||||
static CodeGenerator()
|
static CodeGenerator()
|
||||||
{
|
{
|
||||||
_instTable = new Action<CodeGenContext, Operation>[EnumUtils.GetCount(typeof(Instruction))];
|
_instTable = new Action<CodeGenContext, Operation>[EnumUtils.GetCount(typeof(Instruction))];
|
||||||
|
|
||||||
#pragma warning disable IDE0055 // Disable formatting
|
|
||||||
Add(Instruction.Add, GenerateAdd);
|
Add(Instruction.Add, GenerateAdd);
|
||||||
Add(Instruction.BitwiseAnd, GenerateBitwiseAnd);
|
Add(Instruction.BitwiseAnd, GenerateBitwiseAnd);
|
||||||
Add(Instruction.BitwiseExclusiveOr, GenerateBitwiseExclusiveOr);
|
Add(Instruction.BitwiseExclusiveOr, GenerateBitwiseExclusiveOr);
|
||||||
@@ -100,7 +100,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Add(Instruction.ZeroExtend16, GenerateZeroExtend16);
|
Add(Instruction.ZeroExtend16, GenerateZeroExtend16);
|
||||||
Add(Instruction.ZeroExtend32, GenerateZeroExtend32);
|
Add(Instruction.ZeroExtend32, GenerateZeroExtend32);
|
||||||
Add(Instruction.ZeroExtend8, GenerateZeroExtend8);
|
Add(Instruction.ZeroExtend8, GenerateZeroExtend8);
|
||||||
#pragma warning restore IDE0055
|
|
||||||
|
|
||||||
static void Add(Instruction inst, Action<CodeGenContext, Operation> func)
|
static void Add(Instruction inst, Action<CodeGenContext, Operation> func)
|
||||||
{
|
{
|
||||||
@@ -132,7 +131,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
StackAllocator stackAlloc = new();
|
StackAllocator stackAlloc = new();
|
||||||
|
|
||||||
PreAllocator.RunPass(cctx, out int maxCallArgs);
|
PreAllocator.RunPass(cctx, stackAlloc, out int maxCallArgs);
|
||||||
|
|
||||||
Logger.EndPass(PassName.PreAllocation, cfg);
|
Logger.EndPass(PassName.PreAllocation, cfg);
|
||||||
|
|
||||||
@@ -169,9 +168,11 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
Logger.StartPass(PassName.CodeGeneration);
|
Logger.StartPass(PassName.CodeGeneration);
|
||||||
|
|
||||||
|
//Console.Error.WriteLine(IRDumper.GetDump(cfg));
|
||||||
|
|
||||||
bool relocatable = (cctx.Options & CompilerOptions.Relocatable) != 0;
|
bool relocatable = (cctx.Options & CompilerOptions.Relocatable) != 0;
|
||||||
|
|
||||||
CodeGenContext context = new(allocResult, maxCallArgs, relocatable);
|
CodeGenContext context = new(allocResult, maxCallArgs, cfg.Blocks.Count, relocatable);
|
||||||
|
|
||||||
UnwindInfo unwindInfo = WritePrologue(context);
|
UnwindInfo unwindInfo = WritePrologue(context);
|
||||||
|
|
||||||
@@ -189,7 +190,8 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
// The only blocks which can have 0 successors are exit blocks.
|
// The only blocks which can have 0 successors are exit blocks.
|
||||||
Operation last = block.Operations.Last;
|
Operation last = block.Operations.Last;
|
||||||
|
|
||||||
Debug.Assert(last.Instruction is Instruction.Tailcall or Instruction.Return);
|
Debug.Assert(last.Instruction == Instruction.Tailcall ||
|
||||||
|
last.Instruction == Instruction.Return);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -321,7 +323,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||||
|
|
||||||
ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition();
|
var cond = ((Comparison)comp.AsInt32()).ToArmCondition();
|
||||||
|
|
||||||
GenerateCompareCommon(context, operation);
|
GenerateCompareCommon(context, operation);
|
||||||
|
|
||||||
@@ -353,7 +355,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Debug.Assert(dest.Type == OperandType.I32);
|
Debug.Assert(dest.Type == OperandType.I32);
|
||||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||||
|
|
||||||
ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition();
|
var cond = ((Comparison)comp.AsInt32()).ToArmCondition();
|
||||||
|
|
||||||
GenerateCompareCommon(context, operation);
|
GenerateCompareCommon(context, operation);
|
||||||
|
|
||||||
@@ -463,7 +465,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Operand dest = operation.Destination;
|
Operand dest = operation.Destination;
|
||||||
Operand source = operation.GetSource(0);
|
Operand source = operation.GetSource(0);
|
||||||
|
|
||||||
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64);
|
Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64);
|
||||||
Debug.Assert(dest.Type != source.Type);
|
Debug.Assert(dest.Type != source.Type);
|
||||||
Debug.Assert(source.Type != OperandType.V128);
|
Debug.Assert(source.Type != OperandType.V128);
|
||||||
|
|
||||||
@@ -482,7 +484,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Operand dest = operation.Destination;
|
Operand dest = operation.Destination;
|
||||||
Operand source = operation.GetSource(0);
|
Operand source = operation.GetSource(0);
|
||||||
|
|
||||||
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64);
|
Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64);
|
||||||
Debug.Assert(dest.Type != source.Type);
|
Debug.Assert(dest.Type != source.Type);
|
||||||
Debug.Assert(source.Type.IsInteger());
|
Debug.Assert(source.Type.IsInteger());
|
||||||
|
|
||||||
@@ -1078,7 +1080,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
private static UnwindInfo WritePrologue(CodeGenContext context)
|
private static UnwindInfo WritePrologue(CodeGenContext context)
|
||||||
{
|
{
|
||||||
List<UnwindPushEntry> pushEntries = [];
|
List<UnwindPushEntry> pushEntries = new List<UnwindPushEntry>();
|
||||||
|
|
||||||
Operand rsp = Register(SpRegister);
|
Operand rsp = Register(SpRegister);
|
||||||
|
|
||||||
@@ -1462,7 +1464,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
private static bool IsLoadOrStore(Operation operation)
|
private static bool IsLoadOrStore(Operation operation)
|
||||||
{
|
{
|
||||||
return operation.Instruction is Instruction.Load or Instruction.Store;
|
return operation.Instruction == Instruction.Load || operation.Instruction == Instruction.Store;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static OperandType GetMemOpValueType(Operation operation)
|
private static OperandType GetMemOpValueType(Operation operation)
|
||||||
@@ -1552,7 +1554,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
private static void EnsureSameReg(Operand op1, Operand op2)
|
private static void EnsureSameReg(Operand op1, Operand op2)
|
||||||
{
|
{
|
||||||
Debug.Assert(op1.Kind is OperandKind.Register or OperandKind.Memory);
|
Debug.Assert(op1.Kind == OperandKind.Register || op1.Kind == OperandKind.Memory);
|
||||||
Debug.Assert(op1.Kind == op2.Kind);
|
Debug.Assert(op1.Kind == op2.Kind);
|
||||||
Debug.Assert(op1.Value == op2.Value);
|
Debug.Assert(op1.Value == op2.Value);
|
||||||
}
|
}
|
||||||
@@ -1568,13 +1570,11 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Debug.Assert(op1.Type == op3.Type);
|
Debug.Assert(op1.Type == op3.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable IDE0051 // Remove unused private member
|
|
||||||
private static void EnsureSameType(Operand op1, Operand op2, Operand op3, Operand op4)
|
private static void EnsureSameType(Operand op1, Operand op2, Operand op3, Operand op4)
|
||||||
{
|
{
|
||||||
Debug.Assert(op1.Type == op2.Type);
|
Debug.Assert(op1.Type == op2.Type);
|
||||||
Debug.Assert(op1.Type == op3.Type);
|
Debug.Assert(op1.Type == op3.Type);
|
||||||
Debug.Assert(op1.Type == op4.Type);
|
Debug.Assert(op1.Type == op4.Type);
|
||||||
}
|
}
|
||||||
#pragma warning restore IDE0051
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,35 +179,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
(uint)operation.GetSource(2).AsInt32());
|
(uint)operation.GetSource(2).AsInt32());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IntrinsicType.Vector128Unary:
|
|
||||||
GenerateVectorUnary(
|
|
||||||
context,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
info.Inst,
|
|
||||||
operation.Destination,
|
|
||||||
operation.GetSource(0));
|
|
||||||
break;
|
|
||||||
case IntrinsicType.Vector128Binary:
|
|
||||||
GenerateVectorBinary(
|
|
||||||
context,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
info.Inst,
|
|
||||||
operation.Destination,
|
|
||||||
operation.GetSource(0),
|
|
||||||
operation.GetSource(1));
|
|
||||||
break;
|
|
||||||
case IntrinsicType.Vector128BinaryRd:
|
|
||||||
GenerateVectorUnary(
|
|
||||||
context,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
info.Inst,
|
|
||||||
operation.Destination,
|
|
||||||
operation.GetSource(1));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IntrinsicType.VectorUnary:
|
case IntrinsicType.VectorUnary:
|
||||||
GenerateVectorUnary(
|
GenerateVectorUnary(
|
||||||
context,
|
context,
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Intrinsics.Arm;
|
using System.Runtime.Intrinsics.Arm;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
@@ -74,7 +77,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Ssbs = 1 << 28,
|
Ssbs = 1 << 28,
|
||||||
Sb = 1 << 29,
|
Sb = 1 << 29,
|
||||||
Paca = 1 << 30,
|
Paca = 1 << 30,
|
||||||
Pacg = 1UL << 31,
|
Pacg = 1UL << 31
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
@@ -116,7 +119,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Sve_Ebf16 = 1UL << 33,
|
Sve_Ebf16 = 1UL << 33,
|
||||||
Cssc = 1UL << 34,
|
Cssc = 1UL << 34,
|
||||||
Rprfm = 1UL << 35,
|
Rprfm = 1UL << 35,
|
||||||
Sve2p1 = 1UL << 36,
|
Sve2p1 = 1UL << 36
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LinuxFeatureFlagsHwCap LinuxFeatureInfoHwCap { get; } = 0;
|
public static LinuxFeatureFlagsHwCap LinuxFeatureInfoHwCap { get; } = 0;
|
||||||
@@ -127,21 +130,21 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
#region macOS
|
#region macOS
|
||||||
|
|
||||||
[LibraryImport("libSystem.dylib", SetLastError = true)]
|
[LibraryImport("libSystem.dylib", SetLastError = true)]
|
||||||
private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, nint newValue, ulong newValueSize);
|
private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
|
||||||
|
|
||||||
[SupportedOSPlatform("macos")]
|
[SupportedOSPlatform("macos")]
|
||||||
private static bool CheckSysctlName(string name)
|
private static bool CheckSysctlName(string name)
|
||||||
{
|
{
|
||||||
ulong size = sizeof(int);
|
ulong size = sizeof(int);
|
||||||
if (sysctlbyname(name, out int val, ref size, nint.Zero, 0) == 0 && size == sizeof(int))
|
if (sysctlbyname(name, out int val, ref size, IntPtr.Zero, 0) == 0 && size == sizeof(int))
|
||||||
{
|
{
|
||||||
return val != 0;
|
return val != 0;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly string[] _sysctlNames =
|
private static string[] _sysctlNames = new string[]
|
||||||
[
|
{
|
||||||
"hw.optional.floatingpoint",
|
"hw.optional.floatingpoint",
|
||||||
"hw.optional.AdvSIMD",
|
"hw.optional.AdvSIMD",
|
||||||
"hw.optional.arm.FEAT_FP16",
|
"hw.optional.arm.FEAT_FP16",
|
||||||
@@ -151,7 +154,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
"hw.optional.armv8_crc32",
|
"hw.optional.armv8_crc32",
|
||||||
"hw.optional.arm.FEAT_SHA1",
|
"hw.optional.arm.FEAT_SHA1",
|
||||||
"hw.optional.arm.FEAT_SHA256"
|
"hw.optional.arm.FEAT_SHA256"
|
||||||
];
|
};
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum MacOsFeatureFlags
|
public enum MacOsFeatureFlags
|
||||||
@@ -164,7 +167,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Lse = 1 << 5,
|
Lse = 1 << 5,
|
||||||
Crc32 = 1 << 6,
|
Crc32 = 1 << 6,
|
||||||
Sha1 = 1 << 7,
|
Sha1 = 1 << 7,
|
||||||
Sha256 = 1 << 8,
|
Sha256 = 1 << 8
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MacOsFeatureFlags MacOsFeatureInfo { get; } = 0;
|
public static MacOsFeatureFlags MacOsFeatureInfo { get; } = 0;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace ARMeilleure.CodeGen.Arm64
|
namespace ARMeilleure.CodeGen.Arm64
|
||||||
{
|
{
|
||||||
readonly struct IntrinsicInfo
|
struct IntrinsicInfo
|
||||||
{
|
{
|
||||||
public uint Inst { get; }
|
public uint Inst { get; }
|
||||||
public IntrinsicType Type { get; }
|
public IntrinsicType Type { get; }
|
||||||
|
|||||||
@@ -5,13 +5,12 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
{
|
{
|
||||||
static class IntrinsicTable
|
static class IntrinsicTable
|
||||||
{
|
{
|
||||||
private static readonly IntrinsicInfo[] _intrinTable;
|
private static IntrinsicInfo[] _intrinTable;
|
||||||
|
|
||||||
static IntrinsicTable()
|
static IntrinsicTable()
|
||||||
{
|
{
|
||||||
_intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))];
|
_intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))];
|
||||||
|
|
||||||
#pragma warning disable IDE0055 // Disable formatting
|
|
||||||
Add(Intrinsic.Arm64AbsS, new IntrinsicInfo(0x5e20b800u, IntrinsicType.ScalarUnary));
|
Add(Intrinsic.Arm64AbsS, new IntrinsicInfo(0x5e20b800u, IntrinsicType.ScalarUnary));
|
||||||
Add(Intrinsic.Arm64AbsV, new IntrinsicInfo(0x0e20b800u, IntrinsicType.VectorUnary));
|
Add(Intrinsic.Arm64AbsV, new IntrinsicInfo(0x0e20b800u, IntrinsicType.VectorUnary));
|
||||||
Add(Intrinsic.Arm64AddhnV, new IntrinsicInfo(0x0e204000u, IntrinsicType.VectorTernaryRd));
|
Add(Intrinsic.Arm64AddhnV, new IntrinsicInfo(0x0e204000u, IntrinsicType.VectorTernaryRd));
|
||||||
@@ -20,8 +19,8 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Add(Intrinsic.Arm64AddvV, new IntrinsicInfo(0x0e31b800u, IntrinsicType.VectorUnary));
|
Add(Intrinsic.Arm64AddvV, new IntrinsicInfo(0x0e31b800u, IntrinsicType.VectorUnary));
|
||||||
Add(Intrinsic.Arm64AddS, new IntrinsicInfo(0x5e208400u, IntrinsicType.ScalarBinary));
|
Add(Intrinsic.Arm64AddS, new IntrinsicInfo(0x5e208400u, IntrinsicType.ScalarBinary));
|
||||||
Add(Intrinsic.Arm64AddV, new IntrinsicInfo(0x0e208400u, IntrinsicType.VectorBinary));
|
Add(Intrinsic.Arm64AddV, new IntrinsicInfo(0x0e208400u, IntrinsicType.VectorBinary));
|
||||||
Add(Intrinsic.Arm64AesdV, new IntrinsicInfo(0x4e285800u, IntrinsicType.Vector128BinaryRd));
|
Add(Intrinsic.Arm64AesdV, new IntrinsicInfo(0x4e285800u, IntrinsicType.Vector128Unary));
|
||||||
Add(Intrinsic.Arm64AeseV, new IntrinsicInfo(0x4e284800u, IntrinsicType.Vector128BinaryRd));
|
Add(Intrinsic.Arm64AeseV, new IntrinsicInfo(0x4e284800u, IntrinsicType.Vector128Unary));
|
||||||
Add(Intrinsic.Arm64AesimcV, new IntrinsicInfo(0x4e287800u, IntrinsicType.Vector128Unary));
|
Add(Intrinsic.Arm64AesimcV, new IntrinsicInfo(0x4e287800u, IntrinsicType.Vector128Unary));
|
||||||
Add(Intrinsic.Arm64AesmcV, new IntrinsicInfo(0x4e286800u, IntrinsicType.Vector128Unary));
|
Add(Intrinsic.Arm64AesmcV, new IntrinsicInfo(0x4e286800u, IntrinsicType.Vector128Unary));
|
||||||
Add(Intrinsic.Arm64AndV, new IntrinsicInfo(0x0e201c00u, IntrinsicType.VectorBinaryBitwise));
|
Add(Intrinsic.Arm64AndV, new IntrinsicInfo(0x0e201c00u, IntrinsicType.VectorBinaryBitwise));
|
||||||
@@ -449,7 +448,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
Add(Intrinsic.Arm64XtnV, new IntrinsicInfo(0x0e212800u, IntrinsicType.VectorUnary));
|
Add(Intrinsic.Arm64XtnV, new IntrinsicInfo(0x0e212800u, IntrinsicType.VectorUnary));
|
||||||
Add(Intrinsic.Arm64Zip1V, new IntrinsicInfo(0x0e003800u, IntrinsicType.VectorBinary));
|
Add(Intrinsic.Arm64Zip1V, new IntrinsicInfo(0x0e003800u, IntrinsicType.VectorBinary));
|
||||||
Add(Intrinsic.Arm64Zip2V, new IntrinsicInfo(0x0e007800u, IntrinsicType.VectorBinary));
|
Add(Intrinsic.Arm64Zip2V, new IntrinsicInfo(0x0e007800u, IntrinsicType.VectorBinary));
|
||||||
#pragma warning restore IDE0055
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Add(Intrinsic intrin, IntrinsicInfo info)
|
private static void Add(Intrinsic intrin, IntrinsicInfo info)
|
||||||
|
|||||||
@@ -23,10 +23,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
ScalarTernaryShlRd,
|
ScalarTernaryShlRd,
|
||||||
ScalarTernaryShrRd,
|
ScalarTernaryShrRd,
|
||||||
|
|
||||||
Vector128Unary,
|
|
||||||
Vector128Binary,
|
|
||||||
Vector128BinaryRd,
|
|
||||||
|
|
||||||
VectorUnary,
|
VectorUnary,
|
||||||
VectorUnaryBitwise,
|
VectorUnaryBitwise,
|
||||||
VectorUnaryByElem,
|
VectorUnaryByElem,
|
||||||
@@ -54,7 +50,10 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
VectorTernaryShlRd,
|
VectorTernaryShlRd,
|
||||||
VectorTernaryShrRd,
|
VectorTernaryShrRd,
|
||||||
|
|
||||||
|
Vector128Unary,
|
||||||
|
Vector128Binary,
|
||||||
|
|
||||||
GetRegister,
|
GetRegister,
|
||||||
SetRegister,
|
SetRegister
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System;
|
using System;
|
||||||
@@ -30,7 +31,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RunPass(CompilerContext cctx, out int maxCallArgs)
|
public static void RunPass(CompilerContext cctx, StackAllocator stackAlloc, out int maxCallArgs)
|
||||||
{
|
{
|
||||||
maxCallArgs = -1;
|
maxCallArgs = -1;
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
for (BasicBlock block = cctx.Cfg.Blocks.First; block != null; block = block.ListNext)
|
for (BasicBlock block = cctx.Cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
ConstantDict constants = new();
|
ConstantDict constants = new ConstantDict();
|
||||||
|
|
||||||
Operation nextNode;
|
Operation nextNode;
|
||||||
|
|
||||||
@@ -91,7 +92,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
InsertReturnCopy(block.Operations, node);
|
InsertReturnCopy(block.Operations, node);
|
||||||
break;
|
break;
|
||||||
case Instruction.Tailcall:
|
case Instruction.Tailcall:
|
||||||
InsertTailcallCopies(constants, block.Operations, node, node);
|
InsertTailcallCopies(constants, block.Operations, stackAlloc, node, node);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,7 +138,10 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
{
|
{
|
||||||
src2 = node.GetSource(1);
|
src2 = node.GetSource(1);
|
||||||
|
|
||||||
(src2, src1) = (src1, src2);
|
Operand temp = src1;
|
||||||
|
|
||||||
|
src1 = src2;
|
||||||
|
src2 = temp;
|
||||||
|
|
||||||
node.SetSource(0, src1);
|
node.SetSource(0, src1);
|
||||||
node.SetSource(1, src2);
|
node.SetSource(1, src2);
|
||||||
@@ -261,10 +265,10 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
Operand dest = operation.Destination;
|
Operand dest = operation.Destination;
|
||||||
|
|
||||||
List<Operand> sources =
|
List<Operand> sources = new List<Operand>
|
||||||
[
|
{
|
||||||
operation.GetSource(0)
|
operation.GetSource(0)
|
||||||
];
|
};
|
||||||
|
|
||||||
int argsCount = operation.SourcesCount - 1;
|
int argsCount = operation.SourcesCount - 1;
|
||||||
|
|
||||||
@@ -360,15 +364,17 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
operation.SetSources(sources.ToArray());
|
operation.SetSources(sources.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void InsertTailcallCopies(ConstantDict constants,
|
private static void InsertTailcallCopies(
|
||||||
|
ConstantDict constants,
|
||||||
IntrusiveList<Operation> nodes,
|
IntrusiveList<Operation> nodes,
|
||||||
|
StackAllocator stackAlloc,
|
||||||
Operation node,
|
Operation node,
|
||||||
Operation operation)
|
Operation operation)
|
||||||
{
|
{
|
||||||
List<Operand> sources =
|
List<Operand> sources = new List<Operand>
|
||||||
[
|
{
|
||||||
operation.GetSource(0)
|
operation.GetSource(0)
|
||||||
];
|
};
|
||||||
|
|
||||||
int argsCount = operation.SourcesCount - 1;
|
int argsCount = operation.SourcesCount - 1;
|
||||||
|
|
||||||
@@ -468,8 +474,8 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
// Update the sources and destinations with split 64-bit halfs of the whole 128-bit values.
|
// 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.
|
// We also need a additional registers that will be used to store temporary information.
|
||||||
operation.SetDestinations([actualLow, actualHigh, Local(OperandType.I64), Local(OperandType.I64)]);
|
operation.SetDestinations(new[] { actualLow, actualHigh, Local(OperandType.I64), Local(OperandType.I64) });
|
||||||
operation.SetSources([address, expectedLow, expectedHigh, desiredLow, desiredHigh]);
|
operation.SetSources(new[] { address, expectedLow, expectedHigh, desiredLow, desiredHigh });
|
||||||
|
|
||||||
// Add some dummy uses of the input operands, as the CAS operation will be a loop,
|
// 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.
|
// so they can't be used as destination operand.
|
||||||
@@ -486,7 +492,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We need a additional register where the store result will be written to.
|
// We need a additional register where the store result will be written to.
|
||||||
node.SetDestinations([node.Destination, Local(OperandType.I32)]);
|
node.SetDestinations(new[] { node.Destination, Local(OperandType.I32) });
|
||||||
|
|
||||||
// Add some dummy uses of the input operands, as the CAS operation will be a loop,
|
// 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.
|
// so they can't be used as destination operand.
|
||||||
@@ -736,19 +742,18 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
{
|
{
|
||||||
IntrinsicInfo info = IntrinsicTable.GetInfo(intrinsic & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask));
|
IntrinsicInfo info = IntrinsicTable.GetInfo(intrinsic & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask));
|
||||||
|
|
||||||
return info.Type is IntrinsicType.ScalarBinaryRd
|
return info.Type == IntrinsicType.ScalarBinaryRd ||
|
||||||
or IntrinsicType.ScalarTernaryFPRdByElem
|
info.Type == IntrinsicType.ScalarTernaryFPRdByElem ||
|
||||||
or IntrinsicType.ScalarTernaryShlRd
|
info.Type == IntrinsicType.ScalarTernaryShlRd ||
|
||||||
or IntrinsicType.ScalarTernaryShrRd
|
info.Type == IntrinsicType.ScalarTernaryShrRd ||
|
||||||
or IntrinsicType.Vector128BinaryRd
|
info.Type == IntrinsicType.VectorBinaryRd ||
|
||||||
or IntrinsicType.VectorBinaryRd
|
info.Type == IntrinsicType.VectorInsertByElem ||
|
||||||
or IntrinsicType.VectorInsertByElem
|
info.Type == IntrinsicType.VectorTernaryRd ||
|
||||||
or IntrinsicType.VectorTernaryRd
|
info.Type == IntrinsicType.VectorTernaryRdBitwise ||
|
||||||
or IntrinsicType.VectorTernaryRdBitwise
|
info.Type == IntrinsicType.VectorTernaryFPRdByElem ||
|
||||||
or IntrinsicType.VectorTernaryFPRdByElem
|
info.Type == IntrinsicType.VectorTernaryRdByElem ||
|
||||||
or IntrinsicType.VectorTernaryRdByElem
|
info.Type == IntrinsicType.VectorTernaryShlRd ||
|
||||||
or IntrinsicType.VectorTernaryShlRd
|
info.Type == IntrinsicType.VectorTernaryShrRd;
|
||||||
or IntrinsicType.VectorTernaryShrRd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool HasConstSrc1(Operation node, ulong value)
|
private static bool HasConstSrc1(Operation node, ulong value)
|
||||||
@@ -847,9 +852,9 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||||||
|
|
||||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||||
|
|
||||||
Comparison compType = (Comparison)comp.AsInt32();
|
var compType = (Comparison)comp.AsInt32();
|
||||||
|
|
||||||
return compType is Comparison.Equal or Comparison.NotEqual;
|
return compType == Comparison.Equal || compType == Comparison.NotEqual;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using ARMeilleure.CodeGen.Linking;
|
using ARMeilleure.CodeGen.Linking;
|
||||||
using ARMeilleure.CodeGen.Unwinding;
|
using ARMeilleure.CodeGen.Unwinding;
|
||||||
using ARMeilleure.Translation.Cache;
|
using ARMeilleure.Translation.Cache;
|
||||||
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen
|
namespace ARMeilleure.CodeGen
|
||||||
@@ -57,7 +58,7 @@ namespace ARMeilleure.CodeGen
|
|||||||
/// <typeparam name="T">Type of delegate</typeparam>
|
/// <typeparam name="T">Type of delegate</typeparam>
|
||||||
/// <param name="codePointer">Pointer to the function code in memory</param>
|
/// <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>
|
/// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
|
||||||
public T MapWithPointer<T>(out nint codePointer)
|
public T MapWithPointer<T>(out IntPtr codePointer)
|
||||||
{
|
{
|
||||||
codePointer = JitCache.Map(this);
|
codePointer = JitCache.Map(this);
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace ARMeilleure.CodeGen.Linking
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets an empty <see cref="RelocInfo"/>.
|
/// Gets an empty <see cref="RelocInfo"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static RelocInfo Empty { get; } = new(null);
|
public static RelocInfo Empty { get; } = new RelocInfo(null);
|
||||||
|
|
||||||
private readonly RelocEntry[] _entries;
|
private readonly RelocEntry[] _entries;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen.Linking
|
namespace ARMeilleure.CodeGen.Linking
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace ARMeilleure.CodeGen.Linking
|
namespace ARMeilleure.CodeGen.Linking
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Types of <see cref="Symbol"/>.
|
/// Types of <see cref="Symbol"/>.
|
||||||
@@ -23,6 +23,6 @@ namespace ARMeilleure.CodeGen.Linking
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Refers to a special symbol which is handled by <see cref="Translation.PTC.Ptc.PatchCode"/>.
|
/// Refers to a special symbol which is handled by <see cref="Translation.PTC.Ptc.PatchCode"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Special,
|
Special
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
|
|||||||
@@ -227,11 +227,11 @@ namespace ARMeilleure.CodeGen.Optimizations
|
|||||||
|
|
||||||
private static bool HasSideEffects(Operation node)
|
private static bool HasSideEffects(Operation node)
|
||||||
{
|
{
|
||||||
return node.Instruction is Instruction.Call
|
return node.Instruction == Instruction.Call
|
||||||
or Instruction.Tailcall
|
|| node.Instruction == Instruction.Tailcall
|
||||||
or Instruction.CompareAndSwap
|
|| node.Instruction == Instruction.CompareAndSwap
|
||||||
or Instruction.CompareAndSwap16
|
|| node.Instruction == Instruction.CompareAndSwap16
|
||||||
or Instruction.CompareAndSwap8;
|
|| node.Instruction == Instruction.CompareAndSwap8;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsPropagableCompare(Operation operation)
|
private static bool IsPropagableCompare(Operation operation)
|
||||||
|
|||||||
@@ -171,12 +171,13 @@ namespace ARMeilleure.CodeGen.Optimizations
|
|||||||
|
|
||||||
private static ulong AllOnes(OperandType type)
|
private static ulong AllOnes(OperandType type)
|
||||||
{
|
{
|
||||||
return type switch
|
switch (type)
|
||||||
{
|
{
|
||||||
OperandType.I32 => ~0U,
|
case OperandType.I32: return ~0U;
|
||||||
OperandType.I64 => ~0UL,
|
case OperandType.I64: return ~0UL;
|
||||||
_ => throw new ArgumentException("Invalid operand type \"" + type + "\"."),
|
}
|
||||||
};
|
|
||||||
|
throw new ArgumentException("Invalid operand type \"" + type + "\".");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
|
using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
|
using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
public ParallelCopy()
|
public ParallelCopy()
|
||||||
{
|
{
|
||||||
_copies = [];
|
_copies = new List<Copy>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddCopy(Register dest, Register source, OperandType type)
|
public void AddCopy(Register dest, Register source, OperandType type)
|
||||||
@@ -41,13 +42,13 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
public void Sequence(List<Operation> sequence)
|
public void Sequence(List<Operation> sequence)
|
||||||
{
|
{
|
||||||
Dictionary<Register, Register> locations = new();
|
Dictionary<Register, Register> locations = new Dictionary<Register, Register>();
|
||||||
Dictionary<Register, Register> sources = new();
|
Dictionary<Register, Register> sources = new Dictionary<Register, Register>();
|
||||||
|
|
||||||
Dictionary<Register, OperandType> types = new();
|
Dictionary<Register, OperandType> types = new Dictionary<Register, OperandType>();
|
||||||
|
|
||||||
Queue<Register> pendingQueue = new();
|
Queue<Register> pendingQueue = new Queue<Register>();
|
||||||
Queue<Register> readyQueue = new();
|
Queue<Register> readyQueue = new Queue<Register>();
|
||||||
|
|
||||||
foreach (Copy copy in _copies)
|
foreach (Copy copy in _copies)
|
||||||
{
|
{
|
||||||
@@ -185,7 +186,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
private void AddSplitFill(LiveInterval left, LiveInterval right, OperandType type)
|
private void AddSplitFill(LiveInterval left, LiveInterval right, OperandType type)
|
||||||
{
|
{
|
||||||
_fillQueue ??= new Queue<Operation>();
|
if (_fillQueue == null)
|
||||||
|
{
|
||||||
|
_fillQueue = new Queue<Operation>();
|
||||||
|
}
|
||||||
|
|
||||||
Operand register = GetRegister(right.Register, type);
|
Operand register = GetRegister(right.Register, type);
|
||||||
Operand offset = Const(left.SpillOffset);
|
Operand offset = Const(left.SpillOffset);
|
||||||
@@ -197,7 +201,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
private void AddSplitSpill(LiveInterval left, LiveInterval right, OperandType type)
|
private void AddSplitSpill(LiveInterval left, LiveInterval right, OperandType type)
|
||||||
{
|
{
|
||||||
_spillQueue ??= new Queue<Operation>();
|
if (_spillQueue == null)
|
||||||
|
{
|
||||||
|
_spillQueue = new Queue<Operation>();
|
||||||
|
}
|
||||||
|
|
||||||
Operand offset = Const(right.SpillOffset);
|
Operand offset = Const(right.SpillOffset);
|
||||||
Operand register = GetRegister(left.Register, type);
|
Operand register = GetRegister(left.Register, type);
|
||||||
@@ -209,7 +216,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
private void AddSplitCopy(LiveInterval left, LiveInterval right, OperandType type)
|
private void AddSplitCopy(LiveInterval left, LiveInterval right, OperandType type)
|
||||||
{
|
{
|
||||||
_parallelCopy ??= new ParallelCopy();
|
if (_parallelCopy == null)
|
||||||
|
{
|
||||||
|
_parallelCopy = new ParallelCopy();
|
||||||
|
}
|
||||||
|
|
||||||
_parallelCopy.AddCopy(right.Register, left.Register, type);
|
_parallelCopy.AddCopy(right.Register, left.Register, type);
|
||||||
|
|
||||||
@@ -218,7 +228,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
public Operation[] Sequence()
|
public Operation[] Sequence()
|
||||||
{
|
{
|
||||||
List<Operation> sequence = [];
|
List<Operation> sequence = new List<Operation>();
|
||||||
|
|
||||||
if (_spillQueue != null)
|
if (_spillQueue != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
private int _first;
|
private int _first;
|
||||||
private int _last;
|
private int _last;
|
||||||
|
|
||||||
public readonly bool IsBlockLocal => _first == _last;
|
public bool IsBlockLocal => _first == _last;
|
||||||
|
|
||||||
public LocalInfo(OperandType type, int uses, int blkIndex)
|
public LocalInfo(OperandType type, int uses, int blkIndex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
{
|
{
|
||||||
NumberLocals(cfg, regMasks.RegistersCount);
|
NumberLocals(cfg, regMasks.RegistersCount);
|
||||||
|
|
||||||
AllocationContext context = new(stackAlloc, regMasks, _intervals.Count);
|
var context = new AllocationContext(stackAlloc, regMasks, _intervals.Count);
|
||||||
|
|
||||||
BuildIntervals(cfg, context);
|
BuildIntervals(cfg, context);
|
||||||
|
|
||||||
@@ -251,20 +251,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a copy destination variable, we prefer the register used for the copy source.
|
int selectedReg = GetHighestValueIndex(freePositions);
|
||||||
// If the register is available, then the copy can be eliminated later as both source
|
|
||||||
// and destination will use the same register.
|
|
||||||
int selectedReg;
|
|
||||||
|
|
||||||
if (current.TryGetCopySourceRegister(out int preferredReg) && freePositions[preferredReg] >= current.GetEnd())
|
|
||||||
{
|
|
||||||
selectedReg = preferredReg;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
selectedReg = GetHighestValueIndex(freePositions);
|
|
||||||
}
|
|
||||||
|
|
||||||
int selectedNextUse = freePositions[selectedReg];
|
int selectedNextUse = freePositions[selectedReg];
|
||||||
|
|
||||||
// Intervals starts and ends at odd positions, unless they span an entire
|
// Intervals starts and ends at odd positions, unless they span an entire
|
||||||
@@ -444,7 +431,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetHighestValueIndex(ReadOnlySpan<int> span)
|
private static int GetHighestValueIndex(Span<int> span)
|
||||||
{
|
{
|
||||||
int highest = int.MinValue;
|
int highest = int.MinValue;
|
||||||
|
|
||||||
@@ -558,7 +545,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
_intervals.Insert(insertIndex, interval);
|
_intervals.Insert(insertIndex, interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Spill(AllocationContext context, LiveInterval interval)
|
private void Spill(AllocationContext context, LiveInterval interval)
|
||||||
{
|
{
|
||||||
Debug.Assert(!interval.IsFixed, "Trying to spill a fixed interval.");
|
Debug.Assert(!interval.IsFixed, "Trying to spill a fixed interval.");
|
||||||
Debug.Assert(interval.UsesCount == 0, "Trying to spill a interval with uses.");
|
Debug.Assert(interval.UsesCount == 0, "Trying to spill a interval with uses.");
|
||||||
@@ -574,7 +561,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
private void InsertSplitCopies()
|
private void InsertSplitCopies()
|
||||||
{
|
{
|
||||||
Dictionary<int, CopyResolver> copyResolvers = new();
|
Dictionary<int, CopyResolver> copyResolvers = new Dictionary<int, CopyResolver>();
|
||||||
|
|
||||||
CopyResolver GetCopyResolver(int position)
|
CopyResolver GetCopyResolver(int position)
|
||||||
{
|
{
|
||||||
@@ -689,7 +676,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
if (left != default && right != default && left != right)
|
if (left != default && right != default && left != right)
|
||||||
{
|
{
|
||||||
copyResolver ??= new CopyResolver();
|
if (copyResolver == null)
|
||||||
|
{
|
||||||
|
copyResolver = new CopyResolver();
|
||||||
|
}
|
||||||
|
|
||||||
copyResolver.AddSplit(left, right);
|
copyResolver.AddSplit(left, right);
|
||||||
}
|
}
|
||||||
@@ -799,8 +789,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
private void NumberLocals(ControlFlowGraph cfg, int registersCount)
|
private void NumberLocals(ControlFlowGraph cfg, int registersCount)
|
||||||
{
|
{
|
||||||
_operationNodes = [];
|
_operationNodes = new List<(IntrusiveList<Operation>, Operation)>();
|
||||||
_intervals = [];
|
_intervals = new List<LiveInterval>();
|
||||||
|
|
||||||
for (int index = 0; index < registersCount; index++)
|
for (int index = 0; index < registersCount; index++)
|
||||||
{
|
{
|
||||||
@@ -811,12 +801,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
// The "visited" state is stored in the MSB of the local's value.
|
// The "visited" state is stored in the MSB of the local's value.
|
||||||
const ulong VisitedMask = 1ul << 63;
|
const ulong VisitedMask = 1ul << 63;
|
||||||
|
|
||||||
static bool IsVisited(Operand local)
|
bool IsVisited(Operand local)
|
||||||
{
|
{
|
||||||
return (local.GetValueUnsafe() & VisitedMask) != 0;
|
return (local.GetValueUnsafe() & VisitedMask) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetVisited(Operand local)
|
void SetVisited(Operand local)
|
||||||
{
|
{
|
||||||
local.GetValueUnsafe() |= VisitedMask;
|
local.GetValueUnsafe() |= VisitedMask;
|
||||||
}
|
}
|
||||||
@@ -839,25 +829,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
{
|
{
|
||||||
dest.NumberLocal(_intervals.Count);
|
dest.NumberLocal(_intervals.Count);
|
||||||
|
|
||||||
LiveInterval interval = new(dest);
|
_intervals.Add(new LiveInterval(dest));
|
||||||
_intervals.Add(interval);
|
|
||||||
|
|
||||||
SetVisited(dest);
|
SetVisited(dest);
|
||||||
|
|
||||||
// If this is a copy (or copy-like operation), set the copy source interval as well.
|
|
||||||
// This is used for register preferencing later on, which allows the copy to be eliminated
|
|
||||||
// in some cases.
|
|
||||||
if (node.Instruction is Instruction.Copy or Instruction.ZeroExtend32)
|
|
||||||
{
|
|
||||||
Operand source = node.GetSource(0);
|
|
||||||
|
|
||||||
if (source.Kind == OperandKind.LocalVariable &&
|
|
||||||
source.GetLocalNumber() > 0 &&
|
|
||||||
(node.Instruction == Instruction.Copy || source.Type == OperandType.I32))
|
|
||||||
{
|
|
||||||
interval.SetCopySource(_intervals[source.GetLocalNumber()]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -888,8 +862,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
// Compute local live sets.
|
// Compute local live sets.
|
||||||
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
{
|
{
|
||||||
BitMap liveGen = new(Allocators.Default, mapSize);
|
BitMap liveGen = new BitMap(Allocators.Default, mapSize);
|
||||||
BitMap liveKill = new(Allocators.Default, mapSize);
|
BitMap liveKill = new BitMap(Allocators.Default, mapSize);
|
||||||
|
|
||||||
for (Operation node = block.Operations.First; node != default; node = node.ListNext)
|
for (Operation node = block.Operations.First; node != default; node = node.ListNext)
|
||||||
{
|
{
|
||||||
@@ -980,7 +954,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
_blockLiveIn = blkLiveIn;
|
_blockLiveIn = blkLiveIn;
|
||||||
|
|
||||||
_blockEdges = [];
|
_blockEdges = new HashSet<int>();
|
||||||
|
|
||||||
// Compute lifetime intervals.
|
// Compute lifetime intervals.
|
||||||
int operationPos = _operationsCount;
|
int operationPos = _operationsCount;
|
||||||
@@ -1087,7 +1061,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
{
|
{
|
||||||
int regIndex = BitOperations.TrailingZeroCount(mask);
|
int regIndex = BitOperations.TrailingZeroCount(mask);
|
||||||
|
|
||||||
Register callerSavedReg = new(regIndex, regType);
|
Register callerSavedReg = new Register(regIndex, regType);
|
||||||
|
|
||||||
LiveInterval interval = _intervals[GetRegisterId(callerSavedReg)];
|
LiveInterval interval = _intervals[GetRegisterId(callerSavedReg)];
|
||||||
|
|
||||||
@@ -1120,7 +1094,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
private static bool IsLocalOrRegister(OperandKind kind)
|
private static bool IsLocalOrRegister(OperandKind kind)
|
||||||
{
|
{
|
||||||
return kind is OperandKind.LocalVariable or OperandKind.Register;
|
return kind == OperandKind.LocalVariable ||
|
||||||
|
kind == OperandKind.Register;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,6 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
public LiveRange CurrRange;
|
public LiveRange CurrRange;
|
||||||
|
|
||||||
public LiveInterval Parent;
|
public LiveInterval Parent;
|
||||||
public LiveInterval CopySource;
|
|
||||||
|
|
||||||
public UseList Uses;
|
public UseList Uses;
|
||||||
public LiveIntervalList Children;
|
public LiveIntervalList Children;
|
||||||
@@ -38,7 +37,6 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
private ref LiveRange CurrRange => ref _data->CurrRange;
|
private ref LiveRange CurrRange => ref _data->CurrRange;
|
||||||
private ref LiveRange PrevRange => ref _data->PrevRange;
|
private ref LiveRange PrevRange => ref _data->PrevRange;
|
||||||
private ref LiveInterval Parent => ref _data->Parent;
|
private ref LiveInterval Parent => ref _data->Parent;
|
||||||
private ref LiveInterval CopySource => ref _data->CopySource;
|
|
||||||
private ref UseList Uses => ref _data->Uses;
|
private ref UseList Uses => ref _data->Uses;
|
||||||
private ref LiveIntervalList Children => ref _data->Children;
|
private ref LiveIntervalList Children => ref _data->Children;
|
||||||
|
|
||||||
@@ -80,25 +78,6 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
Register = register;
|
Register = register;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetCopySource(LiveInterval copySource)
|
|
||||||
{
|
|
||||||
CopySource = copySource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryGetCopySourceRegister(out int copySourceRegIndex)
|
|
||||||
{
|
|
||||||
if (CopySource._data != null)
|
|
||||||
{
|
|
||||||
copySourceRegIndex = CopySource.Register.Index;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
copySourceRegIndex = 0;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
PrevRange = default;
|
PrevRange = default;
|
||||||
@@ -261,10 +240,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
public LiveInterval Split(int position)
|
public LiveInterval Split(int position)
|
||||||
{
|
{
|
||||||
LiveInterval result = new(Local, Parent)
|
LiveInterval result = new(Local, Parent);
|
||||||
{
|
result.End = End;
|
||||||
End = End,
|
|
||||||
};
|
|
||||||
|
|
||||||
LiveRange prev = PrevRange;
|
LiveRange prev = PrevRange;
|
||||||
LiveRange curr = CurrRange;
|
LiveRange curr = CurrRange;
|
||||||
@@ -387,7 +364,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return HashCode.Combine((nint)_data);
|
return HashCode.Combine((IntPtr)_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen.RegisterAllocators
|
namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
{
|
{
|
||||||
@@ -8,19 +8,19 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
private int _count;
|
private int _count;
|
||||||
private int _capacity;
|
private int _capacity;
|
||||||
|
|
||||||
public readonly int Count => _count;
|
public int Count => _count;
|
||||||
public readonly Span<LiveInterval> Span => new(_items, _count);
|
public Span<LiveInterval> Span => new(_items, _count);
|
||||||
|
|
||||||
public void Add(LiveInterval interval)
|
public void Add(LiveInterval interval)
|
||||||
{
|
{
|
||||||
if (_count + 1 > _capacity)
|
if (_count + 1 > _capacity)
|
||||||
{
|
{
|
||||||
Span<LiveInterval> oldSpan = Span;
|
var oldSpan = Span;
|
||||||
|
|
||||||
_capacity = Math.Max(4, _capacity * 2);
|
_capacity = Math.Max(4, _capacity * 2);
|
||||||
_items = Allocators.References.Allocate<LiveInterval>((uint)_capacity);
|
_items = Allocators.References.Allocate<LiveInterval>((uint)_capacity);
|
||||||
|
|
||||||
Span<LiveInterval> newSpan = Span;
|
var newSpan = Span;
|
||||||
|
|
||||||
oldSpan.CopyTo(newSpan);
|
oldSpan.CopyTo(newSpan);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return HashCode.Combine((nint)_data);
|
return HashCode.Combine((IntPtr)_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen.RegisterAllocators
|
namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
{
|
{
|
||||||
@@ -6,29 +6,29 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
{
|
{
|
||||||
private int* _items;
|
private int* _items;
|
||||||
private int _capacity;
|
private int _capacity;
|
||||||
|
private int _count;
|
||||||
|
|
||||||
public int Count { get; private set; }
|
public int Count => _count;
|
||||||
|
public int FirstUse => _count > 0 ? _items[_count - 1] : LiveInterval.NotFound;
|
||||||
public readonly int FirstUse => Count > 0 ? _items[Count - 1] : LiveInterval.NotFound;
|
public Span<int> Span => new(_items, _count);
|
||||||
public readonly Span<int> Span => new(_items, Count);
|
|
||||||
|
|
||||||
public void Add(int position)
|
public void Add(int position)
|
||||||
{
|
{
|
||||||
if (Count + 1 > _capacity)
|
if (_count + 1 > _capacity)
|
||||||
{
|
{
|
||||||
Span<int> oldSpan = Span;
|
var oldSpan = Span;
|
||||||
|
|
||||||
_capacity = Math.Max(4, _capacity * 2);
|
_capacity = Math.Max(4, _capacity * 2);
|
||||||
_items = Allocators.Default.Allocate<int>((uint)_capacity);
|
_items = Allocators.Default.Allocate<int>((uint)_capacity);
|
||||||
|
|
||||||
Span<int> newSpan = Span;
|
var newSpan = Span;
|
||||||
|
|
||||||
oldSpan.CopyTo(newSpan);
|
oldSpan.CopyTo(newSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use positions are usually inserted in descending order, so inserting in descending order is faster,
|
// Use positions are usually inserted in descending order, so inserting in descending order is faster,
|
||||||
// since the number of half exchanges is reduced.
|
// since the number of half exchanges is reduced.
|
||||||
int i = Count - 1;
|
int i = _count - 1;
|
||||||
|
|
||||||
while (i >= 0 && _items[i] < position)
|
while (i >= 0 && _items[i] < position)
|
||||||
{
|
{
|
||||||
@@ -36,19 +36,19 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
}
|
}
|
||||||
|
|
||||||
_items[i + 1] = position;
|
_items[i + 1] = position;
|
||||||
Count++;
|
_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly int NextUse(int position)
|
public int NextUse(int position)
|
||||||
{
|
{
|
||||||
int index = NextUseIndex(position);
|
int index = NextUseIndex(position);
|
||||||
|
|
||||||
return index != LiveInterval.NotFound ? _items[index] : LiveInterval.NotFound;
|
return index != LiveInterval.NotFound ? _items[index] : LiveInterval.NotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly int NextUseIndex(int position)
|
public int NextUseIndex(int position)
|
||||||
{
|
{
|
||||||
int i = Count - 1;
|
int i = _count - 1;
|
||||||
|
|
||||||
if (i == -1 || position > _items[0])
|
if (i == -1 || position > _items[0])
|
||||||
{
|
{
|
||||||
@@ -69,16 +69,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||||||
|
|
||||||
// Since the list is in descending order, the new split list takes the front of the list and the current
|
// Since the list is in descending order, the new split list takes the front of the list and the current
|
||||||
// list takes the back of the list.
|
// list takes the back of the list.
|
||||||
UseList result = new()
|
UseList result = new();
|
||||||
{
|
result._count = index + 1;
|
||||||
Count = index + 1,
|
result._capacity = result._count;
|
||||||
};
|
|
||||||
result._capacity = result.Count;
|
|
||||||
result._items = _items;
|
result._items = _items;
|
||||||
|
|
||||||
Count -= result.Count;
|
_count = _count - result._count;
|
||||||
_capacity = Count;
|
_capacity = _count;
|
||||||
_items += result.Count;
|
_items = _items + result._count;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ namespace ARMeilleure.CodeGen.Unwinding
|
|||||||
SetFrame = 1,
|
SetFrame = 1,
|
||||||
AllocStack = 2,
|
AllocStack = 2,
|
||||||
SaveReg = 3,
|
SaveReg = 3,
|
||||||
SaveXmm128 = 4,
|
SaveXmm128 = 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using ARMeilleure.CodeGen.Linking;
|
using ARMeilleure.CodeGen.Linking;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using Microsoft.IO;
|
|
||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -75,9 +74,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
_stream = stream;
|
_stream = stream;
|
||||||
_labels = new Dictionary<Operand, long>();
|
_labels = new Dictionary<Operand, long>();
|
||||||
_jumps = [];
|
_jumps = new List<Jump>();
|
||||||
|
|
||||||
_relocs = relocatable ? [] : null;
|
_relocs = relocatable ? new List<Reloc>() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MarkLabel(Operand label)
|
public void MarkLabel(Operand label)
|
||||||
@@ -800,7 +799,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
JumpIndex = _jumps.Count - 1,
|
JumpIndex = _jumps.Count - 1,
|
||||||
Position = (int)_stream.Position,
|
Position = (int)_stream.Position,
|
||||||
Symbol = source.Symbol,
|
Symbol = source.Symbol
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1050,7 +1049,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
InstructionFlags.Prefix66 => 1,
|
InstructionFlags.Prefix66 => 1,
|
||||||
InstructionFlags.PrefixF3 => 2,
|
InstructionFlags.PrefixF3 => 2,
|
||||||
InstructionFlags.PrefixF2 => 3,
|
InstructionFlags.PrefixF2 => 3,
|
||||||
_ => 0,
|
_ => 0
|
||||||
};
|
};
|
||||||
|
|
||||||
if (src1 != default)
|
if (src1 != default)
|
||||||
@@ -1082,19 +1081,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
switch (opCodeHigh)
|
switch (opCodeHigh)
|
||||||
{
|
{
|
||||||
case 0xf:
|
case 0xf: vexByte1 |= 1; break;
|
||||||
vexByte1 |= 1;
|
case 0xf38: vexByte1 |= 2; break;
|
||||||
break;
|
case 0xf3a: vexByte1 |= 3; break;
|
||||||
case 0xf38:
|
|
||||||
vexByte1 |= 2;
|
|
||||||
break;
|
|
||||||
case 0xf3a:
|
|
||||||
vexByte1 |= 3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default: Debug.Assert(false, $"Failed to VEX encode opcode 0x{opCode:X}."); break;
|
||||||
Debug.Assert(false, $"Failed to VEX encode opcode 0x{opCode:X}.");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vexByte2 |= (rexPrefix & 8) << 4;
|
vexByte2 |= (rexPrefix & 8) << 4;
|
||||||
@@ -1107,17 +1098,17 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((flags & InstructionFlags.Prefix66) != 0)
|
if (flags.HasFlag(InstructionFlags.Prefix66))
|
||||||
{
|
{
|
||||||
WriteByte(0x66);
|
WriteByte(0x66);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & InstructionFlags.PrefixF2) != 0f)
|
if (flags.HasFlag(InstructionFlags.PrefixF2))
|
||||||
{
|
{
|
||||||
WriteByte(0xf2);
|
WriteByte(0xf2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & InstructionFlags.PrefixF3) != 0f)
|
if (flags.HasFlag(InstructionFlags.PrefixF3))
|
||||||
{
|
{
|
||||||
WriteByte(0xf3);
|
WriteByte(0xf3);
|
||||||
}
|
}
|
||||||
@@ -1200,19 +1191,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
switch ((ushort)(opCode >> 8))
|
switch ((ushort)(opCode >> 8))
|
||||||
{
|
{
|
||||||
case 0xf00:
|
case 0xf00: mm = 0b01; break;
|
||||||
mm = 0b01;
|
case 0xf38: mm = 0b10; break;
|
||||||
break;
|
case 0xf3a: mm = 0b11; break;
|
||||||
case 0xf38:
|
|
||||||
mm = 0b10;
|
|
||||||
break;
|
|
||||||
case 0xf3a:
|
|
||||||
mm = 0b11;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default: Debug.Fail($"Failed to EVEX encode opcode 0x{opCode:X}."); break;
|
||||||
Debug.Fail($"Failed to EVEX encode opcode 0x{opCode:X}.");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteByte(
|
WriteByte(
|
||||||
@@ -1234,7 +1217,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
InstructionFlags.Prefix66 => 0b01,
|
InstructionFlags.Prefix66 => 0b01,
|
||||||
InstructionFlags.PrefixF3 => 0b10,
|
InstructionFlags.PrefixF3 => 0b10,
|
||||||
InstructionFlags.PrefixF2 => 0b11,
|
InstructionFlags.PrefixF2 => 0b11,
|
||||||
_ => 0,
|
_ => 0
|
||||||
};
|
};
|
||||||
WriteByte(
|
WriteByte(
|
||||||
(byte)(
|
(byte)(
|
||||||
@@ -1250,19 +1233,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
byte ll = 0b00;
|
byte ll = 0b00;
|
||||||
switch (registerWidth)
|
switch (registerWidth)
|
||||||
{
|
{
|
||||||
case 128:
|
case 128: ll = 0b00; break;
|
||||||
ll = 0b00;
|
case 256: ll = 0b01; break;
|
||||||
break;
|
case 512: ll = 0b10; break;
|
||||||
case 256:
|
|
||||||
ll = 0b01;
|
|
||||||
break;
|
|
||||||
case 512:
|
|
||||||
ll = 0b10;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default: Debug.Fail($"Invalid EVEX vector register width {registerWidth}."); break;
|
||||||
Debug.Fail($"Invalid EVEX vector register width {registerWidth}.");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
// Embedded broadcast in the case of a memory operand
|
// Embedded broadcast in the case of a memory operand
|
||||||
bool bcast = broadcast;
|
bool bcast = broadcast;
|
||||||
@@ -1325,8 +1300,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
public (byte[], RelocInfo) GetCode()
|
public (byte[], RelocInfo) GetCode()
|
||||||
{
|
{
|
||||||
Span<Jump> jumps = CollectionsMarshal.AsSpan(_jumps);
|
var jumps = CollectionsMarshal.AsSpan(_jumps);
|
||||||
Span<Reloc> relocs = CollectionsMarshal.AsSpan(_relocs);
|
var relocs = CollectionsMarshal.AsSpan(_relocs);
|
||||||
|
|
||||||
// Write jump relative offsets.
|
// Write jump relative offsets.
|
||||||
bool modified;
|
bool modified;
|
||||||
@@ -1340,7 +1315,10 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
ref Jump jump = ref jumps[i];
|
ref Jump jump = ref jumps[i];
|
||||||
|
|
||||||
// If jump target not resolved yet, resolve it.
|
// If jump target not resolved yet, resolve it.
|
||||||
jump.JumpTarget ??= _labels[jump.JumpLabel];
|
if (jump.JumpTarget == null)
|
||||||
|
{
|
||||||
|
jump.JumpTarget = _labels[jump.JumpLabel];
|
||||||
|
}
|
||||||
|
|
||||||
long jumpTarget = jump.JumpTarget.Value;
|
long jumpTarget = jump.JumpTarget.Value;
|
||||||
long offset = jumpTarget - jump.JumpPosition;
|
long offset = jumpTarget - jump.JumpPosition;
|
||||||
@@ -1411,13 +1389,13 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
// Write the code, ignoring the dummy bytes after jumps, into a new stream.
|
// Write the code, ignoring the dummy bytes after jumps, into a new stream.
|
||||||
_stream.Seek(0, SeekOrigin.Begin);
|
_stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
using RecyclableMemoryStream codeStream = MemoryStreamManager.Shared.GetStream();
|
using var codeStream = MemoryStreamManager.Shared.GetStream();
|
||||||
Assembler assembler = new(codeStream, HasRelocs);
|
var assembler = new Assembler(codeStream, HasRelocs);
|
||||||
|
|
||||||
bool hasRelocs = HasRelocs;
|
bool hasRelocs = HasRelocs;
|
||||||
int relocIndex = 0;
|
int relocIndex = 0;
|
||||||
int relocOffset = 0;
|
int relocOffset = 0;
|
||||||
RelocEntry[] relocEntries = hasRelocs
|
var relocEntries = hasRelocs
|
||||||
? new RelocEntry[relocs.Length]
|
? new RelocEntry[relocs.Length]
|
||||||
: Array.Empty<RelocEntry>();
|
: Array.Empty<RelocEntry>();
|
||||||
|
|
||||||
@@ -1445,7 +1423,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Span<byte> buffer = new byte[jump.JumpPosition - _stream.Position];
|
Span<byte> buffer = new byte[jump.JumpPosition - _stream.Position];
|
||||||
|
|
||||||
_stream.ReadExactly(buffer);
|
_stream.Read(buffer);
|
||||||
_stream.Seek(ReservedBytesForJump, SeekOrigin.Current);
|
_stream.Seek(ReservedBytesForJump, SeekOrigin.Current);
|
||||||
|
|
||||||
codeStream.Write(buffer);
|
codeStream.Write(buffer);
|
||||||
@@ -1470,15 +1448,15 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
_stream.CopyTo(codeStream);
|
_stream.CopyTo(codeStream);
|
||||||
|
|
||||||
byte[] code = codeStream.ToArray();
|
var code = codeStream.ToArray();
|
||||||
RelocInfo relocInfo = new(relocEntries);
|
var relocInfo = new RelocInfo(relocEntries);
|
||||||
|
|
||||||
return (code, relocInfo);
|
return (code, relocInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool Is64Bits(OperandType type)
|
private static bool Is64Bits(OperandType type)
|
||||||
{
|
{
|
||||||
return type is OperandType.I64 or OperandType.FP64;
|
return type == OperandType.I64 || type == OperandType.FP64;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsImm8(ulong immediate, OperandType type)
|
private static bool IsImm8(ulong immediate, OperandType type)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen.X86
|
namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
@@ -13,7 +12,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
private const int BadOp = 0;
|
private const int BadOp = 0;
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
|
||||||
private enum InstructionFlags
|
private enum InstructionFlags
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
@@ -28,7 +26,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
PrefixMask = 7 << PrefixBit,
|
PrefixMask = 7 << PrefixBit,
|
||||||
Prefix66 = 1 << PrefixBit,
|
Prefix66 = 1 << PrefixBit,
|
||||||
PrefixF3 = 2 << PrefixBit,
|
PrefixF3 = 2 << PrefixBit,
|
||||||
PrefixF2 = 4 << PrefixBit,
|
PrefixF2 = 4 << PrefixBit
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly struct InstructionInfo
|
private readonly struct InstructionInfo
|
||||||
@@ -64,7 +62,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
_instTable = new InstructionInfo[(int)X86Instruction.Count];
|
_instTable = new InstructionInfo[(int)X86Instruction.Count];
|
||||||
|
|
||||||
#pragma warning disable IDE0055 // Disable formatting
|
|
||||||
// Name RM/R RM/I8 RM/I32 R/I64 R/RM Flags
|
// 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.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.Addpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||||
@@ -288,7 +285,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Add(X86Instruction.Xor, new InstructionInfo(0x00000031, 0x06000083, 0x06000081, BadOp, 0x00000033, InstructionFlags.None));
|
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.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.Xorps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex));
|
||||||
#pragma warning restore IDE0055
|
|
||||||
|
|
||||||
static void Add(X86Instruction inst, in InstructionInfo info)
|
static void Add(X86Instruction inst, in InstructionInfo info)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,6 +3,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
enum CallConvName
|
enum CallConvName
|
||||||
{
|
{
|
||||||
SystemV,
|
SystemV,
|
||||||
Windows,
|
Windows
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
if (GetCurrentCallConv() == CallConvName.Windows)
|
if (GetCurrentCallConv() == CallConvName.Windows)
|
||||||
{
|
{
|
||||||
#pragma warning disable IDE0055 // Disable formatting
|
|
||||||
return (1 << (int)X86Register.Rax) |
|
return (1 << (int)X86Register.Rax) |
|
||||||
(1 << (int)X86Register.Rcx) |
|
(1 << (int)X86Register.Rcx) |
|
||||||
(1 << (int)X86Register.Rdx) |
|
(1 << (int)X86Register.Rdx) |
|
||||||
@@ -40,7 +39,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
(1 << (int)X86Register.R9) |
|
(1 << (int)X86Register.R9) |
|
||||||
(1 << (int)X86Register.R10) |
|
(1 << (int)X86Register.R10) |
|
||||||
(1 << (int)X86Register.R11);
|
(1 << (int)X86Register.R11);
|
||||||
#pragma warning restore IDE0055
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,32 +90,22 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
switch (index)
|
switch (index)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0: return X86Register.Rcx;
|
||||||
return X86Register.Rcx;
|
case 1: return X86Register.Rdx;
|
||||||
case 1:
|
case 2: return X86Register.R8;
|
||||||
return X86Register.Rdx;
|
case 3: return X86Register.R9;
|
||||||
case 2:
|
|
||||||
return X86Register.R8;
|
|
||||||
case 3:
|
|
||||||
return X86Register.R9;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* if (GetCurrentCallConv() == CallConvName.SystemV) */
|
else /* if (GetCurrentCallConv() == CallConvName.SystemV) */
|
||||||
{
|
{
|
||||||
switch (index)
|
switch (index)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0: return X86Register.Rdi;
|
||||||
return X86Register.Rdi;
|
case 1: return X86Register.Rsi;
|
||||||
case 1:
|
case 2: return X86Register.Rdx;
|
||||||
return X86Register.Rsi;
|
case 3: return X86Register.Rcx;
|
||||||
case 2:
|
case 4: return X86Register.R8;
|
||||||
return X86Register.Rdx;
|
case 5: return X86Register.R9;
|
||||||
case 3:
|
|
||||||
return X86Register.Rcx;
|
|
||||||
case 4:
|
|
||||||
return X86Register.R8;
|
|
||||||
case 5:
|
|
||||||
return X86Register.R9;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen.X86
|
namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
_instTable = new Action<CodeGenContext, Operation>[EnumUtils.GetCount(typeof(Instruction))];
|
_instTable = new Action<CodeGenContext, Operation>[EnumUtils.GetCount(typeof(Instruction))];
|
||||||
|
|
||||||
#pragma warning disable IDE0055 // Disable formatting
|
|
||||||
Add(Instruction.Add, GenerateAdd);
|
Add(Instruction.Add, GenerateAdd);
|
||||||
Add(Instruction.BitwiseAnd, GenerateBitwiseAnd);
|
Add(Instruction.BitwiseAnd, GenerateBitwiseAnd);
|
||||||
Add(Instruction.BitwiseExclusiveOr, GenerateBitwiseExclusiveOr);
|
Add(Instruction.BitwiseExclusiveOr, GenerateBitwiseExclusiveOr);
|
||||||
@@ -86,7 +85,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Add(Instruction.ZeroExtend16, GenerateZeroExtend16);
|
Add(Instruction.ZeroExtend16, GenerateZeroExtend16);
|
||||||
Add(Instruction.ZeroExtend32, GenerateZeroExtend32);
|
Add(Instruction.ZeroExtend32, GenerateZeroExtend32);
|
||||||
Add(Instruction.ZeroExtend8, GenerateZeroExtend8);
|
Add(Instruction.ZeroExtend8, GenerateZeroExtend8);
|
||||||
#pragma warning restore IDE0055
|
|
||||||
|
|
||||||
static void Add(Instruction inst, Action<CodeGenContext, Operation> func)
|
static void Add(Instruction inst, Action<CodeGenContext, Operation> func)
|
||||||
{
|
{
|
||||||
@@ -175,7 +173,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
// The only blocks which can have 0 successors are exit blocks.
|
// The only blocks which can have 0 successors are exit blocks.
|
||||||
Operation last = block.Operations.Last;
|
Operation last = block.Operations.Last;
|
||||||
|
|
||||||
Debug.Assert(last.Instruction is Instruction.Tailcall or Instruction.Return);
|
Debug.Assert(last.Instruction == Instruction.Tailcall ||
|
||||||
|
last.Instruction == Instruction.Return);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -477,7 +476,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Debug.Assert(HardwareCapabilities.SupportsVexEncoding);
|
Debug.Assert(HardwareCapabilities.SupportsVexEncoding);
|
||||||
|
|
||||||
Debug.Assert(dest.Kind == OperandKind.Register && src1.Kind == OperandKind.Register && src2.Kind == OperandKind.Register);
|
Debug.Assert(dest.Kind == OperandKind.Register && src1.Kind == OperandKind.Register && src2.Kind == OperandKind.Register);
|
||||||
Debug.Assert(src3.Kind is OperandKind.Register or OperandKind.Memory);
|
Debug.Assert(src3.Kind == OperandKind.Register || src3.Kind == OperandKind.Memory);
|
||||||
|
|
||||||
EnsureSameType(dest, src1, src2, src3);
|
EnsureSameType(dest, src1, src2, src3);
|
||||||
Debug.Assert(dest.Type == OperandType.V128);
|
Debug.Assert(dest.Type == OperandType.V128);
|
||||||
@@ -622,7 +621,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||||
|
|
||||||
X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition();
|
var cond = ((Comparison)comp.AsInt32()).ToX86Condition();
|
||||||
|
|
||||||
GenerateCompareCommon(context, operation);
|
GenerateCompareCommon(context, operation);
|
||||||
|
|
||||||
@@ -660,7 +659,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Debug.Assert(dest.Type == OperandType.I32);
|
Debug.Assert(dest.Type == OperandType.I32);
|
||||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||||
|
|
||||||
X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition();
|
var cond = ((Comparison)comp.AsInt32()).ToX86Condition();
|
||||||
|
|
||||||
GenerateCompareCommon(context, operation);
|
GenerateCompareCommon(context, operation);
|
||||||
|
|
||||||
@@ -787,7 +786,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Operand dest = operation.Destination;
|
Operand dest = operation.Destination;
|
||||||
Operand source = operation.GetSource(0);
|
Operand source = operation.GetSource(0);
|
||||||
|
|
||||||
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64);
|
Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64);
|
||||||
|
|
||||||
if (dest.Type == OperandType.FP32)
|
if (dest.Type == OperandType.FP32)
|
||||||
{
|
{
|
||||||
@@ -1295,11 +1294,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const byte Mask = 0b01_00_11_10;
|
const byte mask = 0b01_00_11_10;
|
||||||
|
|
||||||
context.Assembler.Pshufd(src1, src1, Mask);
|
context.Assembler.Pshufd(src1, src1, mask);
|
||||||
context.Assembler.Movq (dest, src1);
|
context.Assembler.Movq (dest, src1);
|
||||||
context.Assembler.Pshufd(src1, src1, Mask);
|
context.Assembler.Pshufd(src1, src1, mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1614,25 +1613,13 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
switch (value.Type)
|
switch (value.Type)
|
||||||
{
|
{
|
||||||
case OperandType.I32:
|
case OperandType.I32: context.Assembler.Mov (value, address, OperandType.I32); break;
|
||||||
context.Assembler.Mov(value, address, OperandType.I32);
|
case OperandType.I64: context.Assembler.Mov (value, address, OperandType.I64); break;
|
||||||
break;
|
case OperandType.FP32: context.Assembler.Movd (value, address); break;
|
||||||
case OperandType.I64:
|
case OperandType.FP64: context.Assembler.Movq (value, address); break;
|
||||||
context.Assembler.Mov(value, address, OperandType.I64);
|
case OperandType.V128: context.Assembler.Movdqu(value, address); break;
|
||||||
break;
|
|
||||||
case OperandType.FP32:
|
|
||||||
context.Assembler.Movd(value, address);
|
|
||||||
break;
|
|
||||||
case OperandType.FP64:
|
|
||||||
context.Assembler.Movq(value, address);
|
|
||||||
break;
|
|
||||||
case OperandType.V128:
|
|
||||||
context.Assembler.Movdqu(value, address);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default: Debug.Assert(false); break;
|
||||||
Debug.Assert(false);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1640,25 +1627,13 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
switch (value.Type)
|
switch (value.Type)
|
||||||
{
|
{
|
||||||
case OperandType.I32:
|
case OperandType.I32: context.Assembler.Mov (address, value, OperandType.I32); break;
|
||||||
context.Assembler.Mov(address, value, OperandType.I32);
|
case OperandType.I64: context.Assembler.Mov (address, value, OperandType.I64); break;
|
||||||
break;
|
case OperandType.FP32: context.Assembler.Movd (address, value); break;
|
||||||
case OperandType.I64:
|
case OperandType.FP64: context.Assembler.Movq (address, value); break;
|
||||||
context.Assembler.Mov(address, value, OperandType.I64);
|
case OperandType.V128: context.Assembler.Movdqu(address, value); break;
|
||||||
break;
|
|
||||||
case OperandType.FP32:
|
|
||||||
context.Assembler.Movd(address, value);
|
|
||||||
break;
|
|
||||||
case OperandType.FP64:
|
|
||||||
context.Assembler.Movq(address, value);
|
|
||||||
break;
|
|
||||||
case OperandType.V128:
|
|
||||||
context.Assembler.Movdqu(address, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default: Debug.Assert(false); break;
|
||||||
Debug.Assert(false);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1722,7 +1697,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(op1.Kind is OperandKind.Register or OperandKind.Memory);
|
Debug.Assert(op1.Kind == OperandKind.Register || op1.Kind == OperandKind.Memory);
|
||||||
Debug.Assert(op1.Kind == op2.Kind);
|
Debug.Assert(op1.Kind == op2.Kind);
|
||||||
Debug.Assert(op1.Value == op2.Value);
|
Debug.Assert(op1.Value == op2.Value);
|
||||||
}
|
}
|
||||||
@@ -1747,7 +1722,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
private static UnwindInfo WritePrologue(CodeGenContext context)
|
private static UnwindInfo WritePrologue(CodeGenContext context)
|
||||||
{
|
{
|
||||||
List<UnwindPushEntry> pushEntries = [];
|
List<UnwindPushEntry> pushEntries = new List<UnwindPushEntry>();
|
||||||
|
|
||||||
Operand rsp = Register(X86Register.Rsp);
|
Operand rsp = Register(X86Register.Rsp);
|
||||||
|
|
||||||
@@ -1852,9 +1827,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
// that the OS will map all pages that we'll use. We do that by
|
// that the OS will map all pages that we'll use. We do that by
|
||||||
// doing a dummy read on those pages, forcing a page fault and
|
// doing a dummy read on those pages, forcing a page fault and
|
||||||
// the OS to map them. If they are already mapped, nothing happens.
|
// the OS to map them. If they are already mapped, nothing happens.
|
||||||
const int PageMask = PageSize - 1;
|
const int pageMask = PageSize - 1;
|
||||||
|
|
||||||
size = (size + PageMask) & ~PageMask;
|
size = (size + pageMask) & ~pageMask;
|
||||||
|
|
||||||
Operand rsp = Register(X86Register.Rsp);
|
Operand rsp = Register(X86Register.Rsp);
|
||||||
Operand temp = Register(CallingConvention.GetIntReturnRegister());
|
Operand temp = Register(CallingConvention.GetIntReturnRegister());
|
||||||
|
|||||||
@@ -40,20 +40,20 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadOnlySpan<byte> asmGetXcr0 =
|
ReadOnlySpan<byte> asmGetXcr0 = new byte[]
|
||||||
[
|
{
|
||||||
0x31, 0xc9, // xor ecx, ecx
|
0x31, 0xc9, // xor ecx, ecx
|
||||||
0xf, 0x01, 0xd0, // xgetbv
|
0xf, 0x01, 0xd0, // xgetbv
|
||||||
0xc3 // ret
|
0xc3, // ret
|
||||||
];
|
};
|
||||||
|
|
||||||
using MemoryBlock memGetXcr0 = new((ulong)asmGetXcr0.Length);
|
using MemoryBlock memGetXcr0 = new MemoryBlock((ulong)asmGetXcr0.Length);
|
||||||
|
|
||||||
memGetXcr0.Write(0, asmGetXcr0);
|
memGetXcr0.Write(0, asmGetXcr0);
|
||||||
|
|
||||||
memGetXcr0.Reprotect(0, (ulong)asmGetXcr0.Length, MemoryPermission.ReadAndExecute);
|
memGetXcr0.Reprotect(0, (ulong)asmGetXcr0.Length, MemoryPermission.ReadAndExecute);
|
||||||
|
|
||||||
GetXcr0 fGetXcr0 = Marshal.GetDelegateForFunctionPointer<GetXcr0>(memGetXcr0.Pointer);
|
var fGetXcr0 = Marshal.GetDelegateForFunctionPointer<GetXcr0>(memGetXcr0.Pointer);
|
||||||
|
|
||||||
return fGetXcr0();
|
return fGetXcr0();
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
public enum FeatureFlags1Edx
|
public enum FeatureFlags1Edx
|
||||||
{
|
{
|
||||||
Sse = 1 << 25,
|
Sse = 1 << 25,
|
||||||
Sse2 = 1 << 26,
|
Sse2 = 1 << 26
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
@@ -79,7 +79,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Xsave = 1 << 26,
|
Xsave = 1 << 26,
|
||||||
Osxsave = 1 << 27,
|
Osxsave = 1 << 27,
|
||||||
Avx = 1 << 28,
|
Avx = 1 << 28,
|
||||||
F16c = 1 << 29,
|
F16c = 1 << 29
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
@@ -90,7 +90,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Avx512dq = 1 << 17,
|
Avx512dq = 1 << 17,
|
||||||
Sha = 1 << 29,
|
Sha = 1 << 29,
|
||||||
Avx512bw = 1 << 30,
|
Avx512bw = 1 << 30,
|
||||||
Avx512vl = 1 << 31,
|
Avx512vl = 1 << 31
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
@@ -106,7 +106,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
YmmHi128 = 1 << 2,
|
YmmHi128 = 1 << 2,
|
||||||
Opmask = 1 << 5,
|
Opmask = 1 << 5,
|
||||||
ZmmHi256 = 1 << 6,
|
ZmmHi256 = 1 << 6,
|
||||||
Hi16Zmm = 1 << 7,
|
Hi16Zmm = 1 << 7
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FeatureFlags1Edx FeatureInfo1Edx { get; }
|
public static FeatureFlags1Edx FeatureInfo1Edx { get; }
|
||||||
|
|||||||
@@ -5,13 +5,12 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
static class IntrinsicTable
|
static class IntrinsicTable
|
||||||
{
|
{
|
||||||
private static readonly IntrinsicInfo[] _intrinTable;
|
private static IntrinsicInfo[] _intrinTable;
|
||||||
|
|
||||||
static IntrinsicTable()
|
static IntrinsicTable()
|
||||||
{
|
{
|
||||||
_intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))];
|
_intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))];
|
||||||
|
|
||||||
#pragma warning disable IDE0055 // Disable formatting
|
|
||||||
Add(Intrinsic.X86Addpd, new IntrinsicInfo(X86Instruction.Addpd, IntrinsicType.Binary));
|
Add(Intrinsic.X86Addpd, new IntrinsicInfo(X86Instruction.Addpd, IntrinsicType.Binary));
|
||||||
Add(Intrinsic.X86Addps, new IntrinsicInfo(X86Instruction.Addps, IntrinsicType.Binary));
|
Add(Intrinsic.X86Addps, new IntrinsicInfo(X86Instruction.Addps, IntrinsicType.Binary));
|
||||||
Add(Intrinsic.X86Addsd, new IntrinsicInfo(X86Instruction.Addsd, IntrinsicType.Binary));
|
Add(Intrinsic.X86Addsd, new IntrinsicInfo(X86Instruction.Addsd, IntrinsicType.Binary));
|
||||||
@@ -186,7 +185,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Add(Intrinsic.X86Vpternlogd, new IntrinsicInfo(X86Instruction.Vpternlogd, IntrinsicType.TernaryImm));
|
Add(Intrinsic.X86Vpternlogd, new IntrinsicInfo(X86Instruction.Vpternlogd, IntrinsicType.TernaryImm));
|
||||||
Add(Intrinsic.X86Xorpd, new IntrinsicInfo(X86Instruction.Xorpd, IntrinsicType.Binary));
|
Add(Intrinsic.X86Xorpd, new IntrinsicInfo(X86Instruction.Xorpd, IntrinsicType.Binary));
|
||||||
Add(Intrinsic.X86Xorps, new IntrinsicInfo(X86Instruction.Xorps, IntrinsicType.Binary));
|
Add(Intrinsic.X86Xorps, new IntrinsicInfo(X86Instruction.Xorps, IntrinsicType.Binary));
|
||||||
#pragma warning restore IDE0055
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Add(Intrinsic intrin, IntrinsicInfo info)
|
private static void Add(Intrinsic intrin, IntrinsicInfo info)
|
||||||
|
|||||||
@@ -13,6 +13,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Crc32,
|
Crc32,
|
||||||
Ternary,
|
Ternary,
|
||||||
TernaryImm,
|
TernaryImm,
|
||||||
Fma,
|
Fma
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen.X86
|
namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
@@ -10,6 +10,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Rlo = 1 << 13, // Round Mode low bit.
|
Rlo = 1 << 13, // Round Mode low bit.
|
||||||
Um = 1 << 11, // Underflow Mask.
|
Um = 1 << 11, // Underflow Mask.
|
||||||
Dm = 1 << 8, // Denormal Mask.
|
Dm = 1 << 8, // Denormal Mask.
|
||||||
Daz = 1 << 6, // Denormals Are Zero.
|
Daz = 1 << 6 // Denormals Are Zero.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,11 +104,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
case Instruction.Tailcall:
|
case Instruction.Tailcall:
|
||||||
if (callConv == CallConvName.Windows)
|
if (callConv == CallConvName.Windows)
|
||||||
{
|
{
|
||||||
PreAllocatorWindows.InsertTailcallCopies(block.Operations, node);
|
PreAllocatorWindows.InsertTailcallCopies(block.Operations, stackAlloc, node);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PreAllocatorSystemV.InsertTailcallCopies(block.Operations, node);
|
PreAllocatorSystemV.InsertTailcallCopies(block.Operations, stackAlloc, node);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -124,13 +124,13 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
int stackOffset = stackAlloc.Allocate(OperandType.I32);
|
int stackOffset = stackAlloc.Allocate(OperandType.I32);
|
||||||
|
|
||||||
node.SetSources([Const(stackOffset), node.GetSource(0)]);
|
node.SetSources(new Operand[] { Const(stackOffset), node.GetSource(0) });
|
||||||
}
|
}
|
||||||
else if (node.Intrinsic == Intrinsic.X86Stmxcsr)
|
else if (node.Intrinsic == Intrinsic.X86Stmxcsr)
|
||||||
{
|
{
|
||||||
int stackOffset = stackAlloc.Allocate(OperandType.I32);
|
int stackOffset = stackAlloc.Allocate(OperandType.I32);
|
||||||
|
|
||||||
node.SetSources([Const(stackOffset)]);
|
node.SetSources(new Operand[] { Const(stackOffset) });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -177,7 +177,10 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
src2 = node.GetSource(1);
|
src2 = node.GetSource(1);
|
||||||
|
|
||||||
(src2, src1) = (src1, src2);
|
Operand temp = src1;
|
||||||
|
|
||||||
|
src1 = src2;
|
||||||
|
src2 = temp;
|
||||||
|
|
||||||
node.SetSource(0, src1);
|
node.SetSource(0, src1);
|
||||||
node.SetSource(1, src2);
|
node.SetSource(1, src2);
|
||||||
@@ -253,8 +256,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, rax));
|
node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, rax));
|
||||||
nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, rdx, Const(1)));
|
nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, rdx, Const(1)));
|
||||||
|
|
||||||
operation.SetDestinations([rdx, rax]);
|
operation.SetDestinations(new Operand[] { rdx, rax });
|
||||||
operation.SetSources([operation.GetSource(0), rdx, rax, rcx, rbx]);
|
operation.SetSources(new Operand[] { operation.GetSource(0), rdx, rax, rcx, rbx });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -274,7 +277,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
nodes.AddBefore(node, Operation(Instruction.Copy, temp, newValue));
|
nodes.AddBefore(node, Operation(Instruction.Copy, temp, newValue));
|
||||||
|
|
||||||
node.SetSources([node.GetSource(0), rax, temp]);
|
node.SetSources(new Operand[] { node.GetSource(0), rax, temp });
|
||||||
|
|
||||||
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax));
|
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax));
|
||||||
|
|
||||||
@@ -303,7 +306,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax));
|
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax));
|
||||||
|
|
||||||
node.SetSources([rdx, rax, node.GetSource(1)]);
|
node.SetSources(new Operand[] { rdx, rax, node.GetSource(1) });
|
||||||
node.Destination = rax;
|
node.Destination = rax;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,9 +315,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
case Instruction.Extended:
|
case Instruction.Extended:
|
||||||
{
|
{
|
||||||
bool isBlend = node.Intrinsic is Intrinsic.X86Blendvpd
|
bool isBlend = node.Intrinsic == Intrinsic.X86Blendvpd ||
|
||||||
or Intrinsic.X86Blendvps
|
node.Intrinsic == Intrinsic.X86Blendvps ||
|
||||||
or Intrinsic.X86Pblendvb;
|
node.Intrinsic == Intrinsic.X86Pblendvb;
|
||||||
|
|
||||||
// BLENDVPD, BLENDVPS, PBLENDVB last operand is always implied to be XMM0 when VEX is not supported.
|
// BLENDVPD, BLENDVPS, PBLENDVB last operand is always implied to be XMM0 when VEX is not supported.
|
||||||
// SHA256RNDS2 always has an implied XMM0 as a last operand.
|
// SHA256RNDS2 always has an implied XMM0 as a last operand.
|
||||||
@@ -348,7 +351,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rdx));
|
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rdx));
|
||||||
|
|
||||||
node.SetDestinations([rdx, rax]);
|
node.SetDestinations(new Operand[] { rdx, rax });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -470,7 +473,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Operand zex = Local(OperandType.I64);
|
Operand zex = Local(OperandType.I64);
|
||||||
|
|
||||||
node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend32, zex, source));
|
node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend32, zex, source));
|
||||||
nodes.AddAfter(node, Operation(Instruction.ConvertToFP, dest, zex));
|
node = nodes.AddAfter(node, Operation(Instruction.ConvertToFP, dest, zex));
|
||||||
}
|
}
|
||||||
else /* if (source.Type == OperandType.I64) */
|
else /* if (source.Type == OperandType.I64) */
|
||||||
{
|
{
|
||||||
@@ -513,8 +516,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Operand dest = node.Destination;
|
Operand dest = node.Destination;
|
||||||
Operand source = node.GetSource(0);
|
Operand source = node.GetSource(0);
|
||||||
|
|
||||||
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64,
|
Debug.Assert(dest.Type == OperandType.FP32 ||
|
||||||
$"Invalid destination type \"{dest.Type}\".");
|
dest.Type == OperandType.FP64, $"Invalid destination type \"{dest.Type}\".");
|
||||||
|
|
||||||
Operation currentNode = node;
|
Operation currentNode = node;
|
||||||
|
|
||||||
@@ -706,11 +709,16 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
private static bool HasConstSrc1(Instruction inst)
|
private static bool HasConstSrc1(Instruction inst)
|
||||||
{
|
{
|
||||||
return inst switch
|
switch (inst)
|
||||||
{
|
{
|
||||||
Instruction.Copy or Instruction.LoadArgument or Instruction.Spill or Instruction.SpillArg => true,
|
case Instruction.Copy:
|
||||||
_ => false,
|
case Instruction.LoadArgument:
|
||||||
};
|
case Instruction.Spill:
|
||||||
|
case Instruction.SpillArg:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool HasConstSrc2(Instruction inst)
|
private static bool HasConstSrc2(Instruction inst)
|
||||||
@@ -759,9 +767,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||||
|
|
||||||
Comparison compType = (Comparison)comp.AsInt32();
|
var compType = (Comparison)comp.AsInt32();
|
||||||
|
|
||||||
return compType is Comparison.Equal or Comparison.NotEqual;
|
return compType == Comparison.Equal || compType == Comparison.NotEqual;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System;
|
using System;
|
||||||
@@ -14,10 +15,10 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
Operand dest = node.Destination;
|
Operand dest = node.Destination;
|
||||||
|
|
||||||
List<Operand> sources =
|
List<Operand> sources = new List<Operand>
|
||||||
[
|
{
|
||||||
node.GetSource(0)
|
node.GetSource(0)
|
||||||
];
|
};
|
||||||
|
|
||||||
int argsCount = node.SourcesCount - 1;
|
int argsCount = node.SourcesCount - 1;
|
||||||
|
|
||||||
@@ -115,12 +116,12 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void InsertTailcallCopies(IntrusiveList<Operation> nodes, Operation node)
|
public static void InsertTailcallCopies(IntrusiveList<Operation> nodes, StackAllocator stackAlloc, Operation node)
|
||||||
|
{
|
||||||
|
List<Operand> sources = new List<Operand>
|
||||||
{
|
{
|
||||||
List<Operand> sources =
|
|
||||||
[
|
|
||||||
node.GetSource(0)
|
node.GetSource(0)
|
||||||
];
|
};
|
||||||
|
|
||||||
int argsCount = node.SourcesCount - 1;
|
int argsCount = node.SourcesCount - 1;
|
||||||
|
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
node.SetSources(sources);
|
node.SetSources(sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void InsertTailcallCopies(IntrusiveList<Operation> nodes, Operation node)
|
public static void InsertTailcallCopies(IntrusiveList<Operation> nodes, StackAllocator stackAlloc, Operation node)
|
||||||
{
|
{
|
||||||
int argsCount = node.SourcesCount - 1;
|
int argsCount = node.SourcesCount - 1;
|
||||||
int maxArgs = CallingConvention.GetArgumentsOnRegsCount();
|
int maxArgs = CallingConvention.GetArgumentsOnRegsCount();
|
||||||
@@ -321,7 +321,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
nodes.AddBefore(node, retCopyOp);
|
nodes.AddBefore(node, retCopyOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
node.SetSources([]);
|
node.SetSources(Array.Empty<Operand>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Less = 0xc,
|
Less = 0xc,
|
||||||
GreaterOrEqual = 0xd,
|
GreaterOrEqual = 0xd,
|
||||||
LessOrEqual = 0xe,
|
LessOrEqual = 0xe,
|
||||||
Greater = 0xf,
|
Greater = 0xf
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ComparisonX86Extensions
|
static class ComparisonX86Extensions
|
||||||
@@ -29,7 +29,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
return comp switch
|
return comp switch
|
||||||
{
|
{
|
||||||
#pragma warning disable IDE0055 // Disable formatting
|
|
||||||
Comparison.Equal => X86Condition.Equal,
|
Comparison.Equal => X86Condition.Equal,
|
||||||
Comparison.NotEqual => X86Condition.NotEqual,
|
Comparison.NotEqual => X86Condition.NotEqual,
|
||||||
Comparison.Greater => X86Condition.Greater,
|
Comparison.Greater => X86Condition.Greater,
|
||||||
@@ -40,9 +39,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Comparison.Less => X86Condition.Less,
|
Comparison.Less => X86Condition.Less,
|
||||||
Comparison.GreaterOrEqualUI => X86Condition.AboveOrEqual,
|
Comparison.GreaterOrEqualUI => X86Condition.AboveOrEqual,
|
||||||
Comparison.LessUI => X86Condition.Below,
|
Comparison.LessUI => X86Condition.Below,
|
||||||
#pragma warning restore IDE0055
|
|
||||||
|
|
||||||
_ => throw new ArgumentException(null, nameof(comp)),
|
_ => throw new ArgumentException(null, nameof(comp))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -226,6 +226,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Xorpd,
|
Xorpd,
|
||||||
Xorps,
|
Xorps,
|
||||||
|
|
||||||
Count,
|
Count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using ARMeilleure.CodeGen.Optimizations;
|
using ARMeilleure.CodeGen.Optimizations;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -13,13 +13,13 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
public static void RunPass(ControlFlowGraph cfg)
|
public static void RunPass(ControlFlowGraph cfg)
|
||||||
{
|
{
|
||||||
Dictionary<ulong, Operand> constants = new();
|
var constants = new Dictionary<ulong, Operand>();
|
||||||
|
|
||||||
Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source)
|
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
|
// 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).
|
// to avoid overflow of the counts field (that is limited to 16 bits).
|
||||||
if (!constants.TryGetValue(source.Value, out Operand constant) || constant.UsesCount > MaxConstantUses)
|
if (!constants.TryGetValue(source.Value, out var constant) || constant.UsesCount > MaxConstantUses)
|
||||||
{
|
{
|
||||||
constant = Local(source.Type);
|
constant = Local(source.Type);
|
||||||
|
|
||||||
@@ -215,7 +215,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
1 => Multiplier.x2,
|
1 => Multiplier.x2,
|
||||||
2 => Multiplier.x4,
|
2 => Multiplier.x4,
|
||||||
3 => Multiplier.x8,
|
3 => Multiplier.x8,
|
||||||
_ => Multiplier.x1,
|
_ => Multiplier.x1
|
||||||
};
|
};
|
||||||
|
|
||||||
baseOp = indexOnSrc2 ? src1 : src2;
|
baseOp = indexOnSrc2 ? src1 : src2;
|
||||||
@@ -248,12 +248,12 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
private static bool IsMemoryLoadOrStore(Instruction inst)
|
private static bool IsMemoryLoadOrStore(Instruction inst)
|
||||||
{
|
{
|
||||||
return inst is Instruction.Load
|
return inst == Instruction.Load ||
|
||||||
or Instruction.Load16
|
inst == Instruction.Load16 ||
|
||||||
or Instruction.Load8
|
inst == Instruction.Load8 ||
|
||||||
or Instruction.Store
|
inst == Instruction.Store ||
|
||||||
or Instruction.Store16
|
inst == Instruction.Store16 ||
|
||||||
or Instruction.Store8;
|
inst == Instruction.Store8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen.X86
|
namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
|
||||||
enum X86Register
|
enum X86Register
|
||||||
{
|
{
|
||||||
Invalid = -1,
|
Invalid = -1,
|
||||||
@@ -39,6 +36,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Xmm12 = 12,
|
Xmm12 = 12,
|
||||||
Xmm13 = 13,
|
Xmm13 = 13,
|
||||||
Xmm14 = 14,
|
Xmm14 = 14,
|
||||||
Xmm15 = 15,
|
Xmm15 = 15
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,252 @@
|
|||||||
|
using ARMeilleure.Diagnostics;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace ARMeilleure.Common
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a table of guest address to a value.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEntry">Type of the value</typeparam>
|
||||||
|
unsafe class AddressTable<TEntry> : IDisposable where TEntry : unmanaged
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a level in an <see cref="AddressTable{TEntry}"/>.
|
||||||
|
/// </summary>
|
||||||
|
public readonly struct Level
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the index of the <see cref="Level"/> in the guest address.
|
||||||
|
/// </summary>
|
||||||
|
public int Index { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the length of the <see cref="Level"/> in the guest address.
|
||||||
|
/// </summary>
|
||||||
|
public int Length { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the mask which masks the bits used by the <see cref="Level"/>.
|
||||||
|
/// </summary>
|
||||||
|
public ulong Mask => ((1ul << Length) - 1) << Index;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Level"/> structure with the specified
|
||||||
|
/// <paramref name="index"/> and <paramref name="length"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="index">Index of the <see cref="Level"/></param>
|
||||||
|
/// <param name="length">Length of the <see cref="Level"/></param>
|
||||||
|
public Level(int index, int length)
|
||||||
|
{
|
||||||
|
(Index, Length) = (index, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value of the <see cref="Level"/> from the specified guest <paramref name="address"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Guest address</param>
|
||||||
|
/// <returns>Value of the <see cref="Level"/> from the specified guest <paramref name="address"/></returns>
|
||||||
|
public int GetValue(ulong address)
|
||||||
|
{
|
||||||
|
return (int)((address & Mask) >> Index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _disposed;
|
||||||
|
private TEntry** _table;
|
||||||
|
private readonly List<IntPtr> _pages;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the bits used by the <see cref="Levels"/> of the <see cref="AddressTable{TEntry}"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
public ulong Mask { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="Level"/>s used by the <see cref="AddressTable{TEntry}"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
public Level[] Levels { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the default fill value of newly created leaf pages.
|
||||||
|
/// </summary>
|
||||||
|
public TEntry Fill { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the base address of the <see cref="EntryTable{TEntry}"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
|
||||||
|
public IntPtr Base
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
|
lock (_pages)
|
||||||
|
{
|
||||||
|
return (IntPtr)GetRootPage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a new instance of the <see cref="AddressTable{TEntry}"/> class with the specified list of
|
||||||
|
/// <see cref="Level"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="levels"/> is null</exception>
|
||||||
|
/// <exception cref="ArgumentException">Length of <paramref name="levels"/> is less than 2</exception>
|
||||||
|
public AddressTable(Level[] levels)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(levels);
|
||||||
|
|
||||||
|
if (levels.Length < 2)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Table must be at least 2 levels deep.", nameof(levels));
|
||||||
|
}
|
||||||
|
|
||||||
|
_pages = new List<IntPtr>(capacity: 16);
|
||||||
|
|
||||||
|
Levels = levels;
|
||||||
|
Mask = 0;
|
||||||
|
|
||||||
|
foreach (var level in Levels)
|
||||||
|
{
|
||||||
|
Mask |= level.Mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if the specified <paramref name="address"/> is in the range of the
|
||||||
|
/// <see cref="AddressTable{TEntry}"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Guest address</param>
|
||||||
|
/// <returns><see langword="true"/> if is valid; otherwise <see langword="false"/></returns>
|
||||||
|
public bool IsValid(ulong address)
|
||||||
|
{
|
||||||
|
return (address & ~Mask) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a reference to the value at the specified guest <paramref name="address"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Guest address</param>
|
||||||
|
/// <returns>Reference to the value at the specified guest <paramref name="address"/></returns>
|
||||||
|
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
|
||||||
|
/// <exception cref="ArgumentException"><paramref name="address"/> is not mapped</exception>
|
||||||
|
public ref TEntry GetValue(ulong address)
|
||||||
|
{
|
||||||
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
|
if (!IsValid(address))
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Address 0x{address:X} is not mapped onto the table.", nameof(address));
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (_pages)
|
||||||
|
{
|
||||||
|
return ref GetPage(address)[Levels[^1].GetValue(address)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the leaf page for the specified guest <paramref name="address"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Guest address</param>
|
||||||
|
/// <returns>Leaf page for the specified guest <paramref name="address"/></returns>
|
||||||
|
private TEntry* GetPage(ulong address)
|
||||||
|
{
|
||||||
|
TEntry** page = GetRootPage();
|
||||||
|
|
||||||
|
for (int i = 0; i < Levels.Length - 1; i++)
|
||||||
|
{
|
||||||
|
ref Level level = ref Levels[i];
|
||||||
|
ref TEntry* nextPage = ref page[level.GetValue(address)];
|
||||||
|
|
||||||
|
if (nextPage == null)
|
||||||
|
{
|
||||||
|
ref Level nextLevel = ref Levels[i + 1];
|
||||||
|
|
||||||
|
nextPage = i == Levels.Length - 2 ?
|
||||||
|
(TEntry*)Allocate(1 << nextLevel.Length, Fill, leaf: true) :
|
||||||
|
(TEntry*)Allocate(1 << nextLevel.Length, IntPtr.Zero, leaf: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
page = (TEntry**)nextPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (TEntry*)page;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Lazily initialize and get the root page of the <see cref="AddressTable{TEntry}"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Root page of the <see cref="AddressTable{TEntry}"/></returns>
|
||||||
|
private TEntry** GetRootPage()
|
||||||
|
{
|
||||||
|
if (_table == null)
|
||||||
|
{
|
||||||
|
_table = (TEntry**)Allocate(1 << Levels[0].Length, fill: IntPtr.Zero, leaf: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allocates a block of memory of the specified type and length.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of elements</typeparam>
|
||||||
|
/// <param name="length">Number of elements</param>
|
||||||
|
/// <param name="fill">Fill value</param>
|
||||||
|
/// <param name="leaf"><see langword="true"/> if leaf; otherwise <see langword="false"/></param>
|
||||||
|
/// <returns>Allocated block</returns>
|
||||||
|
private IntPtr Allocate<T>(int length, T fill, bool leaf) where T : unmanaged
|
||||||
|
{
|
||||||
|
var size = sizeof(T) * length;
|
||||||
|
var page = (IntPtr)NativeAllocator.Instance.Allocate((uint)size);
|
||||||
|
var span = new Span<T>((void*)page, length);
|
||||||
|
|
||||||
|
span.Fill(fill);
|
||||||
|
|
||||||
|
_pages.Add(page);
|
||||||
|
|
||||||
|
TranslatorEventSource.Log.AddressTableAllocated(size, leaf);
|
||||||
|
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases all resources used by the <see cref="AddressTable{TEntry}"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases all unmanaged and optionally managed resources used by the <see cref="AddressTable{TEntry}"/>
|
||||||
|
/// instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing"><see langword="true"/> to dispose managed resources also; otherwise just unmanaged resouces</param>
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!_disposed)
|
||||||
|
{
|
||||||
|
foreach (var page in _pages)
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Frees resources used by the <see cref="AddressTable{TEntry}"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
~AddressTable()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
namespace ARMeilleure.Common
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a level in an <see cref="IAddressTable{TEntry}"/>.
|
|
||||||
/// </summary>
|
|
||||||
public readonly struct AddressTableLevel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the index of the <see cref="Level"/> in the guest address.
|
|
||||||
/// </summary>
|
|
||||||
public int Index { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the length of the <see cref="AddressTableLevel"/> in the guest address.
|
|
||||||
/// </summary>
|
|
||||||
public int Length { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the mask which masks the bits used by the <see cref="AddressTableLevel"/>.
|
|
||||||
/// </summary>
|
|
||||||
public ulong Mask => ((1ul << Length) - 1) << Index;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="AddressTableLevel"/> structure with the specified
|
|
||||||
/// <paramref name="index"/> and <paramref name="length"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="index">Index of the <see cref="AddressTableLevel"/></param>
|
|
||||||
/// <param name="length">Length of the <see cref="AddressTableLevel"/></param>
|
|
||||||
public AddressTableLevel(int index, int length)
|
|
||||||
{
|
|
||||||
(Index, Length) = (index, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the value of the <see cref="AddressTableLevel"/> from the specified guest <paramref name="address"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="address">Guest address</param>
|
|
||||||
/// <returns>Value of the <see cref="AddressTableLevel"/> from the specified guest <paramref name="address"/></returns>
|
|
||||||
public long GetValue(ulong address)
|
|
||||||
{
|
|
||||||
return (long)((address & Mask) >> Index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
namespace ARMeilleure.Common
|
|
||||||
{
|
|
||||||
public static class AddressTablePresets
|
|
||||||
{
|
|
||||||
private static readonly AddressTableLevel[] _levels64Bit =
|
|
||||||
[
|
|
||||||
new(31, 17),
|
|
||||||
new(23, 8),
|
|
||||||
new(15, 8),
|
|
||||||
new( 7, 8),
|
|
||||||
new( 2, 5)
|
|
||||||
];
|
|
||||||
|
|
||||||
private static readonly AddressTableLevel[] _levels32Bit =
|
|
||||||
[
|
|
||||||
new(31, 17),
|
|
||||||
new(23, 8),
|
|
||||||
new(15, 8),
|
|
||||||
new( 7, 8),
|
|
||||||
new( 1, 6)
|
|
||||||
];
|
|
||||||
|
|
||||||
private static readonly AddressTableLevel[] _levels64BitSparseTiny =
|
|
||||||
[
|
|
||||||
new( 11, 28),
|
|
||||||
new( 2, 9)
|
|
||||||
];
|
|
||||||
|
|
||||||
private static readonly AddressTableLevel[] _levels32BitSparseTiny =
|
|
||||||
[
|
|
||||||
new( 10, 22),
|
|
||||||
new( 1, 9)
|
|
||||||
];
|
|
||||||
|
|
||||||
private static readonly AddressTableLevel[] _levels64BitSparseGiant =
|
|
||||||
[
|
|
||||||
new( 38, 1),
|
|
||||||
new( 2, 36)
|
|
||||||
];
|
|
||||||
|
|
||||||
private static readonly AddressTableLevel[] _levels32BitSparseGiant =
|
|
||||||
[
|
|
||||||
new( 31, 1),
|
|
||||||
new( 1, 30)
|
|
||||||
];
|
|
||||||
|
|
||||||
//high power will run worse on DDR3 systems and some DDR4 systems due to the higher ram utilization
|
|
||||||
//low power will never run worse than non-sparse, but for most systems it won't be necessary
|
|
||||||
//high power is always used, but I've left low power in here for future reference
|
|
||||||
public static AddressTableLevel[] GetArmPreset(bool for64Bits, bool sparse, bool lowPower = false)
|
|
||||||
{
|
|
||||||
if (sparse)
|
|
||||||
{
|
|
||||||
if (lowPower)
|
|
||||||
{
|
|
||||||
return for64Bits ? _levels64BitSparseTiny : _levels32BitSparseTiny;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return for64Bits ? _levels64BitSparseGiant : _levels32BitSparseGiant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return for64Bits ? _levels64Bit : _levels32Bit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace ARMeilleure.Common
|
namespace ARMeilleure.Common
|
||||||
{
|
{
|
||||||
public unsafe abstract class Allocator : IDisposable
|
unsafe abstract class Allocator : IDisposable
|
||||||
{
|
{
|
||||||
public T* Allocate<T>(ulong count = 1) where T : unmanaged
|
public T* Allocate<T>(ulong count = 1) where T : unmanaged
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ namespace ARMeilleure.Common
|
|||||||
private List<PageInfo> _pages;
|
private List<PageInfo> _pages;
|
||||||
private readonly ulong _pageSize;
|
private readonly ulong _pageSize;
|
||||||
private readonly uint _pageCount;
|
private readonly uint _pageCount;
|
||||||
private readonly List<nint> _extras;
|
private readonly List<IntPtr> _extras;
|
||||||
|
|
||||||
public ArenaAllocator(uint pageSize, uint pageCount)
|
public ArenaAllocator(uint pageSize, uint pageCount)
|
||||||
{
|
{
|
||||||
@@ -31,11 +31,11 @@ namespace ARMeilleure.Common
|
|||||||
_pageIndex = -1;
|
_pageIndex = -1;
|
||||||
|
|
||||||
_page = null;
|
_page = null;
|
||||||
_pages = [];
|
_pages = new List<PageInfo>();
|
||||||
_pageSize = pageSize;
|
_pageSize = pageSize;
|
||||||
_pageCount = pageCount;
|
_pageCount = pageCount;
|
||||||
|
|
||||||
_extras = [];
|
_extras = new List<IntPtr>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Span<T> AllocateSpan<T>(ulong count) where T : unmanaged
|
public Span<T> AllocateSpan<T>(ulong count) where T : unmanaged
|
||||||
@@ -64,7 +64,7 @@ namespace ARMeilleure.Common
|
|||||||
{
|
{
|
||||||
void* extra = NativeAllocator.Instance.Allocate(size);
|
void* extra = NativeAllocator.Instance.Allocate(size);
|
||||||
|
|
||||||
_extras.Add((nint)extra);
|
_extras.Add((IntPtr)extra);
|
||||||
|
|
||||||
return extra;
|
return extra;
|
||||||
}
|
}
|
||||||
@@ -82,10 +82,8 @@ namespace ARMeilleure.Common
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_page = new PageInfo
|
_page = new PageInfo();
|
||||||
{
|
_page.Pointer = (byte*)NativeAllocator.Instance.Allocate(_pageSize);
|
||||||
Pointer = (byte*)NativeAllocator.Instance.Allocate(_pageSize),
|
|
||||||
};
|
|
||||||
|
|
||||||
_pages.Add(_page);
|
_pages.Add(_page);
|
||||||
}
|
}
|
||||||
@@ -108,13 +106,13 @@ namespace ARMeilleure.Common
|
|||||||
// Free excess pages that was allocated.
|
// Free excess pages that was allocated.
|
||||||
while (_pages.Count > _pageCount)
|
while (_pages.Count > _pageCount)
|
||||||
{
|
{
|
||||||
NativeAllocator.Instance.Free(_pages[^1].Pointer);
|
NativeAllocator.Instance.Free(_pages[_pages.Count - 1].Pointer);
|
||||||
|
|
||||||
_pages.RemoveAt(_pages.Count - 1);
|
_pages.RemoveAt(_pages.Count - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free extra blocks that are not page-sized
|
// Free extra blocks that are not page-sized
|
||||||
foreach (nint ptr in _extras)
|
foreach (IntPtr ptr in _extras)
|
||||||
{
|
{
|
||||||
NativeAllocator.Instance.Free((void*)ptr);
|
NativeAllocator.Instance.Free((void*)ptr);
|
||||||
}
|
}
|
||||||
@@ -127,13 +125,12 @@ namespace ARMeilleure.Common
|
|||||||
|
|
||||||
// If arena is used frequently, keep pages for longer. Otherwise keep pages for a shorter amount of time.
|
// If arena is used frequently, keep pages for longer. Otherwise keep pages for a shorter amount of time.
|
||||||
int now = Environment.TickCount;
|
int now = Environment.TickCount;
|
||||||
int count = (now - _lastReset) switch
|
int count = (now - _lastReset) switch {
|
||||||
{
|
|
||||||
>= 5000 => 0,
|
>= 5000 => 0,
|
||||||
>= 2500 => 50,
|
>= 2500 => 50,
|
||||||
>= 1000 => 100,
|
>= 1000 => 100,
|
||||||
>= 10 => 1500,
|
>= 10 => 1500,
|
||||||
_ => 5000,
|
_ => 5000
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = _pages.Count - 1; i >= 0; i--)
|
for (int i = _pages.Count - 1; i >= 0; i--)
|
||||||
@@ -173,7 +170,7 @@ namespace ARMeilleure.Common
|
|||||||
NativeAllocator.Instance.Free(info.Pointer);
|
NativeAllocator.Instance.Free(info.Pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (nint ptr in _extras)
|
foreach (IntPtr ptr in _extras)
|
||||||
{
|
{
|
||||||
NativeAllocator.Instance.Free((void*)ptr);
|
NativeAllocator.Instance.Free((void*)ptr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,16 +129,16 @@ namespace ARMeilleure.Common
|
|||||||
|
|
||||||
if (count > _count)
|
if (count > _count)
|
||||||
{
|
{
|
||||||
long* oldMask = _masks;
|
var oldMask = _masks;
|
||||||
Span<long> oldSpan = new(_masks, _count);
|
var oldSpan = new Span<long>(_masks, _count);
|
||||||
|
|
||||||
_masks = _allocator.Allocate<long>((uint)count);
|
_masks = _allocator.Allocate<long>((uint)count);
|
||||||
_count = count;
|
_count = count;
|
||||||
|
|
||||||
Span<long> newSpan = new(_masks, _count);
|
var newSpan = new Span<long>(_masks, _count);
|
||||||
|
|
||||||
oldSpan.CopyTo(newSpan);
|
oldSpan.CopyTo(newSpan);
|
||||||
newSpan[oldSpan.Length..].Clear();
|
newSpan.Slice(oldSpan.Length).Clear();
|
||||||
|
|
||||||
_allocator.Free(oldMask);
|
_allocator.Free(oldMask);
|
||||||
}
|
}
|
||||||
@@ -176,8 +176,8 @@ namespace ARMeilleure.Common
|
|||||||
private int _bit;
|
private int _bit;
|
||||||
private readonly BitMap _map;
|
private readonly BitMap _map;
|
||||||
|
|
||||||
public readonly int Current => (int)_index * IntSize + _bit;
|
public int Current => (int)_index * IntSize + _bit;
|
||||||
readonly object IEnumerator.Current => Current;
|
object IEnumerator.Current => Current;
|
||||||
|
|
||||||
public Enumerator(BitMap map)
|
public Enumerator(BitMap map)
|
||||||
{
|
{
|
||||||
@@ -214,9 +214,9 @@ namespace ARMeilleure.Common
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly void Reset() { }
|
public void Reset() { }
|
||||||
|
|
||||||
public readonly void Dispose() { }
|
public void Dispose() { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ namespace ARMeilleure.Common
|
|||||||
{
|
{
|
||||||
static class BitUtils
|
static class BitUtils
|
||||||
{
|
{
|
||||||
private static ReadOnlySpan<sbyte> HbsNibbleLut => [-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)
|
public static long FillWithOnes(int bits)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace ARMeilleure.Common
|
namespace ARMeilleure.Common
|
||||||
{
|
{
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user