Compare commits
97 Commits
Author | SHA1 | Date | |
---|---|---|---|
41bba5310a | |||
8071c8c8c0 | |||
b402b4e7f6 | |||
93df366b2c | |||
cd3a15aea5 | |||
070136b3f7 | |||
08ab47c6c0 | |||
85faa9d8fa | |||
dca5b14493 | |||
4d2c8e2a44 | |||
8fa248ceb4 | |||
30862b5ffd | |||
9f57747c57 | |||
fe29a2ff6e | |||
e9a173e00c | |||
a11784fcbf | |||
fd36c8deca | |||
70638340b3 | |||
4b495f3333 | |||
934b5a64e5 | |||
cee667b491 | |||
94a64f2aea | |||
2355c2af62 | |||
5e0f8e8738 | |||
d16288a2a8 | |||
600f86dc7b | |||
7210c17c5e | |||
a16854e55a | |||
3e455a90a1 | |||
e4413542b2 | |||
8c720783f5 | |||
8734ea9dd4 | |||
c586e6d2b7 | |||
3a4eeb77fe | |||
51b3953cfc | |||
610eecc1c1 | |||
492056abf6 | |||
ee6e682ab4 | |||
6f60e102a2 | |||
eeb2af9953 | |||
550747eac6 | |||
3ffceab1fb | |||
b9f2a96595 | |||
cbaa845f5d | |||
9e2681f2d7 | |||
81fae0d1a6 | |||
38519f3b9a | |||
7f27aabbd0 | |||
e876c43ce9 | |||
8639245533 | |||
d6b86a6629 | |||
8f2b7b5b8e | |||
fc4b7cba2c | |||
08831eecf7 | |||
c6a139a6e7 | |||
02714a1291 | |||
09c9686498 | |||
b6614c6ad5 | |||
b1d4b174a6 | |||
2b23463daa | |||
9dfe81770a | |||
52c115a1f8 | |||
e20abbf9cc | |||
76671d63d4 | |||
3d1a0bf374 | |||
c20f3fbebd | |||
0d3b82477e | |||
470be03c2f | |||
c963b3c804 | |||
a4fdfb5f94 | |||
37d27c4c99 | |||
f906eb06c2 | |||
219f63ff4e | |||
1cca3e99ab | |||
55a23e5ec8 | |||
479d1fd8b0 | |||
cb70e7bb30 | |||
c200a7b7c6 | |||
6268170a10 | |||
ee0f9b03a4 | |||
f93c5f006a | |||
295fbd0542 | |||
d7310d7a1c | |||
8c50943a2e | |||
ec4cd57ccf | |||
5a085cba0f | |||
1a1d33a018 | |||
0fbcd630bc | |||
f4d731ae20 | |||
8ac53c66b4 | |||
0f50de72be | |||
df758eddd1 | |||
5f32a8ed94 | |||
535fbec675 | |||
6fe88115a3 | |||
475fa4d390 | |||
edf7e628ca |
61
.gitattributes
vendored
61
.gitattributes
vendored
@ -1,63 +1,4 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
* text=auto eol=lf
|
||||
|
28
.github/workflows/release.yml
vendored
28
.github/workflows/release.yml
vendored
@ -38,11 +38,11 @@ jobs:
|
||||
shell: bash
|
||||
- name: Configure for release
|
||||
run: |
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' Ryujinx.Common/ReleaseInformations.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' Ryujinx.Common/ReleaseInformations.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' Ryujinx.Common/ReleaseInformations.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' Ryujinx.Common/ReleaseInformations.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' Ryujinx.Common/ReleaseInformations.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_VERSION\%\%/${{ steps.version_info.outputs.build_version }}/g;' Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_BUILD_GIT_HASH\%\%/${{ steps.version_info.outputs.git_short_hash }}/g;' Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_NAME\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_NAME }}/g;' Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/g;' Ryujinx.Common/ReleaseInformation.cs
|
||||
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' Ryujinx.Common/ReleaseInformation.cs
|
||||
shell: bash
|
||||
- name: Create output dir
|
||||
run: "mkdir release_output"
|
||||
@ -75,15 +75,27 @@ jobs:
|
||||
- name: Packing Linux builds
|
||||
run: |
|
||||
pushd publish_linux
|
||||
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
|
||||
tar --exclude "publish/Ryujinx" --exclude "publish/Ryujinx.sh" -cvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar publish
|
||||
python3 ../distribution/misc/add_tar_exec.py ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx" "publish/Ryujinx"
|
||||
python3 ../distribution/misc/add_tar_exec.py ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx.sh" "publish/Ryujinx.sh"
|
||||
gzip -9 < ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar > ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz
|
||||
rm ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar
|
||||
popd
|
||||
|
||||
pushd publish_linux_sdl2_headless
|
||||
tar -czvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
|
||||
tar --exclude "publish/Ryujinx.Headless.SDL2" --exclude "publish/Ryujinx.sh" -cvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar publish
|
||||
python3 ../distribution/misc/add_tar_exec.py ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx.Headless.SDL2" "publish/Ryujinx.Headless.SDL2"
|
||||
python3 ../distribution/misc/add_tar_exec.py ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx.sh" "publish/Ryujinx.sh"
|
||||
gzip -9 < ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar > ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz
|
||||
rm ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-linux_x64.tar
|
||||
popd
|
||||
|
||||
pushd publish_linux_ava
|
||||
tar -czvf ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz publish
|
||||
tar --exclude "publish/Ryujinx.Ava" --exclude "publish/Ryujinx.sh" -cvf ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar publish
|
||||
python3 ../distribution/misc/add_tar_exec.py ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx.Ava" "publish/Ryujinx.Ava"
|
||||
python3 ../distribution/misc/add_tar_exec.py ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar "publish/Ryujinx.sh" "publish/Ryujinx.sh"
|
||||
gzip -9 < ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar > ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz
|
||||
rm ../release_output/test-ava-ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar
|
||||
popd
|
||||
shell: bash
|
||||
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -125,6 +125,9 @@ ClientBin/
|
||||
packages/*
|
||||
*.config
|
||||
|
||||
# Include nuget.config
|
||||
!nuget.config
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
|
@ -9,4 +9,11 @@
|
||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ContentWithTargetPath Include="Native\libs\libarmeilleure-jitsupport.dylib" Condition="'$(RuntimeIdentifier)' == '' OR '$(RuntimeIdentifier)' == 'osx-arm64'">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>libarmeilleure-jitsupport.dylib</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
270
ARMeilleure/CodeGen/Arm64/Arm64Optimizer.cs
Normal file
270
ARMeilleure/CodeGen/Arm64/Arm64Optimizer.cs
Normal file
@ -0,0 +1,270 @@
|
||||
using ARMeilleure.CodeGen.Optimizations;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System.Collections.Generic;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
|
||||
|
||||
namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
static class Arm64Optimizer
|
||||
{
|
||||
private const int MaxConstantUses = 10000;
|
||||
|
||||
public static void RunPass(ControlFlowGraph cfg)
|
||||
{
|
||||
var constants = new Dictionary<ulong, Operand>();
|
||||
|
||||
Operand GetConstantCopy(BasicBlock block, Operation operation, Operand source)
|
||||
{
|
||||
// If the constant has many uses, we also force a new constant mov to be added, in order
|
||||
// to avoid overflow of the counts field (that is limited to 16 bits).
|
||||
if (!constants.TryGetValue(source.Value, out var constant) || constant.UsesCount > MaxConstantUses)
|
||||
{
|
||||
constant = Local(source.Type);
|
||||
|
||||
Operation copyOp = Operation(Instruction.Copy, constant, source);
|
||||
|
||||
block.Operations.AddBefore(operation, copyOp);
|
||||
|
||||
constants[source.Value] = constant;
|
||||
}
|
||||
|
||||
return constant;
|
||||
}
|
||||
|
||||
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||
{
|
||||
constants.Clear();
|
||||
|
||||
Operation nextNode;
|
||||
|
||||
for (Operation node = block.Operations.First; node != default; node = nextNode)
|
||||
{
|
||||
nextNode = node.ListNext;
|
||||
|
||||
// Insert copies for constants that can't fit on a 32-bit immediate.
|
||||
// Doing this early unblocks a few optimizations.
|
||||
if (node.Instruction == Instruction.Add)
|
||||
{
|
||||
Operand src1 = node.GetSource(0);
|
||||
Operand src2 = node.GetSource(1);
|
||||
|
||||
if (src1.Kind == OperandKind.Constant && (src1.Relocatable || ConstTooLong(src1, OperandType.I32)))
|
||||
{
|
||||
node.SetSource(0, GetConstantCopy(block, node, src1));
|
||||
}
|
||||
|
||||
if (src2.Kind == OperandKind.Constant && (src2.Relocatable || ConstTooLong(src2, OperandType.I32)))
|
||||
{
|
||||
node.SetSource(1, GetConstantCopy(block, node, src2));
|
||||
}
|
||||
}
|
||||
|
||||
// Try to fold something like:
|
||||
// lsl x1, x1, #2
|
||||
// add x0, x0, x1
|
||||
// ldr x0, [x0]
|
||||
// add x2, x2, #16
|
||||
// ldr x2, [x2]
|
||||
// Into:
|
||||
// ldr x0, [x0, x1, lsl #2]
|
||||
// ldr x2, [x2, #16]
|
||||
if (IsMemoryLoadOrStore(node.Instruction))
|
||||
{
|
||||
OperandType type;
|
||||
|
||||
if (node.Destination != default)
|
||||
{
|
||||
type = node.Destination.Type;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = node.GetSource(1).Type;
|
||||
}
|
||||
|
||||
Operand memOp = GetMemoryOperandOrNull(node.GetSource(0), type);
|
||||
|
||||
if (memOp != default)
|
||||
{
|
||||
node.SetSource(0, memOp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Optimizer.RemoveUnusedNodes(cfg);
|
||||
}
|
||||
|
||||
private static Operand GetMemoryOperandOrNull(Operand addr, OperandType type)
|
||||
{
|
||||
Operand baseOp = addr;
|
||||
|
||||
// First we check if the address is the result of a local X with immediate
|
||||
// addition. If that is the case, then the baseOp is X, and the memory operand immediate
|
||||
// becomes the addition immediate. Otherwise baseOp keeps being the address.
|
||||
int imm = GetConstOp(ref baseOp, type);
|
||||
if (imm != 0)
|
||||
{
|
||||
return MemoryOp(type, baseOp, default, Multiplier.x1, imm);
|
||||
}
|
||||
|
||||
// Now we check if the baseOp is the result of a local Y with a local Z addition.
|
||||
// If that is the case, we now set baseOp to Y and indexOp to Z. We further check
|
||||
// if Z is the result of a left shift of local W by a value == 0 or == Log2(AccessSize),
|
||||
// if that is the case, we set indexOp to W and adjust the scale value of the memory operand
|
||||
// to match that of the left shift.
|
||||
// There is one missed case, which is the address being a shift result, but this is
|
||||
// probably not worth optimizing as it should never happen.
|
||||
(Operand indexOp, Multiplier scale) = GetIndexOp(ref baseOp, type);
|
||||
|
||||
// If baseOp is still equal to address, then there's nothing that can be optimized.
|
||||
if (baseOp == addr)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return MemoryOp(type, baseOp, indexOp, scale, 0);
|
||||
}
|
||||
|
||||
private static int GetConstOp(ref Operand baseOp, OperandType accessType)
|
||||
{
|
||||
Operation operation = GetAsgOpWithInst(baseOp, Instruction.Add);
|
||||
|
||||
if (operation == default)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Operand src1 = operation.GetSource(0);
|
||||
Operand src2 = operation.GetSource(1);
|
||||
|
||||
Operand constOp;
|
||||
Operand otherOp;
|
||||
|
||||
if (src1.Kind == OperandKind.Constant && src2.Kind == OperandKind.LocalVariable)
|
||||
{
|
||||
constOp = src1;
|
||||
otherOp = src2;
|
||||
}
|
||||
else if (src1.Kind == OperandKind.LocalVariable && src2.Kind == OperandKind.Constant)
|
||||
{
|
||||
constOp = src2;
|
||||
otherOp = src1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If we have addition by a constant that we can't encode on the instruction,
|
||||
// then we can't optimize it further.
|
||||
if (ConstTooLong(constOp, accessType))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
baseOp = otherOp;
|
||||
|
||||
return constOp.AsInt32();
|
||||
}
|
||||
|
||||
private static (Operand, Multiplier) GetIndexOp(ref Operand baseOp, OperandType accessType)
|
||||
{
|
||||
Operand indexOp = default;
|
||||
|
||||
Multiplier scale = Multiplier.x1;
|
||||
|
||||
Operation addOp = GetAsgOpWithInst(baseOp, Instruction.Add);
|
||||
|
||||
if (addOp == default)
|
||||
{
|
||||
return (indexOp, scale);
|
||||
}
|
||||
|
||||
Operand src1 = addOp.GetSource(0);
|
||||
Operand src2 = addOp.GetSource(1);
|
||||
|
||||
if (src1.Kind != OperandKind.LocalVariable || src2.Kind != OperandKind.LocalVariable)
|
||||
{
|
||||
return (indexOp, scale);
|
||||
}
|
||||
|
||||
baseOp = src1;
|
||||
indexOp = src2;
|
||||
|
||||
Operation shlOp = GetAsgOpWithInst(src1, Instruction.ShiftLeft);
|
||||
|
||||
bool indexOnSrc2 = false;
|
||||
|
||||
if (shlOp == default)
|
||||
{
|
||||
shlOp = GetAsgOpWithInst(src2, Instruction.ShiftLeft);
|
||||
|
||||
indexOnSrc2 = true;
|
||||
}
|
||||
|
||||
if (shlOp != default)
|
||||
{
|
||||
Operand shSrc = shlOp.GetSource(0);
|
||||
Operand shift = shlOp.GetSource(1);
|
||||
|
||||
int maxShift = Assembler.GetScaleForType(accessType);
|
||||
|
||||
if (shSrc.Kind == OperandKind.LocalVariable &&
|
||||
shift.Kind == OperandKind.Constant &&
|
||||
(shift.Value == 0 || shift.Value == (ulong)maxShift))
|
||||
{
|
||||
scale = shift.Value switch
|
||||
{
|
||||
1 => Multiplier.x2,
|
||||
2 => Multiplier.x4,
|
||||
3 => Multiplier.x8,
|
||||
4 => Multiplier.x16,
|
||||
_ => Multiplier.x1
|
||||
};
|
||||
|
||||
baseOp = indexOnSrc2 ? src1 : src2;
|
||||
indexOp = shSrc;
|
||||
}
|
||||
}
|
||||
|
||||
return (indexOp, scale);
|
||||
}
|
||||
|
||||
private static Operation GetAsgOpWithInst(Operand op, Instruction inst)
|
||||
{
|
||||
// If we have multiple assignments, folding is not safe
|
||||
// as the value may be different depending on the
|
||||
// control flow path.
|
||||
if (op.AssignmentsCount != 1)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
Operation asgOp = op.Assignments[0];
|
||||
|
||||
if (asgOp.Instruction != inst)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return asgOp;
|
||||
}
|
||||
|
||||
private static bool IsMemoryLoadOrStore(Instruction inst)
|
||||
{
|
||||
return inst == Instruction.Load || inst == Instruction.Store;
|
||||
}
|
||||
|
||||
private static bool ConstTooLong(Operand constOp, OperandType accessType)
|
||||
{
|
||||
if ((uint)constOp.Value != constOp.Value)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return !CodeGenCommon.ConstFitsOnUImm12(constOp.AsInt32(), accessType);
|
||||
}
|
||||
}
|
||||
}
|
47
ARMeilleure/CodeGen/Arm64/ArmCondition.cs
Normal file
47
ARMeilleure/CodeGen/Arm64/ArmCondition.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using System;
|
||||
|
||||
namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
enum ArmCondition
|
||||
{
|
||||
Eq = 0,
|
||||
Ne = 1,
|
||||
GeUn = 2,
|
||||
LtUn = 3,
|
||||
Mi = 4,
|
||||
Pl = 5,
|
||||
Vs = 6,
|
||||
Vc = 7,
|
||||
GtUn = 8,
|
||||
LeUn = 9,
|
||||
Ge = 10,
|
||||
Lt = 11,
|
||||
Gt = 12,
|
||||
Le = 13,
|
||||
Al = 14,
|
||||
Nv = 15
|
||||
}
|
||||
|
||||
static class ComparisonArm64Extensions
|
||||
{
|
||||
public static ArmCondition ToArmCondition(this Comparison comp)
|
||||
{
|
||||
return comp switch
|
||||
{
|
||||
Comparison.Equal => ArmCondition.Eq,
|
||||
Comparison.NotEqual => ArmCondition.Ne,
|
||||
Comparison.Greater => ArmCondition.Gt,
|
||||
Comparison.LessOrEqual => ArmCondition.Le,
|
||||
Comparison.GreaterUI => ArmCondition.GtUn,
|
||||
Comparison.LessOrEqualUI => ArmCondition.LeUn,
|
||||
Comparison.GreaterOrEqual => ArmCondition.Ge,
|
||||
Comparison.Less => ArmCondition.Lt,
|
||||
Comparison.GreaterOrEqualUI => ArmCondition.GeUn,
|
||||
Comparison.LessUI => ArmCondition.LtUn,
|
||||
|
||||
_ => throw new ArgumentException(null, nameof(comp))
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
14
ARMeilleure/CodeGen/Arm64/ArmExtensionType.cs
Normal file
14
ARMeilleure/CodeGen/Arm64/ArmExtensionType.cs
Normal file
@ -0,0 +1,14 @@
|
||||
namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
enum ArmExtensionType
|
||||
{
|
||||
Uxtb = 0,
|
||||
Uxth = 1,
|
||||
Uxtw = 2,
|
||||
Uxtx = 3,
|
||||
Sxtb = 4,
|
||||
Sxth = 5,
|
||||
Sxtw = 6,
|
||||
Sxtx = 7
|
||||
}
|
||||
}
|
11
ARMeilleure/CodeGen/Arm64/ArmShiftType.cs
Normal file
11
ARMeilleure/CodeGen/Arm64/ArmShiftType.cs
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
enum ArmShiftType
|
||||
{
|
||||
Lsl = 0,
|
||||
Lsr = 1,
|
||||
Asr = 2,
|
||||
Ror = 3
|
||||
}
|
||||
}
|
1160
ARMeilleure/CodeGen/Arm64/Assembler.cs
Normal file
1160
ARMeilleure/CodeGen/Arm64/Assembler.cs
Normal file
File diff suppressed because it is too large
Load Diff
96
ARMeilleure/CodeGen/Arm64/CallingConvention.cs
Normal file
96
ARMeilleure/CodeGen/Arm64/CallingConvention.cs
Normal file
@ -0,0 +1,96 @@
|
||||
using System;
|
||||
|
||||
namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
static class CallingConvention
|
||||
{
|
||||
private const int RegistersMask = unchecked((int)0xffffffff);
|
||||
|
||||
// Some of those register have specific roles and can't be used as general purpose registers.
|
||||
// X18 - Reserved for platform specific usage.
|
||||
// X29 - Frame pointer.
|
||||
// X30 - Return address.
|
||||
// X31 - Not an actual register, in some cases maps to SP, and in others to ZR.
|
||||
private const int ReservedRegsMask = (1 << CodeGenCommon.ReservedRegister) | (1 << 18) | (1 << 29) | (1 << 30) | (1 << 31);
|
||||
|
||||
public static int GetIntAvailableRegisters()
|
||||
{
|
||||
return RegistersMask & ~ReservedRegsMask;
|
||||
}
|
||||
|
||||
public static int GetVecAvailableRegisters()
|
||||
{
|
||||
return RegistersMask;
|
||||
}
|
||||
|
||||
public static int GetIntCallerSavedRegisters()
|
||||
{
|
||||
return (GetIntCalleeSavedRegisters() ^ RegistersMask) & ~ReservedRegsMask;
|
||||
}
|
||||
|
||||
public static int GetFpCallerSavedRegisters()
|
||||
{
|
||||
return GetFpCalleeSavedRegisters() ^ RegistersMask;
|
||||
}
|
||||
|
||||
public static int GetVecCallerSavedRegisters()
|
||||
{
|
||||
return GetVecCalleeSavedRegisters() ^ RegistersMask;
|
||||
}
|
||||
|
||||
public static int GetIntCalleeSavedRegisters()
|
||||
{
|
||||
return 0x1ff80000; // X19 to X28
|
||||
}
|
||||
|
||||
public static int GetFpCalleeSavedRegisters()
|
||||
{
|
||||
return 0xff00; // D8 to D15
|
||||
}
|
||||
|
||||
public static int GetVecCalleeSavedRegisters()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int GetArgumentsOnRegsCount()
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
public static int GetIntArgumentRegister(int index)
|
||||
{
|
||||
if ((uint)index < (uint)GetArgumentsOnRegsCount())
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
public static int GetVecArgumentRegister(int index)
|
||||
{
|
||||
if ((uint)index < (uint)GetArgumentsOnRegsCount())
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
public static int GetIntReturnRegister()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int GetIntReturnRegisterHigh()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static int GetVecReturnRegister()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
173
ARMeilleure/CodeGen/Arm64/CodeGenCommon.cs
Normal file
173
ARMeilleure/CodeGen/Arm64/CodeGenCommon.cs
Normal file
@ -0,0 +1,173 @@
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
static class CodeGenCommon
|
||||
{
|
||||
public const int TcAddressRegister = 8;
|
||||
public const int ReservedRegister = 17;
|
||||
|
||||
public static bool ConstFitsOnSImm7(int value, int scale)
|
||||
{
|
||||
return (((value >> scale) << 25) >> (25 - scale)) == value;
|
||||
}
|
||||
|
||||
public static bool ConstFitsOnSImm9(int value)
|
||||
{
|
||||
return ((value << 23) >> 23) == value;
|
||||
}
|
||||
|
||||
public static bool ConstFitsOnUImm12(int value)
|
||||
{
|
||||
return (value & 0xfff) == value;
|
||||
}
|
||||
|
||||
public static bool ConstFitsOnUImm12(int value, OperandType type)
|
||||
{
|
||||
int scale = Assembler.GetScaleForType(type);
|
||||
return (((value >> scale) & 0xfff) << scale) == value;
|
||||
}
|
||||
|
||||
public static bool TryEncodeBitMask(Operand operand, out int immN, out int immS, out int immR)
|
||||
{
|
||||
ulong value = operand.Value;
|
||||
|
||||
if (operand.Type == OperandType.I32)
|
||||
{
|
||||
value |= value << 32;
|
||||
}
|
||||
|
||||
return TryEncodeBitMask(value, out immN, out immS, out immR);
|
||||
}
|
||||
|
||||
public static bool TryEncodeBitMask(ulong value, out int immN, out int immS, out int immR)
|
||||
{
|
||||
// Some special values also can't be encoded:
|
||||
// 0 can't be encoded because we need to subtract 1 from onesCount (which would became negative if 0).
|
||||
// A value with all bits set can't be encoded because it is reserved according to the spec, because:
|
||||
// Any value AND all ones will be equal itself, so it's effectively a no-op.
|
||||
// Any value OR all ones will be equal all ones, so one can just use MOV.
|
||||
// Any value XOR all ones will be equal its inverse, so one can just use MVN.
|
||||
if (value == ulong.MaxValue)
|
||||
{
|
||||
immN = 0;
|
||||
immS = 0;
|
||||
immR = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int bitLength = CountSequence(value);
|
||||
|
||||
if ((value >> bitLength) != 0)
|
||||
{
|
||||
bitLength += CountSequence(value >> bitLength);
|
||||
}
|
||||
|
||||
int bitLengthLog2 = BitOperations.Log2((uint)bitLength);
|
||||
int bitLengthPow2 = 1 << bitLengthLog2;
|
||||
|
||||
if (bitLengthPow2 < bitLength)
|
||||
{
|
||||
bitLengthLog2++;
|
||||
bitLengthPow2 <<= 1;
|
||||
}
|
||||
|
||||
int selectedESize = 64;
|
||||
int repetitions = 1;
|
||||
int onesCount = BitOperations.PopCount(value);
|
||||
|
||||
if (bitLengthPow2 < 64 && (value >> bitLengthPow2) != 0)
|
||||
{
|
||||
for (int eSizeLog2 = bitLengthLog2; eSizeLog2 < 6; eSizeLog2++)
|
||||
{
|
||||
bool match = true;
|
||||
int eSize = 1 << eSizeLog2;
|
||||
ulong mask = (1UL << eSize) - 1;
|
||||
ulong eValue = value & mask;
|
||||
|
||||
for (int e = 1; e < 64 / eSize; e++)
|
||||
{
|
||||
if (((value >> (e * eSize)) & mask) != eValue)
|
||||
{
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (match)
|
||||
{
|
||||
selectedESize = eSize;
|
||||
repetitions = 64 / eSize;
|
||||
onesCount = BitOperations.PopCount(eValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find rotation. We have two cases, one where the highest bit is 0
|
||||
// and one where it is 1.
|
||||
// If it's 1, we just need to count the number of 1 bits on the MSB to find the right rotation.
|
||||
// If it's 0, we just need to count the number of 0 bits on the LSB to find the left rotation,
|
||||
// then we can convert it to the right rotation shift by subtracting the value from the element size.
|
||||
int rotation;
|
||||
long vHigh = (long)(value << (64 - selectedESize));
|
||||
if (vHigh < 0)
|
||||
{
|
||||
rotation = BitOperations.LeadingZeroCount(~(ulong)vHigh);
|
||||
}
|
||||
else
|
||||
{
|
||||
rotation = (selectedESize - BitOperations.TrailingZeroCount(value)) & (selectedESize - 1);
|
||||
}
|
||||
|
||||
// Reconstruct value and see if it matches. If not, we can't encode.
|
||||
ulong reconstructed = onesCount == 64 ? ulong.MaxValue : RotateRight((1UL << onesCount) - 1, rotation, selectedESize);
|
||||
|
||||
for (int bit = 32; bit >= selectedESize; bit >>= 1)
|
||||
{
|
||||
reconstructed |= reconstructed << bit;
|
||||
}
|
||||
|
||||
if (reconstructed != value || onesCount == 0)
|
||||
{
|
||||
immN = 0;
|
||||
immS = 0;
|
||||
immR = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
immR = rotation;
|
||||
|
||||
// immN indicates that there are no repetitions.
|
||||
// The MSB of immS indicates the amount of repetitions, and the LSB the number of bits set.
|
||||
if (repetitions == 1)
|
||||
{
|
||||
immN = 1;
|
||||
immS = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
immN = 0;
|
||||
immS = (0xf80 >> BitOperations.Log2((uint)repetitions)) & 0x3f;
|
||||
}
|
||||
|
||||
immS |= onesCount - 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int CountSequence(ulong value)
|
||||
{
|
||||
return BitOperations.TrailingZeroCount(value) + BitOperations.TrailingZeroCount(~value);
|
||||
}
|
||||
|
||||
private static ulong RotateRight(ulong bits, int shift, int size)
|
||||
{
|
||||
return (bits >> shift) | ((bits << (size - shift)) & (size == 64 ? ulong.MaxValue : (1UL << size) - 1));
|
||||
}
|
||||
}
|
||||
}
|
286
ARMeilleure/CodeGen/Arm64/CodeGenContext.cs
Normal file
286
ARMeilleure/CodeGen/Arm64/CodeGenContext.cs
Normal file
@ -0,0 +1,286 @@
|
||||
using ARMeilleure.CodeGen.Linking;
|
||||
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
class CodeGenContext
|
||||
{
|
||||
private const int BccInstLength = 4;
|
||||
private const int CbnzInstLength = 4;
|
||||
private const int LdrLitInstLength = 4;
|
||||
|
||||
private Stream _stream;
|
||||
|
||||
public int StreamOffset => (int)_stream.Length;
|
||||
|
||||
public AllocationResult AllocResult { get; }
|
||||
|
||||
public Assembler Assembler { get; }
|
||||
|
||||
public BasicBlock CurrBlock { get; private set; }
|
||||
|
||||
public bool HasCall { get; }
|
||||
|
||||
public int CallArgsRegionSize { get; }
|
||||
public int FpLrSaveRegionSize { get; }
|
||||
|
||||
private readonly Dictionary<BasicBlock, long> _visitedBlocks;
|
||||
private readonly Dictionary<BasicBlock, List<(ArmCondition Condition, long BranchPos)>> _pendingBranches;
|
||||
|
||||
private struct ConstantPoolEntry
|
||||
{
|
||||
public readonly int Offset;
|
||||
public readonly Symbol Symbol;
|
||||
public readonly List<(Operand, int)> LdrOffsets;
|
||||
|
||||
public ConstantPoolEntry(int offset, Symbol symbol)
|
||||
{
|
||||
Offset = offset;
|
||||
Symbol = symbol;
|
||||
LdrOffsets = new List<(Operand, int)>();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Dictionary<ulong, ConstantPoolEntry> _constantPool;
|
||||
|
||||
private bool _constantPoolWritten;
|
||||
private long _constantPoolOffset;
|
||||
|
||||
private ArmCondition _jNearCondition;
|
||||
private Operand _jNearValue;
|
||||
|
||||
private long _jNearPosition;
|
||||
|
||||
private readonly bool _relocatable;
|
||||
|
||||
public CodeGenContext(AllocationResult allocResult, int maxCallArgs, int blocksCount, bool relocatable)
|
||||
{
|
||||
_stream = new MemoryStream();
|
||||
|
||||
AllocResult = allocResult;
|
||||
|
||||
Assembler = new Assembler(_stream);
|
||||
|
||||
bool hasCall = maxCallArgs >= 0;
|
||||
|
||||
HasCall = hasCall;
|
||||
|
||||
if (maxCallArgs < 0)
|
||||
{
|
||||
maxCallArgs = 0;
|
||||
}
|
||||
|
||||
CallArgsRegionSize = maxCallArgs * 16;
|
||||
FpLrSaveRegionSize = hasCall ? 16 : 0;
|
||||
|
||||
_visitedBlocks = new Dictionary<BasicBlock, long>();
|
||||
_pendingBranches = new Dictionary<BasicBlock, List<(ArmCondition, long)>>();
|
||||
_constantPool = new Dictionary<ulong, ConstantPoolEntry>();
|
||||
|
||||
_relocatable = relocatable;
|
||||
}
|
||||
|
||||
public void EnterBlock(BasicBlock block)
|
||||
{
|
||||
CurrBlock = block;
|
||||
|
||||
long target = _stream.Position;
|
||||
|
||||
if (_pendingBranches.TryGetValue(block, out var list))
|
||||
{
|
||||
foreach (var tuple in list)
|
||||
{
|
||||
_stream.Seek(tuple.BranchPos, SeekOrigin.Begin);
|
||||
WriteBranch(tuple.Condition, target);
|
||||
}
|
||||
|
||||
_stream.Seek(target, SeekOrigin.Begin);
|
||||
_pendingBranches.Remove(block);
|
||||
}
|
||||
|
||||
_visitedBlocks.Add(block, target);
|
||||
}
|
||||
|
||||
public void JumpTo(BasicBlock target)
|
||||
{
|
||||
JumpTo(ArmCondition.Al, target);
|
||||
}
|
||||
|
||||
public void JumpTo(ArmCondition condition, BasicBlock target)
|
||||
{
|
||||
if (_visitedBlocks.TryGetValue(target, out long offset))
|
||||
{
|
||||
WriteBranch(condition, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_pendingBranches.TryGetValue(target, out var list))
|
||||
{
|
||||
list = new List<(ArmCondition, long)>();
|
||||
_pendingBranches.Add(target, list);
|
||||
}
|
||||
|
||||
list.Add((condition, _stream.Position));
|
||||
|
||||
_stream.Seek(BccInstLength, SeekOrigin.Current);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteBranch(ArmCondition condition, long to)
|
||||
{
|
||||
int imm = checked((int)(to - _stream.Position));
|
||||
|
||||
if (condition != ArmCondition.Al)
|
||||
{
|
||||
Assembler.B(condition, imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assembler.B(imm);
|
||||
}
|
||||
}
|
||||
|
||||
public void JumpToNear(ArmCondition condition)
|
||||
{
|
||||
_jNearCondition = condition;
|
||||
_jNearPosition = _stream.Position;
|
||||
|
||||
_stream.Seek(BccInstLength, SeekOrigin.Current);
|
||||
}
|
||||
|
||||
public void JumpToNearIfNotZero(Operand value)
|
||||
{
|
||||
_jNearValue = value;
|
||||
_jNearPosition = _stream.Position;
|
||||
|
||||
_stream.Seek(CbnzInstLength, SeekOrigin.Current);
|
||||
}
|
||||
|
||||
public void JumpHere()
|
||||
{
|
||||
long currentPosition = _stream.Position;
|
||||
long offset = currentPosition - _jNearPosition;
|
||||
|
||||
_stream.Seek(_jNearPosition, SeekOrigin.Begin);
|
||||
|
||||
if (_jNearValue != default)
|
||||
{
|
||||
Assembler.Cbnz(_jNearValue, checked((int)offset));
|
||||
_jNearValue = default;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assembler.B(_jNearCondition, checked((int)offset));
|
||||
}
|
||||
|
||||
_stream.Seek(currentPosition, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
public void ReserveRelocatableConstant(Operand rt, Symbol symbol, ulong value)
|
||||
{
|
||||
if (!_constantPool.TryGetValue(value, out ConstantPoolEntry cpe))
|
||||
{
|
||||
cpe = new ConstantPoolEntry(_constantPool.Count * sizeof(ulong), symbol);
|
||||
_constantPool.Add(value, cpe);
|
||||
}
|
||||
|
||||
cpe.LdrOffsets.Add((rt, (int)_stream.Position));
|
||||
_stream.Seek(LdrLitInstLength, SeekOrigin.Current);
|
||||
}
|
||||
|
||||
private long WriteConstantPool()
|
||||
{
|
||||
if (_constantPoolWritten)
|
||||
{
|
||||
return _constantPoolOffset;
|
||||
}
|
||||
|
||||
long constantPoolBaseOffset = _stream.Position;
|
||||
|
||||
foreach (ulong value in _constantPool.Keys)
|
||||
{
|
||||
WriteUInt64(value);
|
||||
}
|
||||
|
||||
foreach (ConstantPoolEntry cpe in _constantPool.Values)
|
||||
{
|
||||
foreach ((Operand rt, int ldrOffset) in cpe.LdrOffsets)
|
||||
{
|
||||
_stream.Seek(ldrOffset, SeekOrigin.Begin);
|
||||
|
||||
int absoluteOffset = checked((int)(constantPoolBaseOffset + cpe.Offset));
|
||||
int pcRelativeOffset = absoluteOffset - ldrOffset;
|
||||
|
||||
Assembler.LdrLit(rt, pcRelativeOffset);
|
||||
}
|
||||
}
|
||||
|
||||
_stream.Seek(constantPoolBaseOffset + _constantPool.Count * sizeof(ulong), SeekOrigin.Begin);
|
||||
|
||||
_constantPoolOffset = constantPoolBaseOffset;
|
||||
_constantPoolWritten = true;
|
||||
|
||||
return constantPoolBaseOffset;
|
||||
}
|
||||
|
||||
public (byte[], RelocInfo) GetCode()
|
||||
{
|
||||
long constantPoolBaseOffset = WriteConstantPool();
|
||||
|
||||
byte[] code = new byte[_stream.Length];
|
||||
|
||||
long originalPosition = _stream.Position;
|
||||
|
||||
_stream.Seek(0, SeekOrigin.Begin);
|
||||
_stream.Read(code, 0, code.Length);
|
||||
_stream.Seek(originalPosition, SeekOrigin.Begin);
|
||||
|
||||
RelocInfo relocInfo;
|
||||
|
||||
if (_relocatable)
|
||||
{
|
||||
RelocEntry[] relocs = new RelocEntry[_constantPool.Count];
|
||||
|
||||
int index = 0;
|
||||
|
||||
foreach (ConstantPoolEntry cpe in _constantPool.Values)
|
||||
{
|
||||
if (cpe.Symbol.Type != SymbolType.None)
|
||||
{
|
||||
int absoluteOffset = checked((int)(constantPoolBaseOffset + cpe.Offset));
|
||||
relocs[index++] = new RelocEntry(absoluteOffset, cpe.Symbol);
|
||||
}
|
||||
}
|
||||
|
||||
if (index != relocs.Length)
|
||||
{
|
||||
Array.Resize(ref relocs, index);
|
||||
}
|
||||
|
||||
relocInfo = new RelocInfo(relocs);
|
||||
}
|
||||
else
|
||||
{
|
||||
relocInfo = new RelocInfo(new RelocEntry[0]);
|
||||
}
|
||||
|
||||
return (code, relocInfo);
|
||||
}
|
||||
|
||||
private void WriteUInt64(ulong value)
|
||||
{
|
||||
_stream.WriteByte((byte)(value >> 0));
|
||||
_stream.WriteByte((byte)(value >> 8));
|
||||
_stream.WriteByte((byte)(value >> 16));
|
||||
_stream.WriteByte((byte)(value >> 24));
|
||||
_stream.WriteByte((byte)(value >> 32));
|
||||
_stream.WriteByte((byte)(value >> 40));
|
||||
_stream.WriteByte((byte)(value >> 48));
|
||||
_stream.WriteByte((byte)(value >> 56));
|
||||
}
|
||||
}
|
||||
}
|
1576
ARMeilleure/CodeGen/Arm64/CodeGenerator.cs
Normal file
1576
ARMeilleure/CodeGen/Arm64/CodeGenerator.cs
Normal file
File diff suppressed because it is too large
Load Diff
662
ARMeilleure/CodeGen/Arm64/CodeGeneratorIntrinsic.cs
Normal file
662
ARMeilleure/CodeGen/Arm64/CodeGeneratorIntrinsic.cs
Normal file
@ -0,0 +1,662 @@
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
static class CodeGeneratorIntrinsic
|
||||
{
|
||||
public static void GenerateOperation(CodeGenContext context, Operation operation)
|
||||
{
|
||||
Intrinsic intrin = operation.Intrinsic;
|
||||
|
||||
IntrinsicInfo info = IntrinsicTable.GetInfo(intrin & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask));
|
||||
|
||||
switch (info.Type)
|
||||
{
|
||||
case IntrinsicType.ScalarUnary:
|
||||
GenerateVectorUnary(
|
||||
context,
|
||||
0,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0));
|
||||
break;
|
||||
case IntrinsicType.ScalarUnaryByElem:
|
||||
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorUnaryByElem(
|
||||
context,
|
||||
0,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
(uint)operation.GetSource(1).AsInt32(),
|
||||
operation.Destination,
|
||||
operation.GetSource(0));
|
||||
break;
|
||||
case IntrinsicType.ScalarBinary:
|
||||
GenerateVectorBinary(
|
||||
context,
|
||||
0,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
operation.GetSource(1));
|
||||
break;
|
||||
case IntrinsicType.ScalarBinaryFPByElem:
|
||||
Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryFPByElem(
|
||||
context,
|
||||
0,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
(uint)operation.GetSource(2).AsInt32(),
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
operation.GetSource(1));
|
||||
break;
|
||||
case IntrinsicType.ScalarBinaryRd:
|
||||
GenerateVectorUnary(
|
||||
context,
|
||||
0,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(1));
|
||||
break;
|
||||
case IntrinsicType.ScalarBinaryShl:
|
||||
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryShlImm(
|
||||
context,
|
||||
0,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
(uint)operation.GetSource(1).AsInt32());
|
||||
break;
|
||||
case IntrinsicType.ScalarBinaryShr:
|
||||
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryShrImm(
|
||||
context,
|
||||
0,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
(uint)operation.GetSource(1).AsInt32());
|
||||
break;
|
||||
case IntrinsicType.ScalarFPCompare:
|
||||
GenerateScalarFPCompare(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
operation.GetSource(1));
|
||||
break;
|
||||
case IntrinsicType.ScalarFPConvFixed:
|
||||
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryShrImm(
|
||||
context,
|
||||
0,
|
||||
((uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift) + 2u,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
(uint)operation.GetSource(1).AsInt32());
|
||||
break;
|
||||
case IntrinsicType.ScalarFPConvFixedGpr:
|
||||
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateScalarFPConvGpr(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
(uint)operation.GetSource(1).AsInt32());
|
||||
break;
|
||||
case IntrinsicType.ScalarFPConvGpr:
|
||||
GenerateScalarFPConvGpr(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0));
|
||||
break;
|
||||
case IntrinsicType.ScalarTernary:
|
||||
GenerateScalarTernary(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(1),
|
||||
operation.GetSource(2),
|
||||
operation.GetSource(0));
|
||||
break;
|
||||
case IntrinsicType.ScalarTernaryFPRdByElem:
|
||||
Debug.Assert(operation.GetSource(3).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryFPByElem(
|
||||
context,
|
||||
0,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
(uint)operation.GetSource(3).AsInt32(),
|
||||
operation.Destination,
|
||||
operation.GetSource(1),
|
||||
operation.GetSource(2));
|
||||
break;
|
||||
case IntrinsicType.ScalarTernaryShlRd:
|
||||
Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryShlImm(
|
||||
context,
|
||||
0,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(1),
|
||||
(uint)operation.GetSource(2).AsInt32());
|
||||
break;
|
||||
case IntrinsicType.ScalarTernaryShrRd:
|
||||
Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryShrImm(
|
||||
context,
|
||||
0,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(1),
|
||||
(uint)operation.GetSource(2).AsInt32());
|
||||
break;
|
||||
|
||||
case IntrinsicType.VectorUnary:
|
||||
GenerateVectorUnary(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0));
|
||||
break;
|
||||
case IntrinsicType.VectorUnaryByElem:
|
||||
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorUnaryByElem(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
(uint)operation.GetSource(1).AsInt32(),
|
||||
operation.Destination,
|
||||
operation.GetSource(0));
|
||||
break;
|
||||
case IntrinsicType.VectorBinary:
|
||||
GenerateVectorBinary(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
operation.GetSource(1));
|
||||
break;
|
||||
case IntrinsicType.VectorBinaryBitwise:
|
||||
GenerateVectorBinary(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
operation.GetSource(1));
|
||||
break;
|
||||
case IntrinsicType.VectorBinaryByElem:
|
||||
Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryByElem(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
(uint)operation.GetSource(2).AsInt32(),
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
operation.GetSource(1));
|
||||
break;
|
||||
case IntrinsicType.VectorBinaryFPByElem:
|
||||
Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryFPByElem(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
(uint)operation.GetSource(2).AsInt32(),
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
operation.GetSource(1));
|
||||
break;
|
||||
case IntrinsicType.VectorBinaryRd:
|
||||
GenerateVectorUnary(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(1));
|
||||
break;
|
||||
case IntrinsicType.VectorBinaryShl:
|
||||
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryShlImm(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
(uint)operation.GetSource(1).AsInt32());
|
||||
break;
|
||||
case IntrinsicType.VectorBinaryShr:
|
||||
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryShrImm(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
(uint)operation.GetSource(1).AsInt32());
|
||||
break;
|
||||
case IntrinsicType.VectorFPConvFixed:
|
||||
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryShrImm(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
((uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift) + 2u,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
(uint)operation.GetSource(1).AsInt32());
|
||||
break;
|
||||
case IntrinsicType.VectorInsertByElem:
|
||||
Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
|
||||
Debug.Assert(operation.GetSource(3).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorInsertByElem(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
(uint)operation.GetSource(3).AsInt32(),
|
||||
(uint)operation.GetSource(1).AsInt32(),
|
||||
operation.Destination,
|
||||
operation.GetSource(2));
|
||||
break;
|
||||
case IntrinsicType.VectorLookupTable:
|
||||
Debug.Assert((uint)(operation.SourcesCount - 2) <= 3);
|
||||
|
||||
for (int i = 1; i < operation.SourcesCount - 1; i++)
|
||||
{
|
||||
Register currReg = operation.GetSource(i).GetRegister();
|
||||
Register prevReg = operation.GetSource(i - 1).GetRegister();
|
||||
|
||||
Debug.Assert(prevReg.Index + 1 == currReg.Index && currReg.Type == RegisterType.Vector);
|
||||
}
|
||||
|
||||
GenerateVectorBinary(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
info.Inst | ((uint)(operation.SourcesCount - 2) << 13),
|
||||
operation.Destination,
|
||||
operation.GetSource(0),
|
||||
operation.GetSource(operation.SourcesCount - 1));
|
||||
break;
|
||||
case IntrinsicType.VectorTernaryFPRdByElem:
|
||||
Debug.Assert(operation.GetSource(3).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryFPByElem(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
(uint)operation.GetSource(3).AsInt32(),
|
||||
operation.Destination,
|
||||
operation.GetSource(1),
|
||||
operation.GetSource(2));
|
||||
break;
|
||||
case IntrinsicType.VectorTernaryRd:
|
||||
GenerateVectorBinary(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(1),
|
||||
operation.GetSource(2));
|
||||
break;
|
||||
case IntrinsicType.VectorTernaryRdBitwise:
|
||||
GenerateVectorBinary(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(1),
|
||||
operation.GetSource(2));
|
||||
break;
|
||||
case IntrinsicType.VectorTernaryRdByElem:
|
||||
Debug.Assert(operation.GetSource(3).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryByElem(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
(uint)operation.GetSource(3).AsInt32(),
|
||||
operation.Destination,
|
||||
operation.GetSource(1),
|
||||
operation.GetSource(2));
|
||||
break;
|
||||
case IntrinsicType.VectorTernaryShlRd:
|
||||
Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryShlImm(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(1),
|
||||
(uint)operation.GetSource(2).AsInt32());
|
||||
break;
|
||||
case IntrinsicType.VectorTernaryShrRd:
|
||||
Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
|
||||
|
||||
GenerateVectorBinaryShrImm(
|
||||
context,
|
||||
(uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
|
||||
(uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
|
||||
info.Inst,
|
||||
operation.Destination,
|
||||
operation.GetSource(1),
|
||||
(uint)operation.GetSource(2).AsInt32());
|
||||
break;
|
||||
|
||||
case IntrinsicType.GetRegister:
|
||||
context.Assembler.WriteInstruction(info.Inst, operation.Destination);
|
||||
break;
|
||||
case IntrinsicType.SetRegister:
|
||||
context.Assembler.WriteInstruction(info.Inst, operation.GetSource(0));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException(info.Type.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private static void GenerateScalarFPCompare(
|
||||
CodeGenContext context,
|
||||
uint sz,
|
||||
uint instruction,
|
||||
Operand dest,
|
||||
Operand rn,
|
||||
Operand rm)
|
||||
{
|
||||
instruction |= (sz << 22);
|
||||
|
||||
if (rm.Kind == OperandKind.Constant && rm.Value == 0)
|
||||
{
|
||||
instruction |= 0b1000;
|
||||
rm = rn;
|
||||
}
|
||||
|
||||
context.Assembler.WriteInstructionRm16NoRet(instruction, rn, rm);
|
||||
context.Assembler.Mrs(dest, 1, 3, 4, 2, 0);
|
||||
}
|
||||
|
||||
private static void GenerateScalarFPConvGpr(
|
||||
CodeGenContext context,
|
||||
uint sz,
|
||||
uint instruction,
|
||||
Operand rd,
|
||||
Operand rn)
|
||||
{
|
||||
instruction |= (sz << 22);
|
||||
|
||||
if (rd.Type.IsInteger())
|
||||
{
|
||||
context.Assembler.WriteInstructionAuto(instruction, rd, rn);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rn.Type == OperandType.I64)
|
||||
{
|
||||
instruction |= Assembler.SfFlag;
|
||||
}
|
||||
|
||||
context.Assembler.WriteInstruction(instruction, rd, rn);
|
||||
}
|
||||
}
|
||||
|
||||
private static void GenerateScalarFPConvGpr(
|
||||
CodeGenContext context,
|
||||
uint sz,
|
||||
uint instruction,
|
||||
Operand rd,
|
||||
Operand rn,
|
||||
uint fBits)
|
||||
{
|
||||
Debug.Assert(fBits <= 64);
|
||||
|
||||
instruction |= (sz << 22);
|
||||
instruction |= (64 - fBits) << 10;
|
||||
|
||||
if (rd.Type.IsInteger())
|
||||
{
|
||||
Debug.Assert(rd.Type != OperandType.I32 || fBits <= 32);
|
||||
|
||||
context.Assembler.WriteInstructionAuto(instruction, rd, rn);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rn.Type == OperandType.I64)
|
||||
{
|
||||
instruction |= Assembler.SfFlag;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(fBits <= 32);
|
||||
}
|
||||
|
||||
context.Assembler.WriteInstruction(instruction, rd, rn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void GenerateScalarTernary(
|
||||
CodeGenContext context,
|
||||
uint sz,
|
||||
uint instruction,
|
||||
Operand rd,
|
||||
Operand rn,
|
||||
Operand rm,
|
||||
Operand ra)
|
||||
{
|
||||
instruction |= (sz << 22);
|
||||
|
||||
context.Assembler.WriteInstruction(instruction, rd, rn, rm, ra);
|
||||
}
|
||||
|
||||
private static void GenerateVectorUnary(
|
||||
CodeGenContext context,
|
||||
uint q,
|
||||
uint sz,
|
||||
uint instruction,
|
||||
Operand rd,
|
||||
Operand rn)
|
||||
{
|
||||
instruction |= (q << 30) | (sz << 22);
|
||||
|
||||
context.Assembler.WriteInstruction(instruction, rd, rn);
|
||||
}
|
||||
|
||||
private static void GenerateVectorUnaryByElem(
|
||||
CodeGenContext context,
|
||||
uint q,
|
||||
uint sz,
|
||||
uint instruction,
|
||||
uint srcIndex,
|
||||
Operand rd,
|
||||
Operand rn)
|
||||
{
|
||||
uint imm5 = (srcIndex << ((int)sz + 1)) | (1u << (int)sz);
|
||||
|
||||
instruction |= (q << 30) | (imm5 << 16);
|
||||
|
||||
context.Assembler.WriteInstruction(instruction, rd, rn);
|
||||
}
|
||||
|
||||
private static void GenerateVectorBinary(
|
||||
CodeGenContext context,
|
||||
uint q,
|
||||
uint instruction,
|
||||
Operand rd,
|
||||
Operand rn,
|
||||
Operand rm)
|
||||
{
|
||||
instruction |= (q << 30);
|
||||
|
||||
context.Assembler.WriteInstructionRm16(instruction, rd, rn, rm);
|
||||
}
|
||||
|
||||
private static void GenerateVectorBinary(
|
||||
CodeGenContext context,
|
||||
uint q,
|
||||
uint sz,
|
||||
uint instruction,
|
||||
Operand rd,
|
||||
Operand rn,
|
||||
Operand rm)
|
||||
{
|
||||
instruction |= (q << 30) | (sz << 22);
|
||||
|
||||
context.Assembler.WriteInstructionRm16(instruction, rd, rn, rm);
|
||||
}
|
||||
|
||||
private static void GenerateVectorBinaryByElem(
|
||||
CodeGenContext context,
|
||||
uint q,
|
||||
uint size,
|
||||
uint instruction,
|
||||
uint srcIndex,
|
||||
Operand rd,
|
||||
Operand rn,
|
||||
Operand rm)
|
||||
{
|
||||
instruction |= (q << 30) | (size << 22);
|
||||
|
||||
if (size == 2)
|
||||
{
|
||||
instruction |= ((srcIndex & 1) << 21) | ((srcIndex & 2) << 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
instruction |= ((srcIndex & 3) << 20) | ((srcIndex & 4) << 9);
|
||||
}
|
||||
|
||||
context.Assembler.WriteInstructionRm16(instruction, rd, rn, rm);
|
||||
}
|
||||
|
||||
private static void GenerateVectorBinaryFPByElem(
|
||||
CodeGenContext context,
|
||||
uint q,
|
||||
uint sz,
|
||||
uint instruction,
|
||||
uint srcIndex,
|
||||
Operand rd,
|
||||
Operand rn,
|
||||
Operand rm)
|
||||
{
|
||||
instruction |= (q << 30) | (sz << 22);
|
||||
|
||||
if (sz != 0)
|
||||
{
|
||||
instruction |= (srcIndex & 1) << 11;
|
||||
}
|
||||
else
|
||||
{
|
||||
instruction |= ((srcIndex & 1) << 21) | ((srcIndex & 2) << 10);
|
||||
}
|
||||
|
||||
context.Assembler.WriteInstructionRm16(instruction, rd, rn, rm);
|
||||
}
|
||||
|
||||
private static void GenerateVectorBinaryShlImm(
|
||||
CodeGenContext context,
|
||||
uint q,
|
||||
uint sz,
|
||||
uint instruction,
|
||||
Operand rd,
|
||||
Operand rn,
|
||||
uint shift)
|
||||
{
|
||||
instruction |= (q << 30);
|
||||
|
||||
Debug.Assert(shift >= 0 && shift < (8u << (int)sz));
|
||||
|
||||
uint imm = (8u << (int)sz) | (shift & (0x3fu >> (int)(3 - sz)));
|
||||
|
||||
instruction |= (imm << 16);
|
||||
|
||||
context.Assembler.WriteInstruction(instruction, rd, rn);
|
||||
}
|
||||
|
||||
private static void GenerateVectorBinaryShrImm(
|
||||
CodeGenContext context,
|
||||
uint q,
|
||||
uint sz,
|
||||
uint instruction,
|
||||
Operand rd,
|
||||
Operand rn,
|
||||
uint shift)
|
||||
{
|
||||
instruction |= (q << 30);
|
||||
|
||||
Debug.Assert(shift > 0 && shift <= (8u << (int)sz));
|
||||
|
||||
uint imm = (8u << (int)sz) | ((8u << (int)sz) - shift);
|
||||
|
||||
instruction |= (imm << 16);
|
||||
|
||||
context.Assembler.WriteInstruction(instruction, rd, rn);
|
||||
}
|
||||
|
||||
private static void GenerateVectorInsertByElem(
|
||||
CodeGenContext context,
|
||||
uint sz,
|
||||
uint instruction,
|
||||
uint srcIndex,
|
||||
uint dstIndex,
|
||||
Operand rd,
|
||||
Operand rn)
|
||||
{
|
||||
uint imm4 = srcIndex << (int)sz;
|
||||
uint imm5 = (dstIndex << ((int)sz + 1)) | (1u << (int)sz);
|
||||
|
||||
instruction |= imm4 << 11;
|
||||
instruction |= imm5 << 16;
|
||||
|
||||
context.Assembler.WriteInstruction(instruction, rd, rn);
|
||||
}
|
||||
}
|
||||
}
|
185
ARMeilleure/CodeGen/Arm64/HardwareCapabilities.cs
Normal file
185
ARMeilleure/CodeGen/Arm64/HardwareCapabilities.cs
Normal file
@ -0,0 +1,185 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics.Arm;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
static partial class HardwareCapabilities
|
||||
{
|
||||
static HardwareCapabilities()
|
||||
{
|
||||
if (!ArmBase.Arm64.IsSupported)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsLinux())
|
||||
{
|
||||
LinuxFeatureInfoHwCap = (LinuxFeatureFlagsHwCap)getauxval(AT_HWCAP);
|
||||
LinuxFeatureInfoHwCap2 = (LinuxFeatureFlagsHwCap2)getauxval(AT_HWCAP2);
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
for (int i = 0; i < _sysctlNames.Length; i++)
|
||||
{
|
||||
if (CheckSysctlName(_sysctlNames[i]))
|
||||
{
|
||||
MacOsFeatureInfo |= (MacOsFeatureFlags)(1 << i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Linux
|
||||
|
||||
private const ulong AT_HWCAP = 16;
|
||||
private const ulong AT_HWCAP2 = 26;
|
||||
|
||||
[LibraryImport("libc", SetLastError = true)]
|
||||
private static partial ulong getauxval(ulong type);
|
||||
|
||||
[Flags]
|
||||
public enum LinuxFeatureFlagsHwCap : ulong
|
||||
{
|
||||
Fp = 1 << 0,
|
||||
Asimd = 1 << 1,
|
||||
Evtstrm = 1 << 2,
|
||||
Aes = 1 << 3,
|
||||
Pmull = 1 << 4,
|
||||
Sha1 = 1 << 5,
|
||||
Sha2 = 1 << 6,
|
||||
Crc32 = 1 << 7,
|
||||
Atomics = 1 << 8,
|
||||
FpHp = 1 << 9,
|
||||
AsimdHp = 1 << 10,
|
||||
CpuId = 1 << 11,
|
||||
AsimdRdm = 1 << 12,
|
||||
Jscvt = 1 << 13,
|
||||
Fcma = 1 << 14,
|
||||
Lrcpc = 1 << 15,
|
||||
DcpOp = 1 << 16,
|
||||
Sha3 = 1 << 17,
|
||||
Sm3 = 1 << 18,
|
||||
Sm4 = 1 << 19,
|
||||
AsimdDp = 1 << 20,
|
||||
Sha512 = 1 << 21,
|
||||
Sve = 1 << 22,
|
||||
AsimdFhm = 1 << 23,
|
||||
Dit = 1 << 24,
|
||||
Uscat = 1 << 25,
|
||||
Ilrcpc = 1 << 26,
|
||||
FlagM = 1 << 27,
|
||||
Ssbs = 1 << 28,
|
||||
Sb = 1 << 29,
|
||||
Paca = 1 << 30,
|
||||
Pacg = 1UL << 31
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum LinuxFeatureFlagsHwCap2 : ulong
|
||||
{
|
||||
Dcpodp = 1 << 0,
|
||||
Sve2 = 1 << 1,
|
||||
SveAes = 1 << 2,
|
||||
SvePmull = 1 << 3,
|
||||
SveBitperm = 1 << 4,
|
||||
SveSha3 = 1 << 5,
|
||||
SveSm4 = 1 << 6,
|
||||
FlagM2 = 1 << 7,
|
||||
Frint = 1 << 8,
|
||||
SveI8mm = 1 << 9,
|
||||
SveF32mm = 1 << 10,
|
||||
SveF64mm = 1 << 11,
|
||||
SveBf16 = 1 << 12,
|
||||
I8mm = 1 << 13,
|
||||
Bf16 = 1 << 14,
|
||||
Dgh = 1 << 15,
|
||||
Rng = 1 << 16,
|
||||
Bti = 1 << 17,
|
||||
Mte = 1 << 18,
|
||||
Ecv = 1 << 19,
|
||||
Afp = 1 << 20,
|
||||
Rpres = 1 << 21,
|
||||
Mte3 = 1 << 22,
|
||||
Sme = 1 << 23,
|
||||
Sme_i16i64 = 1 << 24,
|
||||
Sme_f64f64 = 1 << 25,
|
||||
Sme_i8i32 = 1 << 26,
|
||||
Sme_f16f32 = 1 << 27,
|
||||
Sme_b16f32 = 1 << 28,
|
||||
Sme_f32f32 = 1 << 29,
|
||||
Sme_fa64 = 1 << 30,
|
||||
Wfxt = 1UL << 31,
|
||||
Ebf16 = 1UL << 32,
|
||||
Sve_Ebf16 = 1UL << 33,
|
||||
Cssc = 1UL << 34,
|
||||
Rprfm = 1UL << 35,
|
||||
Sve2p1 = 1UL << 36
|
||||
}
|
||||
|
||||
public static LinuxFeatureFlagsHwCap LinuxFeatureInfoHwCap { get; } = 0;
|
||||
public static LinuxFeatureFlagsHwCap2 LinuxFeatureInfoHwCap2 { get; } = 0;
|
||||
|
||||
#endregion
|
||||
|
||||
#region macOS
|
||||
|
||||
[LibraryImport("libSystem.dylib", SetLastError = true)]
|
||||
private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
|
||||
|
||||
[SupportedOSPlatform("macos")]
|
||||
private static bool CheckSysctlName(string name)
|
||||
{
|
||||
ulong size = sizeof(int);
|
||||
if (sysctlbyname(name, out int val, ref size, IntPtr.Zero, 0) == 0 && size == sizeof(int))
|
||||
{
|
||||
return val != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string[] _sysctlNames = new string[]
|
||||
{
|
||||
"hw.optional.floatingpoint",
|
||||
"hw.optional.AdvSIMD",
|
||||
"hw.optional.arm.FEAT_FP16",
|
||||
"hw.optional.arm.FEAT_AES",
|
||||
"hw.optional.arm.FEAT_PMULL",
|
||||
"hw.optional.arm.FEAT_LSE",
|
||||
"hw.optional.armv8_crc32",
|
||||
"hw.optional.arm.FEAT_SHA1",
|
||||
"hw.optional.arm.FEAT_SHA256"
|
||||
};
|
||||
|
||||
[Flags]
|
||||
public enum MacOsFeatureFlags
|
||||
{
|
||||
Fp = 1 << 0,
|
||||
AdvSimd = 1 << 1,
|
||||
Fp16 = 1 << 2,
|
||||
Aes = 1 << 3,
|
||||
Pmull = 1 << 4,
|
||||
Lse = 1 << 5,
|
||||
Crc32 = 1 << 6,
|
||||
Sha1 = 1 << 7,
|
||||
Sha256 = 1 << 8
|
||||
}
|
||||
|
||||
public static MacOsFeatureFlags MacOsFeatureInfo { get; } = 0;
|
||||
|
||||
#endregion
|
||||
|
||||
public static bool SupportsAdvSimd => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Asimd) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.AdvSimd);
|
||||
public static bool SupportsAes => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Aes) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Aes);
|
||||
public static bool SupportsPmull => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Pmull) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Pmull);
|
||||
public static bool SupportsLse => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Atomics) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Lse);
|
||||
public static bool SupportsCrc32 => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Crc32) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Crc32);
|
||||
public static bool SupportsSha1 => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Sha1) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Sha1);
|
||||
public static bool SupportsSha256 => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Sha2) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Sha256);
|
||||
}
|
||||
}
|
14
ARMeilleure/CodeGen/Arm64/IntrinsicInfo.cs
Normal file
14
ARMeilleure/CodeGen/Arm64/IntrinsicInfo.cs
Normal file
@ -0,0 +1,14 @@
|
||||
namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
struct IntrinsicInfo
|
||||
{
|
||||
public uint Inst { get; }
|
||||
public IntrinsicType Type { get; }
|
||||
|
||||
public IntrinsicInfo(uint inst, IntrinsicType type)
|
||||
{
|
||||
Inst = inst;
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
}
|
461
ARMeilleure/CodeGen/Arm64/IntrinsicTable.cs
Normal file
461
ARMeilleure/CodeGen/Arm64/IntrinsicTable.cs
Normal file
@ -0,0 +1,461 @@
|
||||
using ARMeilleure.Common;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
|
||||
namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
static class IntrinsicTable
|
||||
{
|
||||
private static IntrinsicInfo[] _intrinTable;
|
||||
|
||||
static IntrinsicTable()
|
||||
{
|
||||
_intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))];
|
||||
|
||||
Add(Intrinsic.Arm64AbsS, new IntrinsicInfo(0x5e20b800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64AbsV, new IntrinsicInfo(0x0e20b800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64AddhnV, new IntrinsicInfo(0x0e204000u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64AddpS, new IntrinsicInfo(0x5e31b800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64AddpV, new IntrinsicInfo(0x0e20bc00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64AddvV, new IntrinsicInfo(0x0e31b800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64AddS, new IntrinsicInfo(0x5e208400u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64AddV, new IntrinsicInfo(0x0e208400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64AesdV, new IntrinsicInfo(0x4e285800u, IntrinsicType.Vector128Unary));
|
||||
Add(Intrinsic.Arm64AeseV, new IntrinsicInfo(0x4e284800u, IntrinsicType.Vector128Unary));
|
||||
Add(Intrinsic.Arm64AesimcV, new IntrinsicInfo(0x4e287800u, IntrinsicType.Vector128Unary));
|
||||
Add(Intrinsic.Arm64AesmcV, new IntrinsicInfo(0x4e286800u, IntrinsicType.Vector128Unary));
|
||||
Add(Intrinsic.Arm64AndV, new IntrinsicInfo(0x0e201c00u, IntrinsicType.VectorBinaryBitwise));
|
||||
Add(Intrinsic.Arm64BicVi, new IntrinsicInfo(0x2f001400u, IntrinsicType.VectorBinaryBitwiseImm));
|
||||
Add(Intrinsic.Arm64BicV, new IntrinsicInfo(0x0e601c00u, IntrinsicType.VectorBinaryBitwise));
|
||||
Add(Intrinsic.Arm64BifV, new IntrinsicInfo(0x2ee01c00u, IntrinsicType.VectorTernaryRdBitwise));
|
||||
Add(Intrinsic.Arm64BitV, new IntrinsicInfo(0x2ea01c00u, IntrinsicType.VectorTernaryRdBitwise));
|
||||
Add(Intrinsic.Arm64BslV, new IntrinsicInfo(0x2e601c00u, IntrinsicType.VectorTernaryRdBitwise));
|
||||
Add(Intrinsic.Arm64ClsV, new IntrinsicInfo(0x0e204800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64ClzV, new IntrinsicInfo(0x2e204800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64CmeqS, new IntrinsicInfo(0x7e208c00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64CmeqV, new IntrinsicInfo(0x2e208c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64CmeqSz, new IntrinsicInfo(0x5e209800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64CmeqVz, new IntrinsicInfo(0x0e209800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64CmgeS, new IntrinsicInfo(0x5e203c00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64CmgeV, new IntrinsicInfo(0x0e203c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64CmgeSz, new IntrinsicInfo(0x7e208800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64CmgeVz, new IntrinsicInfo(0x2e208800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64CmgtS, new IntrinsicInfo(0x5e203400u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64CmgtV, new IntrinsicInfo(0x0e203400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64CmgtSz, new IntrinsicInfo(0x5e208800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64CmgtVz, new IntrinsicInfo(0x0e208800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64CmhiS, new IntrinsicInfo(0x7e203400u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64CmhiV, new IntrinsicInfo(0x2e203400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64CmhsS, new IntrinsicInfo(0x7e203c00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64CmhsV, new IntrinsicInfo(0x2e203c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64CmleSz, new IntrinsicInfo(0x7e209800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64CmleVz, new IntrinsicInfo(0x2e209800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64CmltSz, new IntrinsicInfo(0x5e20a800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64CmltVz, new IntrinsicInfo(0x0e20a800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64CmtstS, new IntrinsicInfo(0x5e208c00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64CmtstV, new IntrinsicInfo(0x0e208c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64CntV, new IntrinsicInfo(0x0e205800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64DupSe, new IntrinsicInfo(0x5e000400u, IntrinsicType.ScalarUnaryByElem));
|
||||
Add(Intrinsic.Arm64DupVe, new IntrinsicInfo(0x0e000400u, IntrinsicType.VectorUnaryByElem));
|
||||
Add(Intrinsic.Arm64DupGp, new IntrinsicInfo(0x0e000c00u, IntrinsicType.VectorUnaryByElem));
|
||||
Add(Intrinsic.Arm64EorV, new IntrinsicInfo(0x2e201c00u, IntrinsicType.VectorBinaryBitwise));
|
||||
Add(Intrinsic.Arm64ExtV, new IntrinsicInfo(0x2e000000u, IntrinsicType.VectorExt));
|
||||
Add(Intrinsic.Arm64FabdS, new IntrinsicInfo(0x7ea0d400u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FabdV, new IntrinsicInfo(0x2ea0d400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FabsV, new IntrinsicInfo(0x0ea0f800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FabsS, new IntrinsicInfo(0x1e20c000u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FacgeS, new IntrinsicInfo(0x7e20ec00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FacgeV, new IntrinsicInfo(0x2e20ec00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FacgtS, new IntrinsicInfo(0x7ea0ec00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FacgtV, new IntrinsicInfo(0x2ea0ec00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FaddpS, new IntrinsicInfo(0x7e30d800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FaddpV, new IntrinsicInfo(0x2e20d400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FaddV, new IntrinsicInfo(0x0e20d400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FaddS, new IntrinsicInfo(0x1e202800u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FccmpeS, new IntrinsicInfo(0x1e200410u, IntrinsicType.ScalarFPCompareCond));
|
||||
Add(Intrinsic.Arm64FccmpS, new IntrinsicInfo(0x1e200400u, IntrinsicType.ScalarFPCompareCond));
|
||||
Add(Intrinsic.Arm64FcmeqS, new IntrinsicInfo(0x5e20e400u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FcmeqV, new IntrinsicInfo(0x0e20e400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FcmeqSz, new IntrinsicInfo(0x5ea0d800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcmeqVz, new IntrinsicInfo(0x0ea0d800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcmgeS, new IntrinsicInfo(0x7e20e400u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FcmgeV, new IntrinsicInfo(0x2e20e400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FcmgeSz, new IntrinsicInfo(0x7ea0c800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcmgeVz, new IntrinsicInfo(0x2ea0c800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcmgtS, new IntrinsicInfo(0x7ea0e400u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FcmgtV, new IntrinsicInfo(0x2ea0e400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FcmgtSz, new IntrinsicInfo(0x5ea0c800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcmgtVz, new IntrinsicInfo(0x0ea0c800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcmleSz, new IntrinsicInfo(0x7ea0d800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcmleVz, new IntrinsicInfo(0x2ea0d800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcmltSz, new IntrinsicInfo(0x5ea0e800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcmltVz, new IntrinsicInfo(0x0ea0e800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcmpeS, new IntrinsicInfo(0x1e202010u, IntrinsicType.ScalarFPCompare));
|
||||
Add(Intrinsic.Arm64FcmpS, new IntrinsicInfo(0x1e202000u, IntrinsicType.ScalarFPCompare));
|
||||
Add(Intrinsic.Arm64FcselS, new IntrinsicInfo(0x1e200c00u, IntrinsicType.ScalarFcsel));
|
||||
Add(Intrinsic.Arm64FcvtasS, new IntrinsicInfo(0x5e21c800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcvtasV, new IntrinsicInfo(0x0e21c800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcvtasGp, new IntrinsicInfo(0x1e240000u, IntrinsicType.ScalarFPConvGpr));
|
||||
Add(Intrinsic.Arm64FcvtauS, new IntrinsicInfo(0x7e21c800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcvtauV, new IntrinsicInfo(0x2e21c800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcvtauGp, new IntrinsicInfo(0x1e250000u, IntrinsicType.ScalarFPConvGpr));
|
||||
Add(Intrinsic.Arm64FcvtlV, new IntrinsicInfo(0x0e217800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcvtmsS, new IntrinsicInfo(0x5e21b800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcvtmsV, new IntrinsicInfo(0x0e21b800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcvtmsGp, new IntrinsicInfo(0x1e300000u, IntrinsicType.ScalarFPConvGpr));
|
||||
Add(Intrinsic.Arm64FcvtmuS, new IntrinsicInfo(0x7e21b800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcvtmuV, new IntrinsicInfo(0x2e21b800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcvtmuGp, new IntrinsicInfo(0x1e310000u, IntrinsicType.ScalarFPConvGpr));
|
||||
Add(Intrinsic.Arm64FcvtnsS, new IntrinsicInfo(0x5e21a800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcvtnsV, new IntrinsicInfo(0x0e21a800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcvtnsGp, new IntrinsicInfo(0x1e200000u, IntrinsicType.ScalarFPConvGpr));
|
||||
Add(Intrinsic.Arm64FcvtnuS, new IntrinsicInfo(0x7e21a800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcvtnuV, new IntrinsicInfo(0x2e21a800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcvtnuGp, new IntrinsicInfo(0x1e210000u, IntrinsicType.ScalarFPConvGpr));
|
||||
Add(Intrinsic.Arm64FcvtnV, new IntrinsicInfo(0x0e216800u, IntrinsicType.VectorBinaryRd));
|
||||
Add(Intrinsic.Arm64FcvtpsS, new IntrinsicInfo(0x5ea1a800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcvtpsV, new IntrinsicInfo(0x0ea1a800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcvtpsGp, new IntrinsicInfo(0x1e280000u, IntrinsicType.ScalarFPConvGpr));
|
||||
Add(Intrinsic.Arm64FcvtpuS, new IntrinsicInfo(0x7ea1a800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcvtpuV, new IntrinsicInfo(0x2ea1a800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcvtpuGp, new IntrinsicInfo(0x1e290000u, IntrinsicType.ScalarFPConvGpr));
|
||||
Add(Intrinsic.Arm64FcvtxnS, new IntrinsicInfo(0x7e216800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcvtxnV, new IntrinsicInfo(0x2e216800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcvtzsSFixed, new IntrinsicInfo(0x5f00fc00u, IntrinsicType.ScalarFPConvFixed));
|
||||
Add(Intrinsic.Arm64FcvtzsVFixed, new IntrinsicInfo(0x0f00fc00u, IntrinsicType.VectorFPConvFixed));
|
||||
Add(Intrinsic.Arm64FcvtzsS, new IntrinsicInfo(0x5ea1b800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcvtzsV, new IntrinsicInfo(0x0ea1b800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcvtzsGpFixed, new IntrinsicInfo(0x1e180000u, IntrinsicType.ScalarFPConvFixedGpr));
|
||||
Add(Intrinsic.Arm64FcvtzsGp, new IntrinsicInfo(0x1e380000u, IntrinsicType.ScalarFPConvGpr));
|
||||
Add(Intrinsic.Arm64FcvtzuSFixed, new IntrinsicInfo(0x7f00fc00u, IntrinsicType.ScalarFPConvFixed));
|
||||
Add(Intrinsic.Arm64FcvtzuVFixed, new IntrinsicInfo(0x2f00fc00u, IntrinsicType.VectorFPConvFixed));
|
||||
Add(Intrinsic.Arm64FcvtzuS, new IntrinsicInfo(0x7ea1b800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FcvtzuV, new IntrinsicInfo(0x2ea1b800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FcvtzuGpFixed, new IntrinsicInfo(0x1e190000u, IntrinsicType.ScalarFPConvFixedGpr));
|
||||
Add(Intrinsic.Arm64FcvtzuGp, new IntrinsicInfo(0x1e390000u, IntrinsicType.ScalarFPConvGpr));
|
||||
Add(Intrinsic.Arm64FcvtS, new IntrinsicInfo(0x1e224000u, IntrinsicType.ScalarFPConv));
|
||||
Add(Intrinsic.Arm64FdivV, new IntrinsicInfo(0x2e20fc00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FdivS, new IntrinsicInfo(0x1e201800u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FmaddS, new IntrinsicInfo(0x1f000000u, IntrinsicType.ScalarTernary));
|
||||
Add(Intrinsic.Arm64FmaxnmpS, new IntrinsicInfo(0x7e30c800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FmaxnmpV, new IntrinsicInfo(0x2e20c400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FmaxnmvV, new IntrinsicInfo(0x2e30c800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FmaxnmV, new IntrinsicInfo(0x0e20c400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FmaxnmS, new IntrinsicInfo(0x1e206800u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FmaxpS, new IntrinsicInfo(0x7e30f800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FmaxpV, new IntrinsicInfo(0x2e20f400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FmaxvV, new IntrinsicInfo(0x2e30f800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FmaxV, new IntrinsicInfo(0x0e20f400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FmaxS, new IntrinsicInfo(0x1e204800u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FminnmpS, new IntrinsicInfo(0x7eb0c800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FminnmpV, new IntrinsicInfo(0x2ea0c400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FminnmvV, new IntrinsicInfo(0x2eb0c800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FminnmV, new IntrinsicInfo(0x0ea0c400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FminnmS, new IntrinsicInfo(0x1e207800u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FminpS, new IntrinsicInfo(0x7eb0f800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FminpV, new IntrinsicInfo(0x2ea0f400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FminvV, new IntrinsicInfo(0x2eb0f800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FminV, new IntrinsicInfo(0x0ea0f400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FminS, new IntrinsicInfo(0x1e205800u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FmlaSe, new IntrinsicInfo(0x5f801000u, IntrinsicType.ScalarTernaryFPRdByElem));
|
||||
Add(Intrinsic.Arm64FmlaVe, new IntrinsicInfo(0x0f801000u, IntrinsicType.VectorTernaryFPRdByElem));
|
||||
Add(Intrinsic.Arm64FmlaV, new IntrinsicInfo(0x0e20cc00u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64FmlsSe, new IntrinsicInfo(0x5f805000u, IntrinsicType.ScalarTernaryFPRdByElem));
|
||||
Add(Intrinsic.Arm64FmlsVe, new IntrinsicInfo(0x0f805000u, IntrinsicType.VectorTernaryFPRdByElem));
|
||||
Add(Intrinsic.Arm64FmlsV, new IntrinsicInfo(0x0ea0cc00u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64FmovVi, new IntrinsicInfo(0x0f00f400u, IntrinsicType.VectorFmovi));
|
||||
Add(Intrinsic.Arm64FmovS, new IntrinsicInfo(0x1e204000u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FmovGp, new IntrinsicInfo(0x1e260000u, IntrinsicType.ScalarFPConvGpr));
|
||||
Add(Intrinsic.Arm64FmovSi, new IntrinsicInfo(0x1e201000u, IntrinsicType.ScalarFmovi));
|
||||
Add(Intrinsic.Arm64FmsubS, new IntrinsicInfo(0x1f008000u, IntrinsicType.ScalarTernary));
|
||||
Add(Intrinsic.Arm64FmulxSe, new IntrinsicInfo(0x7f809000u, IntrinsicType.ScalarBinaryFPByElem));
|
||||
Add(Intrinsic.Arm64FmulxVe, new IntrinsicInfo(0x2f809000u, IntrinsicType.VectorBinaryFPByElem));
|
||||
Add(Intrinsic.Arm64FmulxS, new IntrinsicInfo(0x5e20dc00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FmulxV, new IntrinsicInfo(0x0e20dc00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FmulSe, new IntrinsicInfo(0x5f809000u, IntrinsicType.ScalarBinaryFPByElem));
|
||||
Add(Intrinsic.Arm64FmulVe, new IntrinsicInfo(0x0f809000u, IntrinsicType.VectorBinaryFPByElem));
|
||||
Add(Intrinsic.Arm64FmulV, new IntrinsicInfo(0x2e20dc00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FmulS, new IntrinsicInfo(0x1e200800u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FnegV, new IntrinsicInfo(0x2ea0f800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FnegS, new IntrinsicInfo(0x1e214000u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FnmaddS, new IntrinsicInfo(0x1f200000u, IntrinsicType.ScalarTernary));
|
||||
Add(Intrinsic.Arm64FnmsubS, new IntrinsicInfo(0x1f208000u, IntrinsicType.ScalarTernary));
|
||||
Add(Intrinsic.Arm64FnmulS, new IntrinsicInfo(0x1e208800u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FrecpeS, new IntrinsicInfo(0x5ea1d800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FrecpeV, new IntrinsicInfo(0x0ea1d800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FrecpsS, new IntrinsicInfo(0x5e20fc00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FrecpsV, new IntrinsicInfo(0x0e20fc00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FrecpxS, new IntrinsicInfo(0x5ea1f800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FrintaV, new IntrinsicInfo(0x2e218800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FrintaS, new IntrinsicInfo(0x1e264000u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FrintiV, new IntrinsicInfo(0x2ea19800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FrintiS, new IntrinsicInfo(0x1e27c000u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FrintmV, new IntrinsicInfo(0x0e219800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FrintmS, new IntrinsicInfo(0x1e254000u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FrintnV, new IntrinsicInfo(0x0e218800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FrintnS, new IntrinsicInfo(0x1e244000u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FrintpV, new IntrinsicInfo(0x0ea18800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FrintpS, new IntrinsicInfo(0x1e24c000u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FrintxV, new IntrinsicInfo(0x2e219800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FrintxS, new IntrinsicInfo(0x1e274000u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FrintzV, new IntrinsicInfo(0x0ea19800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FrintzS, new IntrinsicInfo(0x1e25c000u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FrsqrteS, new IntrinsicInfo(0x7ea1d800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FrsqrteV, new IntrinsicInfo(0x2ea1d800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FrsqrtsS, new IntrinsicInfo(0x5ea0fc00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64FrsqrtsV, new IntrinsicInfo(0x0ea0fc00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FsqrtV, new IntrinsicInfo(0x2ea1f800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64FsqrtS, new IntrinsicInfo(0x1e21c000u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64FsubV, new IntrinsicInfo(0x0ea0d400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64FsubS, new IntrinsicInfo(0x1e203800u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64InsVe, new IntrinsicInfo(0x6e000400u, IntrinsicType.VectorInsertByElem));
|
||||
Add(Intrinsic.Arm64InsGp, new IntrinsicInfo(0x4e001c00u, IntrinsicType.ScalarUnaryByElem));
|
||||
Add(Intrinsic.Arm64Ld1rV, new IntrinsicInfo(0x0d40c000u, IntrinsicType.VectorLdSt));
|
||||
Add(Intrinsic.Arm64Ld1Vms, new IntrinsicInfo(0x0c402000u, IntrinsicType.VectorLdSt));
|
||||
Add(Intrinsic.Arm64Ld1Vss, new IntrinsicInfo(0x0d400000u, IntrinsicType.VectorLdStSs));
|
||||
Add(Intrinsic.Arm64Ld2rV, new IntrinsicInfo(0x0d60c000u, IntrinsicType.VectorLdSt));
|
||||
Add(Intrinsic.Arm64Ld2Vms, new IntrinsicInfo(0x0c408000u, IntrinsicType.VectorLdSt));
|
||||
Add(Intrinsic.Arm64Ld2Vss, new IntrinsicInfo(0x0d600000u, IntrinsicType.VectorLdStSs));
|
||||
Add(Intrinsic.Arm64Ld3rV, new IntrinsicInfo(0x0d40e000u, IntrinsicType.VectorLdSt));
|
||||
Add(Intrinsic.Arm64Ld3Vms, new IntrinsicInfo(0x0c404000u, IntrinsicType.VectorLdSt));
|
||||
Add(Intrinsic.Arm64Ld3Vss, new IntrinsicInfo(0x0d402000u, IntrinsicType.VectorLdStSs));
|
||||
Add(Intrinsic.Arm64Ld4rV, new IntrinsicInfo(0x0d60e000u, IntrinsicType.VectorLdSt));
|
||||
Add(Intrinsic.Arm64Ld4Vms, new IntrinsicInfo(0x0c400000u, IntrinsicType.VectorLdSt));
|
||||
Add(Intrinsic.Arm64Ld4Vss, new IntrinsicInfo(0x0d602000u, IntrinsicType.VectorLdStSs));
|
||||
Add(Intrinsic.Arm64MlaVe, new IntrinsicInfo(0x2f000000u, IntrinsicType.VectorTernaryRdByElem));
|
||||
Add(Intrinsic.Arm64MlaV, new IntrinsicInfo(0x0e209400u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64MlsVe, new IntrinsicInfo(0x2f004000u, IntrinsicType.VectorTernaryRdByElem));
|
||||
Add(Intrinsic.Arm64MlsV, new IntrinsicInfo(0x2e209400u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64MoviV, new IntrinsicInfo(0x0f000400u, IntrinsicType.VectorMovi));
|
||||
Add(Intrinsic.Arm64MrsFpsr, new IntrinsicInfo(0xd53b4420u, IntrinsicType.GetRegister));
|
||||
Add(Intrinsic.Arm64MsrFpsr, new IntrinsicInfo(0xd51b4420u, IntrinsicType.SetRegister));
|
||||
Add(Intrinsic.Arm64MulVe, new IntrinsicInfo(0x0f008000u, IntrinsicType.VectorBinaryByElem));
|
||||
Add(Intrinsic.Arm64MulV, new IntrinsicInfo(0x0e209c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64MvniV, new IntrinsicInfo(0x2f000400u, IntrinsicType.VectorMvni));
|
||||
Add(Intrinsic.Arm64NegS, new IntrinsicInfo(0x7e20b800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64NegV, new IntrinsicInfo(0x2e20b800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64NotV, new IntrinsicInfo(0x2e205800u, IntrinsicType.VectorUnaryBitwise));
|
||||
Add(Intrinsic.Arm64OrnV, new IntrinsicInfo(0x0ee01c00u, IntrinsicType.VectorBinaryBitwise));
|
||||
Add(Intrinsic.Arm64OrrVi, new IntrinsicInfo(0x0f001400u, IntrinsicType.VectorBinaryBitwiseImm));
|
||||
Add(Intrinsic.Arm64OrrV, new IntrinsicInfo(0x0ea01c00u, IntrinsicType.VectorBinaryBitwise));
|
||||
Add(Intrinsic.Arm64PmullV, new IntrinsicInfo(0x0e20e000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64PmulV, new IntrinsicInfo(0x2e209c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64RaddhnV, new IntrinsicInfo(0x2e204000u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64RbitV, new IntrinsicInfo(0x2e605800u, IntrinsicType.VectorUnaryBitwise));
|
||||
Add(Intrinsic.Arm64Rev16V, new IntrinsicInfo(0x0e201800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64Rev32V, new IntrinsicInfo(0x2e200800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64Rev64V, new IntrinsicInfo(0x0e200800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64RshrnV, new IntrinsicInfo(0x0f008c00u, IntrinsicType.VectorTernaryShrRd));
|
||||
Add(Intrinsic.Arm64RsubhnV, new IntrinsicInfo(0x2e206000u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64SabalV, new IntrinsicInfo(0x0e205000u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64SabaV, new IntrinsicInfo(0x0e207c00u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64SabdlV, new IntrinsicInfo(0x0e207000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SabdV, new IntrinsicInfo(0x0e207400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SadalpV, new IntrinsicInfo(0x0e206800u, IntrinsicType.VectorBinaryRd));
|
||||
Add(Intrinsic.Arm64SaddlpV, new IntrinsicInfo(0x0e202800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64SaddlvV, new IntrinsicInfo(0x0e303800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64SaddlV, new IntrinsicInfo(0x0e200000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SaddwV, new IntrinsicInfo(0x0e201000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64ScvtfSFixed, new IntrinsicInfo(0x5f00e400u, IntrinsicType.ScalarFPConvFixed));
|
||||
Add(Intrinsic.Arm64ScvtfVFixed, new IntrinsicInfo(0x0f00e400u, IntrinsicType.VectorFPConvFixed));
|
||||
Add(Intrinsic.Arm64ScvtfS, new IntrinsicInfo(0x5e21d800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64ScvtfV, new IntrinsicInfo(0x0e21d800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64ScvtfGpFixed, new IntrinsicInfo(0x1e020000u, IntrinsicType.ScalarFPConvFixedGpr));
|
||||
Add(Intrinsic.Arm64ScvtfGp, new IntrinsicInfo(0x1e220000u, IntrinsicType.ScalarFPConvGpr));
|
||||
Add(Intrinsic.Arm64Sha1cV, new IntrinsicInfo(0x5e000000u, IntrinsicType.Vector128Binary));
|
||||
Add(Intrinsic.Arm64Sha1hV, new IntrinsicInfo(0x5e280800u, IntrinsicType.Vector128Unary));
|
||||
Add(Intrinsic.Arm64Sha1mV, new IntrinsicInfo(0x5e002000u, IntrinsicType.Vector128Binary));
|
||||
Add(Intrinsic.Arm64Sha1pV, new IntrinsicInfo(0x5e001000u, IntrinsicType.Vector128Binary));
|
||||
Add(Intrinsic.Arm64Sha1su0V, new IntrinsicInfo(0x5e003000u, IntrinsicType.Vector128Binary));
|
||||
Add(Intrinsic.Arm64Sha1su1V, new IntrinsicInfo(0x5e281800u, IntrinsicType.Vector128Unary));
|
||||
Add(Intrinsic.Arm64Sha256h2V, new IntrinsicInfo(0x5e005000u, IntrinsicType.Vector128Binary));
|
||||
Add(Intrinsic.Arm64Sha256hV, new IntrinsicInfo(0x5e004000u, IntrinsicType.Vector128Binary));
|
||||
Add(Intrinsic.Arm64Sha256su0V, new IntrinsicInfo(0x5e282800u, IntrinsicType.Vector128Unary));
|
||||
Add(Intrinsic.Arm64Sha256su1V, new IntrinsicInfo(0x5e006000u, IntrinsicType.Vector128Binary));
|
||||
Add(Intrinsic.Arm64ShaddV, new IntrinsicInfo(0x0e200400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64ShllV, new IntrinsicInfo(0x2e213800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64ShlS, new IntrinsicInfo(0x5f005400u, IntrinsicType.ScalarBinaryShl));
|
||||
Add(Intrinsic.Arm64ShlV, new IntrinsicInfo(0x0f005400u, IntrinsicType.VectorBinaryShl));
|
||||
Add(Intrinsic.Arm64ShrnV, new IntrinsicInfo(0x0f008400u, IntrinsicType.VectorTernaryShrRd));
|
||||
Add(Intrinsic.Arm64ShsubV, new IntrinsicInfo(0x0e202400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SliS, new IntrinsicInfo(0x7f005400u, IntrinsicType.ScalarTernaryShlRd));
|
||||
Add(Intrinsic.Arm64SliV, new IntrinsicInfo(0x2f005400u, IntrinsicType.VectorTernaryShlRd));
|
||||
Add(Intrinsic.Arm64SmaxpV, new IntrinsicInfo(0x0e20a400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SmaxvV, new IntrinsicInfo(0x0e30a800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64SmaxV, new IntrinsicInfo(0x0e206400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SminpV, new IntrinsicInfo(0x0e20ac00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SminvV, new IntrinsicInfo(0x0e31a800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64SminV, new IntrinsicInfo(0x0e206c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SmlalVe, new IntrinsicInfo(0x0f002000u, IntrinsicType.VectorTernaryRdByElem));
|
||||
Add(Intrinsic.Arm64SmlalV, new IntrinsicInfo(0x0e208000u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64SmlslVe, new IntrinsicInfo(0x0f006000u, IntrinsicType.VectorTernaryRdByElem));
|
||||
Add(Intrinsic.Arm64SmlslV, new IntrinsicInfo(0x0e20a000u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64SmovV, new IntrinsicInfo(0x0e002c00u, IntrinsicType.VectorUnaryByElem));
|
||||
Add(Intrinsic.Arm64SmullVe, new IntrinsicInfo(0x0f00a000u, IntrinsicType.VectorBinaryByElem));
|
||||
Add(Intrinsic.Arm64SmullV, new IntrinsicInfo(0x0e20c000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SqabsS, new IntrinsicInfo(0x5e207800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64SqabsV, new IntrinsicInfo(0x0e207800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64SqaddS, new IntrinsicInfo(0x5e200c00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64SqaddV, new IntrinsicInfo(0x0e200c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SqdmlalSe, new IntrinsicInfo(0x5f003000u, IntrinsicType.ScalarBinaryByElem));
|
||||
Add(Intrinsic.Arm64SqdmlalVe, new IntrinsicInfo(0x0f003000u, IntrinsicType.VectorBinaryByElem));
|
||||
Add(Intrinsic.Arm64SqdmlalS, new IntrinsicInfo(0x5e209000u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64SqdmlalV, new IntrinsicInfo(0x0e209000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SqdmlslSe, new IntrinsicInfo(0x5f007000u, IntrinsicType.ScalarBinaryByElem));
|
||||
Add(Intrinsic.Arm64SqdmlslVe, new IntrinsicInfo(0x0f007000u, IntrinsicType.VectorBinaryByElem));
|
||||
Add(Intrinsic.Arm64SqdmlslS, new IntrinsicInfo(0x5e20b000u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64SqdmlslV, new IntrinsicInfo(0x0e20b000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SqdmulhSe, new IntrinsicInfo(0x5f00c000u, IntrinsicType.ScalarBinaryByElem));
|
||||
Add(Intrinsic.Arm64SqdmulhVe, new IntrinsicInfo(0x0f00c000u, IntrinsicType.VectorBinaryByElem));
|
||||
Add(Intrinsic.Arm64SqdmulhS, new IntrinsicInfo(0x5e20b400u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64SqdmulhV, new IntrinsicInfo(0x0e20b400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SqdmullSe, new IntrinsicInfo(0x5f00b000u, IntrinsicType.ScalarBinaryByElem));
|
||||
Add(Intrinsic.Arm64SqdmullVe, new IntrinsicInfo(0x0f00b000u, IntrinsicType.VectorBinaryByElem));
|
||||
Add(Intrinsic.Arm64SqdmullS, new IntrinsicInfo(0x5e20d000u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64SqdmullV, new IntrinsicInfo(0x0e20d000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SqnegS, new IntrinsicInfo(0x7e207800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64SqnegV, new IntrinsicInfo(0x2e207800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64SqrdmulhSe, new IntrinsicInfo(0x5f00d000u, IntrinsicType.ScalarBinaryByElem));
|
||||
Add(Intrinsic.Arm64SqrdmulhVe, new IntrinsicInfo(0x0f00d000u, IntrinsicType.VectorBinaryByElem));
|
||||
Add(Intrinsic.Arm64SqrdmulhS, new IntrinsicInfo(0x7e20b400u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64SqrdmulhV, new IntrinsicInfo(0x2e20b400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SqrshlS, new IntrinsicInfo(0x5e205c00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64SqrshlV, new IntrinsicInfo(0x0e205c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SqrshrnS, new IntrinsicInfo(0x5f009c00u, IntrinsicType.ScalarTernaryShrRd));
|
||||
Add(Intrinsic.Arm64SqrshrnV, new IntrinsicInfo(0x0f009c00u, IntrinsicType.VectorTernaryShrRd));
|
||||
Add(Intrinsic.Arm64SqrshrunS, new IntrinsicInfo(0x7f008c00u, IntrinsicType.ScalarTernaryShrRd));
|
||||
Add(Intrinsic.Arm64SqrshrunV, new IntrinsicInfo(0x2f008c00u, IntrinsicType.VectorTernaryShrRd));
|
||||
Add(Intrinsic.Arm64SqshluS, new IntrinsicInfo(0x7f006400u, IntrinsicType.ScalarBinaryShl));
|
||||
Add(Intrinsic.Arm64SqshluV, new IntrinsicInfo(0x2f006400u, IntrinsicType.VectorBinaryShl));
|
||||
Add(Intrinsic.Arm64SqshlSi, new IntrinsicInfo(0x5f007400u, IntrinsicType.ScalarBinaryShl));
|
||||
Add(Intrinsic.Arm64SqshlVi, new IntrinsicInfo(0x0f007400u, IntrinsicType.VectorBinaryShl));
|
||||
Add(Intrinsic.Arm64SqshlS, new IntrinsicInfo(0x5e204c00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64SqshlV, new IntrinsicInfo(0x0e204c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SqshrnS, new IntrinsicInfo(0x5f009400u, IntrinsicType.ScalarTernaryShrRd));
|
||||
Add(Intrinsic.Arm64SqshrnV, new IntrinsicInfo(0x0f009400u, IntrinsicType.VectorTernaryShrRd));
|
||||
Add(Intrinsic.Arm64SqshrunS, new IntrinsicInfo(0x7f008400u, IntrinsicType.ScalarTernaryShrRd));
|
||||
Add(Intrinsic.Arm64SqshrunV, new IntrinsicInfo(0x2f008400u, IntrinsicType.VectorTernaryShrRd));
|
||||
Add(Intrinsic.Arm64SqsubS, new IntrinsicInfo(0x5e202c00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64SqsubV, new IntrinsicInfo(0x0e202c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SqxtnS, new IntrinsicInfo(0x5e214800u, IntrinsicType.ScalarBinaryRd));
|
||||
Add(Intrinsic.Arm64SqxtnV, new IntrinsicInfo(0x0e214800u, IntrinsicType.VectorBinaryRd));
|
||||
Add(Intrinsic.Arm64SqxtunS, new IntrinsicInfo(0x7e212800u, IntrinsicType.ScalarBinaryRd));
|
||||
Add(Intrinsic.Arm64SqxtunV, new IntrinsicInfo(0x2e212800u, IntrinsicType.VectorBinaryRd));
|
||||
Add(Intrinsic.Arm64SrhaddV, new IntrinsicInfo(0x0e201400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SriS, new IntrinsicInfo(0x7f004400u, IntrinsicType.ScalarTernaryShrRd));
|
||||
Add(Intrinsic.Arm64SriV, new IntrinsicInfo(0x2f004400u, IntrinsicType.VectorTernaryShrRd));
|
||||
Add(Intrinsic.Arm64SrshlS, new IntrinsicInfo(0x5e205400u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64SrshlV, new IntrinsicInfo(0x0e205400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SrshrS, new IntrinsicInfo(0x5f002400u, IntrinsicType.ScalarBinaryShr));
|
||||
Add(Intrinsic.Arm64SrshrV, new IntrinsicInfo(0x0f002400u, IntrinsicType.VectorBinaryShr));
|
||||
Add(Intrinsic.Arm64SrsraS, new IntrinsicInfo(0x5f003400u, IntrinsicType.ScalarTernaryShrRd));
|
||||
Add(Intrinsic.Arm64SrsraV, new IntrinsicInfo(0x0f003400u, IntrinsicType.VectorTernaryShrRd));
|
||||
Add(Intrinsic.Arm64SshllV, new IntrinsicInfo(0x0f00a400u, IntrinsicType.VectorBinaryShl));
|
||||
Add(Intrinsic.Arm64SshlS, new IntrinsicInfo(0x5e204400u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64SshlV, new IntrinsicInfo(0x0e204400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SshrS, new IntrinsicInfo(0x5f000400u, IntrinsicType.ScalarBinaryShr));
|
||||
Add(Intrinsic.Arm64SshrV, new IntrinsicInfo(0x0f000400u, IntrinsicType.VectorBinaryShr));
|
||||
Add(Intrinsic.Arm64SsraS, new IntrinsicInfo(0x5f001400u, IntrinsicType.ScalarTernaryShrRd));
|
||||
Add(Intrinsic.Arm64SsraV, new IntrinsicInfo(0x0f001400u, IntrinsicType.VectorTernaryShrRd));
|
||||
Add(Intrinsic.Arm64SsublV, new IntrinsicInfo(0x0e202000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SsubwV, new IntrinsicInfo(0x0e203000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64St1Vms, new IntrinsicInfo(0x0c002000u, IntrinsicType.VectorLdSt));
|
||||
Add(Intrinsic.Arm64St1Vss, new IntrinsicInfo(0x0d000000u, IntrinsicType.VectorLdStSs));
|
||||
Add(Intrinsic.Arm64St2Vms, new IntrinsicInfo(0x0c008000u, IntrinsicType.VectorLdSt));
|
||||
Add(Intrinsic.Arm64St2Vss, new IntrinsicInfo(0x0d200000u, IntrinsicType.VectorLdStSs));
|
||||
Add(Intrinsic.Arm64St3Vms, new IntrinsicInfo(0x0c004000u, IntrinsicType.VectorLdSt));
|
||||
Add(Intrinsic.Arm64St3Vss, new IntrinsicInfo(0x0d002000u, IntrinsicType.VectorLdStSs));
|
||||
Add(Intrinsic.Arm64St4Vms, new IntrinsicInfo(0x0c000000u, IntrinsicType.VectorLdSt));
|
||||
Add(Intrinsic.Arm64St4Vss, new IntrinsicInfo(0x0d202000u, IntrinsicType.VectorLdStSs));
|
||||
Add(Intrinsic.Arm64SubhnV, new IntrinsicInfo(0x0e206000u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64SubS, new IntrinsicInfo(0x7e208400u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64SubV, new IntrinsicInfo(0x2e208400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64SuqaddS, new IntrinsicInfo(0x5e203800u, IntrinsicType.ScalarBinaryRd));
|
||||
Add(Intrinsic.Arm64SuqaddV, new IntrinsicInfo(0x0e203800u, IntrinsicType.VectorBinaryRd));
|
||||
Add(Intrinsic.Arm64TblV, new IntrinsicInfo(0x0e000000u, IntrinsicType.VectorLookupTable));
|
||||
Add(Intrinsic.Arm64TbxV, new IntrinsicInfo(0x0e001000u, IntrinsicType.VectorLookupTable));
|
||||
Add(Intrinsic.Arm64Trn1V, new IntrinsicInfo(0x0e002800u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64Trn2V, new IntrinsicInfo(0x0e006800u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UabalV, new IntrinsicInfo(0x2e205000u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64UabaV, new IntrinsicInfo(0x2e207c00u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64UabdlV, new IntrinsicInfo(0x2e207000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UabdV, new IntrinsicInfo(0x2e207400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UadalpV, new IntrinsicInfo(0x2e206800u, IntrinsicType.VectorBinaryRd));
|
||||
Add(Intrinsic.Arm64UaddlpV, new IntrinsicInfo(0x2e202800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64UaddlvV, new IntrinsicInfo(0x2e303800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64UaddlV, new IntrinsicInfo(0x2e200000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UaddwV, new IntrinsicInfo(0x2e201000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UcvtfSFixed, new IntrinsicInfo(0x7f00e400u, IntrinsicType.ScalarFPConvFixed));
|
||||
Add(Intrinsic.Arm64UcvtfVFixed, new IntrinsicInfo(0x2f00e400u, IntrinsicType.VectorFPConvFixed));
|
||||
Add(Intrinsic.Arm64UcvtfS, new IntrinsicInfo(0x7e21d800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64UcvtfV, new IntrinsicInfo(0x2e21d800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64UcvtfGpFixed, new IntrinsicInfo(0x1e030000u, IntrinsicType.ScalarFPConvFixedGpr));
|
||||
Add(Intrinsic.Arm64UcvtfGp, new IntrinsicInfo(0x1e230000u, IntrinsicType.ScalarFPConvGpr));
|
||||
Add(Intrinsic.Arm64UhaddV, new IntrinsicInfo(0x2e200400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UhsubV, new IntrinsicInfo(0x2e202400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UmaxpV, new IntrinsicInfo(0x2e20a400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UmaxvV, new IntrinsicInfo(0x2e30a800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64UmaxV, new IntrinsicInfo(0x2e206400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UminpV, new IntrinsicInfo(0x2e20ac00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UminvV, new IntrinsicInfo(0x2e31a800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64UminV, new IntrinsicInfo(0x2e206c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UmlalVe, new IntrinsicInfo(0x2f002000u, IntrinsicType.VectorTernaryRdByElem));
|
||||
Add(Intrinsic.Arm64UmlalV, new IntrinsicInfo(0x2e208000u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64UmlslVe, new IntrinsicInfo(0x2f006000u, IntrinsicType.VectorTernaryRdByElem));
|
||||
Add(Intrinsic.Arm64UmlslV, new IntrinsicInfo(0x2e20a000u, IntrinsicType.VectorTernaryRd));
|
||||
Add(Intrinsic.Arm64UmovV, new IntrinsicInfo(0x0e003c00u, IntrinsicType.VectorUnaryByElem));
|
||||
Add(Intrinsic.Arm64UmullVe, new IntrinsicInfo(0x2f00a000u, IntrinsicType.VectorBinaryByElem));
|
||||
Add(Intrinsic.Arm64UmullV, new IntrinsicInfo(0x2e20c000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UqaddS, new IntrinsicInfo(0x7e200c00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64UqaddV, new IntrinsicInfo(0x2e200c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UqrshlS, new IntrinsicInfo(0x7e205c00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64UqrshlV, new IntrinsicInfo(0x2e205c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UqrshrnS, new IntrinsicInfo(0x7f009c00u, IntrinsicType.ScalarTernaryShrRd));
|
||||
Add(Intrinsic.Arm64UqrshrnV, new IntrinsicInfo(0x2f009c00u, IntrinsicType.VectorTernaryShrRd));
|
||||
Add(Intrinsic.Arm64UqshlSi, new IntrinsicInfo(0x7f007400u, IntrinsicType.ScalarBinaryShl));
|
||||
Add(Intrinsic.Arm64UqshlVi, new IntrinsicInfo(0x2f007400u, IntrinsicType.VectorBinaryShl));
|
||||
Add(Intrinsic.Arm64UqshlS, new IntrinsicInfo(0x7e204c00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64UqshlV, new IntrinsicInfo(0x2e204c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UqshrnS, new IntrinsicInfo(0x7f009400u, IntrinsicType.ScalarTernaryShrRd));
|
||||
Add(Intrinsic.Arm64UqshrnV, new IntrinsicInfo(0x2f009400u, IntrinsicType.VectorTernaryShrRd));
|
||||
Add(Intrinsic.Arm64UqsubS, new IntrinsicInfo(0x7e202c00u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64UqsubV, new IntrinsicInfo(0x2e202c00u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UqxtnS, new IntrinsicInfo(0x7e214800u, IntrinsicType.ScalarBinaryRd));
|
||||
Add(Intrinsic.Arm64UqxtnV, new IntrinsicInfo(0x2e214800u, IntrinsicType.VectorBinaryRd));
|
||||
Add(Intrinsic.Arm64UrecpeV, new IntrinsicInfo(0x0ea1c800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64UrhaddV, new IntrinsicInfo(0x2e201400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UrshlS, new IntrinsicInfo(0x7e205400u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64UrshlV, new IntrinsicInfo(0x2e205400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UrshrS, new IntrinsicInfo(0x7f002400u, IntrinsicType.ScalarBinaryShr));
|
||||
Add(Intrinsic.Arm64UrshrV, new IntrinsicInfo(0x2f002400u, IntrinsicType.VectorBinaryShr));
|
||||
Add(Intrinsic.Arm64UrsqrteV, new IntrinsicInfo(0x2ea1c800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64UrsraS, new IntrinsicInfo(0x7f003400u, IntrinsicType.ScalarTernaryShrRd));
|
||||
Add(Intrinsic.Arm64UrsraV, new IntrinsicInfo(0x2f003400u, IntrinsicType.VectorTernaryShrRd));
|
||||
Add(Intrinsic.Arm64UshllV, new IntrinsicInfo(0x2f00a400u, IntrinsicType.VectorBinaryShl));
|
||||
Add(Intrinsic.Arm64UshlS, new IntrinsicInfo(0x7e204400u, IntrinsicType.ScalarBinary));
|
||||
Add(Intrinsic.Arm64UshlV, new IntrinsicInfo(0x2e204400u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UshrS, new IntrinsicInfo(0x7f000400u, IntrinsicType.ScalarBinaryShr));
|
||||
Add(Intrinsic.Arm64UshrV, new IntrinsicInfo(0x2f000400u, IntrinsicType.VectorBinaryShr));
|
||||
Add(Intrinsic.Arm64UsqaddS, new IntrinsicInfo(0x7e203800u, IntrinsicType.ScalarBinaryRd));
|
||||
Add(Intrinsic.Arm64UsqaddV, new IntrinsicInfo(0x2e203800u, IntrinsicType.VectorBinaryRd));
|
||||
Add(Intrinsic.Arm64UsraS, new IntrinsicInfo(0x7f001400u, IntrinsicType.ScalarTernaryShrRd));
|
||||
Add(Intrinsic.Arm64UsraV, new IntrinsicInfo(0x2f001400u, IntrinsicType.VectorTernaryShrRd));
|
||||
Add(Intrinsic.Arm64UsublV, new IntrinsicInfo(0x2e202000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64UsubwV, new IntrinsicInfo(0x2e203000u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64Uzp1V, new IntrinsicInfo(0x0e001800u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64Uzp2V, new IntrinsicInfo(0x0e005800u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64XtnV, new IntrinsicInfo(0x0e212800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64Zip1V, new IntrinsicInfo(0x0e003800u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64Zip2V, new IntrinsicInfo(0x0e007800u, IntrinsicType.VectorBinary));
|
||||
}
|
||||
|
||||
private static void Add(Intrinsic intrin, IntrinsicInfo info)
|
||||
{
|
||||
_intrinTable[(int)intrin] = info;
|
||||
}
|
||||
|
||||
public static IntrinsicInfo GetInfo(Intrinsic intrin)
|
||||
{
|
||||
return _intrinTable[(int)intrin];
|
||||
}
|
||||
}
|
||||
}
|
59
ARMeilleure/CodeGen/Arm64/IntrinsicType.cs
Normal file
59
ARMeilleure/CodeGen/Arm64/IntrinsicType.cs
Normal file
@ -0,0 +1,59 @@
|
||||
namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
enum IntrinsicType
|
||||
{
|
||||
ScalarUnary,
|
||||
ScalarUnaryByElem,
|
||||
ScalarBinary,
|
||||
ScalarBinaryByElem,
|
||||
ScalarBinaryFPByElem,
|
||||
ScalarBinaryRd,
|
||||
ScalarBinaryShl,
|
||||
ScalarBinaryShr,
|
||||
ScalarFcsel,
|
||||
ScalarFmovi,
|
||||
ScalarFPCompare,
|
||||
ScalarFPCompareCond,
|
||||
ScalarFPConv,
|
||||
ScalarFPConvFixed,
|
||||
ScalarFPConvFixedGpr,
|
||||
ScalarFPConvGpr,
|
||||
ScalarTernary,
|
||||
ScalarTernaryFPRdByElem,
|
||||
ScalarTernaryShlRd,
|
||||
ScalarTernaryShrRd,
|
||||
|
||||
VectorUnary,
|
||||
VectorUnaryBitwise,
|
||||
VectorUnaryByElem,
|
||||
VectorBinary,
|
||||
VectorBinaryBitwise,
|
||||
VectorBinaryBitwiseImm,
|
||||
VectorBinaryByElem,
|
||||
VectorBinaryFPByElem,
|
||||
VectorBinaryRd,
|
||||
VectorBinaryShl,
|
||||
VectorBinaryShr,
|
||||
VectorExt,
|
||||
VectorFmovi,
|
||||
VectorFPConvFixed,
|
||||
VectorInsertByElem,
|
||||
VectorLdSt,
|
||||
VectorLdStSs,
|
||||
VectorLookupTable,
|
||||
VectorMovi,
|
||||
VectorMvni,
|
||||
VectorTernaryFPRdByElem,
|
||||
VectorTernaryRd,
|
||||
VectorTernaryRdBitwise,
|
||||
VectorTernaryRdByElem,
|
||||
VectorTernaryShlRd,
|
||||
VectorTernaryShrRd,
|
||||
|
||||
Vector128Unary,
|
||||
Vector128Binary,
|
||||
|
||||
GetRegister,
|
||||
SetRegister
|
||||
}
|
||||
}
|
940
ARMeilleure/CodeGen/Arm64/PreAllocator.cs
Normal file
940
ARMeilleure/CodeGen/Arm64/PreAllocator.cs
Normal file
@ -0,0 +1,940 @@
|
||||
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
|
||||
|
||||
namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
class PreAllocator
|
||||
{
|
||||
private class ConstantDict
|
||||
{
|
||||
private readonly Dictionary<(ulong, OperandType), Operand> _constants;
|
||||
|
||||
public ConstantDict()
|
||||
{
|
||||
_constants = new Dictionary<(ulong, OperandType), Operand>();
|
||||
}
|
||||
|
||||
public void Add(ulong value, OperandType type, Operand local)
|
||||
{
|
||||
_constants.Add((value, type), local);
|
||||
}
|
||||
|
||||
public bool TryGetValue(ulong value, OperandType type, out Operand local)
|
||||
{
|
||||
return _constants.TryGetValue((value, type), out local);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RunPass(CompilerContext cctx, StackAllocator stackAlloc, out int maxCallArgs)
|
||||
{
|
||||
maxCallArgs = -1;
|
||||
|
||||
Span<Operation> buffer = default;
|
||||
|
||||
Operand[] preservedArgs = new Operand[CallingConvention.GetArgumentsOnRegsCount()];
|
||||
|
||||
for (BasicBlock block = cctx.Cfg.Blocks.First; block != null; block = block.ListNext)
|
||||
{
|
||||
ConstantDict constants = new ConstantDict();
|
||||
|
||||
Operation nextNode;
|
||||
|
||||
for (Operation node = block.Operations.First; node != default; node = nextNode)
|
||||
{
|
||||
nextNode = node.ListNext;
|
||||
|
||||
if (node.Instruction == Instruction.Phi)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
HandleConstantRegCopy(constants, block.Operations, node);
|
||||
HandleDestructiveRegCopy(block.Operations, node);
|
||||
|
||||
switch (node.Instruction)
|
||||
{
|
||||
case Instruction.Call:
|
||||
// Get the maximum number of arguments used on a call.
|
||||
// On windows, when a struct is returned from the call,
|
||||
// we also need to pass the pointer where the struct
|
||||
// should be written on the first argument.
|
||||
int argsCount = node.SourcesCount - 1;
|
||||
|
||||
if (node.Destination != default && node.Destination.Type == OperandType.V128)
|
||||
{
|
||||
argsCount++;
|
||||
}
|
||||
|
||||
if (maxCallArgs < argsCount)
|
||||
{
|
||||
maxCallArgs = argsCount;
|
||||
}
|
||||
|
||||
// Copy values to registers expected by the function
|
||||
// being called, as mandated by the ABI.
|
||||
HandleCall(constants, block.Operations, node);
|
||||
break;
|
||||
case Instruction.CompareAndSwap:
|
||||
case Instruction.CompareAndSwap16:
|
||||
case Instruction.CompareAndSwap8:
|
||||
nextNode = HandleCompareAndSwap(block.Operations, node);
|
||||
break;
|
||||
case Instruction.LoadArgument:
|
||||
nextNode = HandleLoadArgument(cctx, ref buffer, block.Operations, preservedArgs, node);
|
||||
break;
|
||||
case Instruction.Return:
|
||||
HandleReturn(block.Operations, node);
|
||||
break;
|
||||
case Instruction.Tailcall:
|
||||
HandleTailcall(constants, block.Operations, stackAlloc, node, node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void HandleConstantRegCopy(ConstantDict constants, IntrusiveList<Operation> nodes, Operation node)
|
||||
{
|
||||
if (node.SourcesCount == 0 || IsIntrinsicWithConst(node))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Instruction inst = node.Instruction;
|
||||
|
||||
Operand src1 = node.GetSource(0);
|
||||
Operand src2;
|
||||
|
||||
if (src1.Kind == OperandKind.Constant)
|
||||
{
|
||||
if (!src1.Type.IsInteger())
|
||||
{
|
||||
// Handle non-integer types (FP32, FP64 and V128).
|
||||
// For instructions without an immediate operand, we do the following:
|
||||
// - Insert a copy with the constant value (as integer) to a GPR.
|
||||
// - Insert a copy from the GPR to a XMM register.
|
||||
// - Replace the constant use with the XMM register.
|
||||
src1 = AddFloatConstantCopy(constants, nodes, node, src1);
|
||||
|
||||
node.SetSource(0, src1);
|
||||
}
|
||||
else if (!HasConstSrc1(node, src1.Value))
|
||||
{
|
||||
// Handle integer types.
|
||||
// Most ALU instructions accepts a 32-bits immediate on the second operand.
|
||||
// We need to ensure the following:
|
||||
// - If the constant is on operand 1, we need to move it.
|
||||
// -- But first, we try to swap operand 1 and 2 if the instruction is commutative.
|
||||
// -- Doing so may allow us to encode the constant as operand 2 and avoid a copy.
|
||||
// - If the constant is on operand 2, we check if the instruction supports it,
|
||||
// if not, we also add a copy. 64-bits constants are usually not supported.
|
||||
if (IsCommutative(node))
|
||||
{
|
||||
src2 = node.GetSource(1);
|
||||
|
||||
Operand temp = src1;
|
||||
|
||||
src1 = src2;
|
||||
src2 = temp;
|
||||
|
||||
node.SetSource(0, src1);
|
||||
node.SetSource(1, src2);
|
||||
}
|
||||
|
||||
if (src1.Kind == OperandKind.Constant)
|
||||
{
|
||||
src1 = AddIntConstantCopy(constants, nodes, node, src1);
|
||||
|
||||
node.SetSource(0, src1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node.SourcesCount < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
src2 = node.GetSource(1);
|
||||
|
||||
if (src2.Kind == OperandKind.Constant)
|
||||
{
|
||||
if (!src2.Type.IsInteger())
|
||||
{
|
||||
src2 = AddFloatConstantCopy(constants, nodes, node, src2);
|
||||
|
||||
node.SetSource(1, src2);
|
||||
}
|
||||
else if (!HasConstSrc2(inst, src2))
|
||||
{
|
||||
src2 = AddIntConstantCopy(constants, nodes, node, src2);
|
||||
|
||||
node.SetSource(1, src2);
|
||||
}
|
||||
}
|
||||
|
||||
if (node.SourcesCount < 3 ||
|
||||
node.Instruction == Instruction.BranchIf ||
|
||||
node.Instruction == Instruction.Compare ||
|
||||
node.Instruction == Instruction.VectorInsert ||
|
||||
node.Instruction == Instruction.VectorInsert16 ||
|
||||
node.Instruction == Instruction.VectorInsert8)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int srcIndex = 2; srcIndex < node.SourcesCount; srcIndex++)
|
||||
{
|
||||
Operand src = node.GetSource(srcIndex);
|
||||
|
||||
if (src.Kind == OperandKind.Constant)
|
||||
{
|
||||
if (!src.Type.IsInteger())
|
||||
{
|
||||
src = AddFloatConstantCopy(constants, nodes, node, src);
|
||||
|
||||
node.SetSource(srcIndex, src);
|
||||
}
|
||||
else
|
||||
{
|
||||
src = AddIntConstantCopy(constants, nodes, node, src);
|
||||
|
||||
node.SetSource(srcIndex, src);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void HandleDestructiveRegCopy(IntrusiveList<Operation> nodes, Operation node)
|
||||
{
|
||||
if (node.Destination == default || node.SourcesCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Operand dest = node.Destination;
|
||||
Operand src1 = node.GetSource(0);
|
||||
|
||||
if (IsSameOperandDestSrc1(node) && src1.Kind == OperandKind.LocalVariable)
|
||||
{
|
||||
bool useNewLocal = false;
|
||||
|
||||
for (int srcIndex = 1; srcIndex < node.SourcesCount; srcIndex++)
|
||||
{
|
||||
if (node.GetSource(srcIndex) == dest)
|
||||
{
|
||||
useNewLocal = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (useNewLocal)
|
||||
{
|
||||
// Dest is being used as some source already, we need to use a new
|
||||
// local to store the temporary value, otherwise the value on dest
|
||||
// local would be overwritten.
|
||||
Operand temp = Local(dest.Type);
|
||||
|
||||
nodes.AddBefore(node, Operation(Instruction.Copy, temp, src1));
|
||||
|
||||
node.SetSource(0, temp);
|
||||
|
||||
nodes.AddAfter(node, Operation(Instruction.Copy, dest, temp));
|
||||
|
||||
node.Destination = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
nodes.AddBefore(node, Operation(Instruction.Copy, dest, src1));
|
||||
|
||||
node.SetSource(0, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void HandleCall(ConstantDict constants, IntrusiveList<Operation> nodes, Operation node)
|
||||
{
|
||||
Operation operation = node;
|
||||
|
||||
Operand dest = operation.Destination;
|
||||
|
||||
List<Operand> sources = new List<Operand>
|
||||
{
|
||||
operation.GetSource(0)
|
||||
};
|
||||
|
||||
int argsCount = operation.SourcesCount - 1;
|
||||
|
||||
int intMax = CallingConvention.GetArgumentsOnRegsCount();
|
||||
int vecMax = CallingConvention.GetArgumentsOnRegsCount();
|
||||
|
||||
int intCount = 0;
|
||||
int vecCount = 0;
|
||||
|
||||
int stackOffset = 0;
|
||||
|
||||
for (int index = 0; index < argsCount; index++)
|
||||
{
|
||||
Operand source = operation.GetSource(index + 1);
|
||||
|
||||
bool passOnReg;
|
||||
|
||||
if (source.Type.IsInteger())
|
||||
{
|
||||
passOnReg = intCount < intMax;
|
||||
}
|
||||
else if (source.Type == OperandType.V128)
|
||||
{
|
||||
passOnReg = intCount + 1 < intMax;
|
||||
}
|
||||
else
|
||||
{
|
||||
passOnReg = vecCount < vecMax;
|
||||
}
|
||||
|
||||
if (source.Type == OperandType.V128 && passOnReg)
|
||||
{
|
||||
// V128 is a struct, we pass each half on a GPR if possible.
|
||||
Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
|
||||
Operand argReg2 = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
|
||||
|
||||
nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg, source, Const(0)));
|
||||
nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg2, source, Const(1)));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (passOnReg)
|
||||
{
|
||||
Operand argReg = source.Type.IsInteger()
|
||||
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
|
||||
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
|
||||
|
||||
Operation copyOp = Operation(Instruction.Copy, argReg, source);
|
||||
|
||||
HandleConstantRegCopy(constants, nodes, nodes.AddBefore(node, copyOp));
|
||||
|
||||
sources.Add(argReg);
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand offset = Const(stackOffset);
|
||||
|
||||
Operation spillOp = Operation(Instruction.SpillArg, default, offset, source);
|
||||
|
||||
HandleConstantRegCopy(constants, nodes, nodes.AddBefore(node, spillOp));
|
||||
|
||||
stackOffset += source.Type.GetSizeInBytes();
|
||||
}
|
||||
}
|
||||
|
||||
if (dest != default)
|
||||
{
|
||||
if (dest.Type == OperandType.V128)
|
||||
{
|
||||
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
|
||||
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
|
||||
|
||||
node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, retLReg));
|
||||
nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, retHReg, Const(1)));
|
||||
|
||||
operation.Destination = default;
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand retReg = dest.Type.IsInteger()
|
||||
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
|
||||
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
|
||||
|
||||
Operation copyOp = Operation(Instruction.Copy, dest, retReg);
|
||||
|
||||
nodes.AddAfter(node, copyOp);
|
||||
|
||||
operation.Destination = retReg;
|
||||
}
|
||||
}
|
||||
|
||||
operation.SetSources(sources.ToArray());
|
||||
}
|
||||
|
||||
private static void HandleTailcall(
|
||||
ConstantDict constants,
|
||||
IntrusiveList<Operation> nodes,
|
||||
StackAllocator stackAlloc,
|
||||
Operation node,
|
||||
Operation operation)
|
||||
{
|
||||
List<Operand> sources = new List<Operand>
|
||||
{
|
||||
operation.GetSource(0)
|
||||
};
|
||||
|
||||
int argsCount = operation.SourcesCount - 1;
|
||||
|
||||
int intMax = CallingConvention.GetArgumentsOnRegsCount();
|
||||
int vecMax = CallingConvention.GetArgumentsOnRegsCount();
|
||||
|
||||
int intCount = 0;
|
||||
int vecCount = 0;
|
||||
|
||||
// Handle arguments passed on registers.
|
||||
for (int index = 0; index < argsCount; index++)
|
||||
{
|
||||
Operand source = operation.GetSource(1 + index);
|
||||
|
||||
bool passOnReg;
|
||||
|
||||
if (source.Type.IsInteger())
|
||||
{
|
||||
passOnReg = intCount + 1 < intMax;
|
||||
}
|
||||
else
|
||||
{
|
||||
passOnReg = vecCount < vecMax;
|
||||
}
|
||||
|
||||
if (source.Type == OperandType.V128 && passOnReg)
|
||||
{
|
||||
// V128 is a struct, we pass each half on a GPR if possible.
|
||||
Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
|
||||
Operand argReg2 = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
|
||||
|
||||
nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg, source, Const(0)));
|
||||
nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg2, source, Const(1)));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (passOnReg)
|
||||
{
|
||||
Operand argReg = source.Type.IsInteger()
|
||||
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
|
||||
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
|
||||
|
||||
Operation copyOp = Operation(Instruction.Copy, argReg, source);
|
||||
|
||||
HandleConstantRegCopy(constants, nodes, nodes.AddBefore(node, copyOp));
|
||||
|
||||
sources.Add(argReg);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException("Spilling is not currently supported for tail calls. (too many arguments)");
|
||||
}
|
||||
}
|
||||
|
||||
// The target address must be on the return registers, since we
|
||||
// don't return anything and it is guaranteed to not be a
|
||||
// callee saved register (which would be trashed on the epilogue).
|
||||
Operand tcAddress = Gpr(CodeGenCommon.TcAddressRegister, OperandType.I64);
|
||||
|
||||
Operation addrCopyOp = Operation(Instruction.Copy, tcAddress, operation.GetSource(0));
|
||||
|
||||
nodes.AddBefore(node, addrCopyOp);
|
||||
|
||||
sources[0] = tcAddress;
|
||||
|
||||
operation.SetSources(sources.ToArray());
|
||||
}
|
||||
|
||||
private static Operation HandleCompareAndSwap(IntrusiveList<Operation> nodes, Operation node)
|
||||
{
|
||||
Operand expected = node.GetSource(1);
|
||||
|
||||
if (expected.Type == OperandType.V128)
|
||||
{
|
||||
Operand dest = node.Destination;
|
||||
Operand expectedLow = Local(OperandType.I64);
|
||||
Operand expectedHigh = Local(OperandType.I64);
|
||||
Operand desiredLow = Local(OperandType.I64);
|
||||
Operand desiredHigh = Local(OperandType.I64);
|
||||
Operand actualLow = Local(OperandType.I64);
|
||||
Operand actualHigh = Local(OperandType.I64);
|
||||
|
||||
Operand address = node.GetSource(0);
|
||||
Operand desired = node.GetSource(2);
|
||||
|
||||
void SplitOperand(Operand source, Operand low, Operand high)
|
||||
{
|
||||
nodes.AddBefore(node, Operation(Instruction.VectorExtract, low, source, Const(0)));
|
||||
nodes.AddBefore(node, Operation(Instruction.VectorExtract, high, source, Const(1)));
|
||||
}
|
||||
|
||||
SplitOperand(expected, expectedLow, expectedHigh);
|
||||
SplitOperand(desired, desiredLow, desiredHigh);
|
||||
|
||||
Operation operation = node;
|
||||
|
||||
// Update the sources and destinations with split 64-bit halfs of the whole 128-bit values.
|
||||
// We also need a additional registers that will be used to store temporary information.
|
||||
operation.SetDestinations(new[] { actualLow, actualHigh, Local(OperandType.I64), Local(OperandType.I64) });
|
||||
operation.SetSources(new[] { address, expectedLow, expectedHigh, desiredLow, desiredHigh });
|
||||
|
||||
// Add some dummy uses of the input operands, as the CAS operation will be a loop,
|
||||
// so they can't be used as destination operand.
|
||||
for (int i = 0; i < operation.SourcesCount; i++)
|
||||
{
|
||||
Operand src = operation.GetSource(i);
|
||||
node = nodes.AddAfter(node, Operation(Instruction.Copy, src, src));
|
||||
}
|
||||
|
||||
// Assemble the vector with the 64-bit values at the given memory location.
|
||||
node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, actualLow));
|
||||
node = nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, actualHigh, Const(1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// We need a additional register where the store result will be written to.
|
||||
node.SetDestinations(new[] { node.Destination, Local(OperandType.I32) });
|
||||
|
||||
// Add some dummy uses of the input operands, as the CAS operation will be a loop,
|
||||
// so they can't be used as destination operand.
|
||||
Operation operation = node;
|
||||
|
||||
for (int i = 0; i < operation.SourcesCount; i++)
|
||||
{
|
||||
Operand src = operation.GetSource(i);
|
||||
node = nodes.AddAfter(node, Operation(Instruction.Copy, src, src));
|
||||
}
|
||||
}
|
||||
|
||||
return node.ListNext;
|
||||
}
|
||||
|
||||
private static void HandleReturn(IntrusiveList<Operation> nodes, Operation node)
|
||||
{
|
||||
if (node.SourcesCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Operand source = node.GetSource(0);
|
||||
|
||||
if (source.Type == OperandType.V128)
|
||||
{
|
||||
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
|
||||
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
|
||||
|
||||
nodes.AddBefore(node, Operation(Instruction.VectorExtract, retLReg, source, Const(0)));
|
||||
nodes.AddBefore(node, Operation(Instruction.VectorExtract, retHReg, source, Const(1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand retReg = source.Type.IsInteger()
|
||||
? Gpr(CallingConvention.GetIntReturnRegister(), source.Type)
|
||||
: Xmm(CallingConvention.GetVecReturnRegister(), source.Type);
|
||||
|
||||
Operation retCopyOp = Operation(Instruction.Copy, retReg, source);
|
||||
|
||||
nodes.AddBefore(node, retCopyOp);
|
||||
}
|
||||
}
|
||||
|
||||
private static Operation HandleLoadArgument(
|
||||
CompilerContext cctx,
|
||||
ref Span<Operation> buffer,
|
||||
IntrusiveList<Operation> nodes,
|
||||
Operand[] preservedArgs,
|
||||
Operation node)
|
||||
{
|
||||
Operand source = node.GetSource(0);
|
||||
|
||||
Debug.Assert(source.Kind == OperandKind.Constant, "Non-constant LoadArgument source kind.");
|
||||
|
||||
int index = source.AsInt32();
|
||||
|
||||
int intCount = 0;
|
||||
int vecCount = 0;
|
||||
|
||||
for (int cIndex = 0; cIndex < index; cIndex++)
|
||||
{
|
||||
OperandType argType = cctx.FuncArgTypes[cIndex];
|
||||
|
||||
if (argType.IsInteger())
|
||||
{
|
||||
intCount++;
|
||||
}
|
||||
else if (argType == OperandType.V128)
|
||||
{
|
||||
intCount += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
vecCount++;
|
||||
}
|
||||
}
|
||||
|
||||
bool passOnReg;
|
||||
|
||||
if (source.Type.IsInteger())
|
||||
{
|
||||
passOnReg = intCount < CallingConvention.GetArgumentsOnRegsCount();
|
||||
}
|
||||
else if (source.Type == OperandType.V128)
|
||||
{
|
||||
passOnReg = intCount + 1 < CallingConvention.GetArgumentsOnRegsCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
passOnReg = vecCount < CallingConvention.GetArgumentsOnRegsCount();
|
||||
}
|
||||
|
||||
if (passOnReg)
|
||||
{
|
||||
Operand dest = node.Destination;
|
||||
|
||||
if (preservedArgs[index] == default)
|
||||
{
|
||||
if (dest.Type == OperandType.V128)
|
||||
{
|
||||
// V128 is a struct, we pass each half on a GPR if possible.
|
||||
Operand pArg = Local(OperandType.V128);
|
||||
|
||||
Operand argLReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount), OperandType.I64);
|
||||
Operand argHReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount + 1), OperandType.I64);
|
||||
|
||||
Operation copyL = Operation(Instruction.VectorCreateScalar, pArg, argLReg);
|
||||
Operation copyH = Operation(Instruction.VectorInsert, pArg, pArg, argHReg, Const(1));
|
||||
|
||||
cctx.Cfg.Entry.Operations.AddFirst(copyH);
|
||||
cctx.Cfg.Entry.Operations.AddFirst(copyL);
|
||||
|
||||
preservedArgs[index] = pArg;
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand pArg = Local(dest.Type);
|
||||
|
||||
Operand argReg = dest.Type.IsInteger()
|
||||
? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type)
|
||||
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type);
|
||||
|
||||
Operation copyOp = Operation(Instruction.Copy, pArg, argReg);
|
||||
|
||||
cctx.Cfg.Entry.Operations.AddFirst(copyOp);
|
||||
|
||||
preservedArgs[index] = pArg;
|
||||
}
|
||||
}
|
||||
|
||||
Operation nextNode;
|
||||
|
||||
if (dest.AssignmentsCount == 1)
|
||||
{
|
||||
// Let's propagate the argument if we can to avoid copies.
|
||||
Propagate(ref buffer, dest, preservedArgs[index]);
|
||||
nextNode = node.ListNext;
|
||||
}
|
||||
else
|
||||
{
|
||||
Operation argCopyOp = Operation(Instruction.Copy, dest, preservedArgs[index]);
|
||||
nextNode = nodes.AddBefore(node, argCopyOp);
|
||||
}
|
||||
|
||||
Delete(nodes, node);
|
||||
return nextNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Pass on stack.
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Propagate(ref Span<Operation> buffer, Operand dest, Operand value)
|
||||
{
|
||||
ReadOnlySpan<Operation> uses = dest.GetUses(ref buffer);
|
||||
|
||||
foreach (Operation use in uses)
|
||||
{
|
||||
for (int srcIndex = 0; srcIndex < use.SourcesCount; srcIndex++)
|
||||
{
|
||||
Operand useSrc = use.GetSource(srcIndex);
|
||||
|
||||
if (useSrc == dest)
|
||||
{
|
||||
use.SetSource(srcIndex, value);
|
||||
}
|
||||
else if (useSrc.Kind == OperandKind.Memory)
|
||||
{
|
||||
MemoryOperand memoryOp = useSrc.GetMemory();
|
||||
|
||||
Operand baseAddr = memoryOp.BaseAddress;
|
||||
Operand index = memoryOp.Index;
|
||||
bool changed = false;
|
||||
|
||||
if (baseAddr == dest)
|
||||
{
|
||||
baseAddr = value;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (index == dest)
|
||||
{
|
||||
index = value;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
use.SetSource(srcIndex, MemoryOp(
|
||||
useSrc.Type,
|
||||
baseAddr,
|
||||
index,
|
||||
memoryOp.Scale,
|
||||
memoryOp.Displacement));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Operand AddFloatConstantCopy(
|
||||
ConstantDict constants,
|
||||
IntrusiveList<Operation> nodes,
|
||||
Operation node,
|
||||
Operand source)
|
||||
{
|
||||
Operand temp = Local(source.Type);
|
||||
|
||||
Operand intConst = AddIntConstantCopy(constants, nodes, node, GetIntConst(source));
|
||||
|
||||
Operation copyOp = Operation(Instruction.VectorCreateScalar, temp, intConst);
|
||||
|
||||
nodes.AddBefore(node, copyOp);
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
private static Operand AddIntConstantCopy(
|
||||
ConstantDict constants,
|
||||
IntrusiveList<Operation> nodes,
|
||||
Operation node,
|
||||
Operand source)
|
||||
{
|
||||
if (constants.TryGetValue(source.Value, source.Type, out Operand temp))
|
||||
{
|
||||
return temp;
|
||||
}
|
||||
|
||||
temp = Local(source.Type);
|
||||
|
||||
Operation copyOp = Operation(Instruction.Copy, temp, source);
|
||||
|
||||
nodes.AddBefore(node, copyOp);
|
||||
|
||||
constants.Add(source.Value, source.Type, temp);
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
private static Operand GetIntConst(Operand value)
|
||||
{
|
||||
if (value.Type == OperandType.FP32)
|
||||
{
|
||||
return Const(value.AsInt32());
|
||||
}
|
||||
else if (value.Type == OperandType.FP64)
|
||||
{
|
||||
return Const(value.AsInt64());
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static void Delete(IntrusiveList<Operation> nodes, Operation node)
|
||||
{
|
||||
node.Destination = default;
|
||||
|
||||
for (int index = 0; index < node.SourcesCount; index++)
|
||||
{
|
||||
node.SetSource(index, default);
|
||||
}
|
||||
|
||||
nodes.Remove(node);
|
||||
}
|
||||
|
||||
private static Operand Gpr(int register, OperandType type)
|
||||
{
|
||||
return Register(register, RegisterType.Integer, type);
|
||||
}
|
||||
|
||||
private static Operand Xmm(int register, OperandType type)
|
||||
{
|
||||
return Register(register, RegisterType.Vector, type);
|
||||
}
|
||||
|
||||
private static bool IsSameOperandDestSrc1(Operation operation)
|
||||
{
|
||||
switch (operation.Instruction)
|
||||
{
|
||||
case Instruction.Extended:
|
||||
return IsSameOperandDestSrc1(operation.Intrinsic);
|
||||
case Instruction.VectorInsert:
|
||||
case Instruction.VectorInsert16:
|
||||
case Instruction.VectorInsert8:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsSameOperandDestSrc1(Intrinsic intrinsic)
|
||||
{
|
||||
IntrinsicInfo info = IntrinsicTable.GetInfo(intrinsic & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask));
|
||||
|
||||
return info.Type == IntrinsicType.ScalarBinaryRd ||
|
||||
info.Type == IntrinsicType.ScalarTernaryFPRdByElem ||
|
||||
info.Type == IntrinsicType.ScalarTernaryShlRd ||
|
||||
info.Type == IntrinsicType.ScalarTernaryShrRd ||
|
||||
info.Type == IntrinsicType.VectorBinaryRd ||
|
||||
info.Type == IntrinsicType.VectorInsertByElem ||
|
||||
info.Type == IntrinsicType.VectorTernaryRd ||
|
||||
info.Type == IntrinsicType.VectorTernaryRdBitwise ||
|
||||
info.Type == IntrinsicType.VectorTernaryFPRdByElem ||
|
||||
info.Type == IntrinsicType.VectorTernaryRdByElem ||
|
||||
info.Type == IntrinsicType.VectorTernaryShlRd ||
|
||||
info.Type == IntrinsicType.VectorTernaryShrRd;
|
||||
}
|
||||
|
||||
private static bool HasConstSrc1(Operation node, ulong value)
|
||||
{
|
||||
switch (node.Instruction)
|
||||
{
|
||||
case Instruction.Add:
|
||||
case Instruction.BranchIf:
|
||||
case Instruction.Compare:
|
||||
case Instruction.Subtract:
|
||||
// The immediate encoding of those instructions does not allow Rn to be
|
||||
// XZR (it will be SP instead), so we can't allow a Rn constant in this case.
|
||||
return value == 0 && NotConstOrConst0(node.GetSource(1));
|
||||
case Instruction.BitwiseAnd:
|
||||
case Instruction.BitwiseExclusiveOr:
|
||||
case Instruction.BitwiseNot:
|
||||
case Instruction.BitwiseOr:
|
||||
case Instruction.ByteSwap:
|
||||
case Instruction.CountLeadingZeros:
|
||||
case Instruction.Multiply:
|
||||
case Instruction.Negate:
|
||||
case Instruction.RotateRight:
|
||||
case Instruction.ShiftLeft:
|
||||
case Instruction.ShiftRightSI:
|
||||
case Instruction.ShiftRightUI:
|
||||
return value == 0;
|
||||
case Instruction.Copy:
|
||||
case Instruction.LoadArgument:
|
||||
case Instruction.Spill:
|
||||
case Instruction.SpillArg:
|
||||
return true;
|
||||
case Instruction.Extended:
|
||||
return value == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool NotConstOrConst0(Operand operand)
|
||||
{
|
||||
return operand.Kind != OperandKind.Constant || operand.Value == 0;
|
||||
}
|
||||
|
||||
private static bool HasConstSrc2(Instruction inst, Operand operand)
|
||||
{
|
||||
ulong value = operand.Value;
|
||||
|
||||
switch (inst)
|
||||
{
|
||||
case Instruction.Add:
|
||||
case Instruction.BranchIf:
|
||||
case Instruction.Compare:
|
||||
case Instruction.Subtract:
|
||||
return ConstFitsOnUImm12Sh(value);
|
||||
case Instruction.BitwiseAnd:
|
||||
case Instruction.BitwiseExclusiveOr:
|
||||
case Instruction.BitwiseOr:
|
||||
return value == 0 || CodeGenCommon.TryEncodeBitMask(operand, out _, out _, out _);
|
||||
case Instruction.Multiply:
|
||||
case Instruction.Store:
|
||||
case Instruction.Store16:
|
||||
case Instruction.Store8:
|
||||
return value == 0;
|
||||
case Instruction.RotateRight:
|
||||
case Instruction.ShiftLeft:
|
||||
case Instruction.ShiftRightSI:
|
||||
case Instruction.ShiftRightUI:
|
||||
case Instruction.VectorExtract:
|
||||
case Instruction.VectorExtract16:
|
||||
case Instruction.VectorExtract8:
|
||||
return true;
|
||||
case Instruction.Extended:
|
||||
// TODO: Check if actual intrinsic is supposed to have consts here?
|
||||
// Right now we only hit this case for fixed-point int <-> FP conversion instructions.
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsCommutative(Operation operation)
|
||||
{
|
||||
switch (operation.Instruction)
|
||||
{
|
||||
case Instruction.Add:
|
||||
case Instruction.BitwiseAnd:
|
||||
case Instruction.BitwiseExclusiveOr:
|
||||
case Instruction.BitwiseOr:
|
||||
case Instruction.Multiply:
|
||||
return true;
|
||||
|
||||
case Instruction.BranchIf:
|
||||
case Instruction.Compare:
|
||||
{
|
||||
Operand comp = operation.GetSource(2);
|
||||
|
||||
Debug.Assert(comp.Kind == OperandKind.Constant);
|
||||
|
||||
var compType = (Comparison)comp.AsInt32();
|
||||
|
||||
return compType == Comparison.Equal || compType == Comparison.NotEqual;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool ConstFitsOnUImm12Sh(ulong value)
|
||||
{
|
||||
return (value & ~0xfffUL) == 0 || (value & ~0xfff000UL) == 0;
|
||||
}
|
||||
|
||||
private static bool IsIntrinsicWithConst(Operation operation)
|
||||
{
|
||||
bool isIntrinsic = IsIntrinsic(operation.Instruction);
|
||||
|
||||
if (isIntrinsic)
|
||||
{
|
||||
Intrinsic intrinsic = operation.Intrinsic;
|
||||
IntrinsicInfo info = IntrinsicTable.GetInfo(intrinsic & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask));
|
||||
|
||||
// Those have integer inputs that don't support consts.
|
||||
return info.Type != IntrinsicType.ScalarFPConvGpr &&
|
||||
info.Type != IntrinsicType.ScalarFPConvFixedGpr &&
|
||||
info.Type != IntrinsicType.SetRegister;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsIntrinsic(Instruction inst)
|
||||
{
|
||||
return inst == Instruction.Extended;
|
||||
}
|
||||
}
|
||||
}
|
@ -90,6 +90,47 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
}
|
||||
break;
|
||||
|
||||
case Instruction.Compare:
|
||||
if (type == OperandType.I32 &&
|
||||
operation.GetSource(0).Type == type &&
|
||||
operation.GetSource(1).Type == type)
|
||||
{
|
||||
switch ((Comparison)operation.GetSource(2).Value)
|
||||
{
|
||||
case Comparison.Equal:
|
||||
EvaluateBinaryI32(operation, (x, y) => x == y ? 1 : 0);
|
||||
break;
|
||||
case Comparison.NotEqual:
|
||||
EvaluateBinaryI32(operation, (x, y) => x != y ? 1 : 0);
|
||||
break;
|
||||
case Comparison.Greater:
|
||||
EvaluateBinaryI32(operation, (x, y) => x > y ? 1 : 0);
|
||||
break;
|
||||
case Comparison.LessOrEqual:
|
||||
EvaluateBinaryI32(operation, (x, y) => x <= y ? 1 : 0);
|
||||
break;
|
||||
case Comparison.GreaterUI:
|
||||
EvaluateBinaryI32(operation, (x, y) => (uint)x > (uint)y ? 1 : 0);
|
||||
break;
|
||||
case Comparison.LessOrEqualUI:
|
||||
EvaluateBinaryI32(operation, (x, y) => (uint)x <= (uint)y ? 1 : 0);
|
||||
break;
|
||||
case Comparison.GreaterOrEqual:
|
||||
EvaluateBinaryI32(operation, (x, y) => x >= y ? 1 : 0);
|
||||
break;
|
||||
case Comparison.Less:
|
||||
EvaluateBinaryI32(operation, (x, y) => x < y ? 1 : 0);
|
||||
break;
|
||||
case Comparison.GreaterOrEqualUI:
|
||||
EvaluateBinaryI32(operation, (x, y) => (uint)x >= (uint)y ? 1 : 0);
|
||||
break;
|
||||
case Comparison.LessUI:
|
||||
EvaluateBinaryI32(operation, (x, y) => (uint)x < (uint)y ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Instruction.Copy:
|
||||
if (type == OperandType.I32)
|
||||
{
|
||||
|
@ -44,8 +44,8 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
ConstantFolding.RunPass(node);
|
||||
Simplification.RunPass(node);
|
||||
|
||||
if (DestIsLocalVar(node))
|
||||
{
|
||||
if (DestIsSingleLocalVar(node))
|
||||
{
|
||||
if (IsPropagableCompare(node))
|
||||
{
|
||||
modified |= PropagateCompare(ref buffer, node);
|
||||
@ -99,20 +99,6 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
while (modified);
|
||||
}
|
||||
|
||||
private static Span<Operation> GetUses(ref Span<Operation> buffer, Operand operand)
|
||||
{
|
||||
ReadOnlySpan<Operation> uses = operand.Uses;
|
||||
|
||||
if (buffer.Length < uses.Length)
|
||||
{
|
||||
buffer = Allocators.Default.AllocateSpan<Operation>((uint)uses.Length);
|
||||
}
|
||||
|
||||
uses.CopyTo(buffer);
|
||||
|
||||
return buffer.Slice(0, uses.Length);
|
||||
}
|
||||
|
||||
private static bool PropagateCompare(ref Span<Operation> buffer, Operation compOp)
|
||||
{
|
||||
// Try to propagate Compare operations into their BranchIf uses, when these BranchIf uses are in the form
|
||||
@ -160,7 +146,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
|
||||
Comparison compType = (Comparison)comp.AsInt32();
|
||||
|
||||
Span<Operation> uses = GetUses(ref buffer, dest);
|
||||
Span<Operation> uses = dest.GetUses(ref buffer);
|
||||
|
||||
foreach (Operation use in uses)
|
||||
{
|
||||
@ -199,7 +185,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
Operand dest = copyOp.Destination;
|
||||
Operand source = copyOp.GetSource(0);
|
||||
|
||||
Span<Operation> uses = GetUses(ref buffer, dest);
|
||||
Span<Operation> uses = dest.GetUses(ref buffer);
|
||||
|
||||
foreach (Operation use in uses)
|
||||
{
|
||||
@ -231,12 +217,12 @@ namespace ARMeilleure.CodeGen.Optimizations
|
||||
|
||||
private static bool IsUnused(Operation node)
|
||||
{
|
||||
return DestIsLocalVar(node) && node.Destination.UsesCount == 0 && !HasSideEffects(node);
|
||||
return DestIsSingleLocalVar(node) && node.Destination.UsesCount == 0 && !HasSideEffects(node);
|
||||
}
|
||||
|
||||
private static bool DestIsLocalVar(Operation node)
|
||||
private static bool DestIsSingleLocalVar(Operation node)
|
||||
{
|
||||
return node.Destination != default && node.Destination.Kind == OperandKind.LocalVariable;
|
||||
return node.DestinationsCount == 1 && node.Destination.Kind == OperandKind.LocalVariable;
|
||||
}
|
||||
|
||||
private static bool HasSideEffects(Operation node)
|
||||
|
@ -17,8 +17,6 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
private const int InstructionGap = 2;
|
||||
private const int InstructionGapMask = InstructionGap - 1;
|
||||
|
||||
private const int RegistersCount = 16;
|
||||
|
||||
private HashSet<int> _blockEdges;
|
||||
private LiveRange[] _blockRanges;
|
||||
private BitMap[] _blockLiveIn;
|
||||
@ -59,7 +57,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
|
||||
void PopulateFreePositions(RegisterType type, out int[] positions, out int count)
|
||||
{
|
||||
positions = new int[RegistersCount];
|
||||
positions = new int[masks.RegistersCount];
|
||||
count = BitOperations.PopCount((uint)masks.GetAvailableRegisters(type));
|
||||
|
||||
int mask = masks.GetAvailableRegisters(type);
|
||||
@ -115,7 +113,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
StackAllocator stackAlloc,
|
||||
RegisterMasks regMasks)
|
||||
{
|
||||
NumberLocals(cfg);
|
||||
NumberLocals(cfg, regMasks.RegistersCount);
|
||||
|
||||
var context = new AllocationContext(stackAlloc, regMasks, _intervals.Count);
|
||||
|
||||
@ -134,22 +132,25 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
{
|
||||
context.Active.Set(index);
|
||||
|
||||
if (current.Register.Type == RegisterType.Integer)
|
||||
if (current.IsFixedAndUsed)
|
||||
{
|
||||
context.IntUsedRegisters |= 1 << current.Register.Index;
|
||||
}
|
||||
else /* if (interval.Register.Type == RegisterType.Vector) */
|
||||
{
|
||||
context.VecUsedRegisters |= 1 << current.Register.Index;
|
||||
if (current.Register.Type == RegisterType.Integer)
|
||||
{
|
||||
context.IntUsedRegisters |= 1 << current.Register.Index;
|
||||
}
|
||||
else /* if (interval.Register.Type == RegisterType.Vector) */
|
||||
{
|
||||
context.VecUsedRegisters |= 1 << current.Register.Index;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
AllocateInterval(context, current, index);
|
||||
AllocateInterval(context, current, index, regMasks.RegistersCount);
|
||||
}
|
||||
|
||||
for (int index = RegistersCount * 2; index < _intervals.Count; index++)
|
||||
for (int index = regMasks.RegistersCount * 2; index < _intervals.Count; index++)
|
||||
{
|
||||
if (!_intervals[index].IsSpilled)
|
||||
{
|
||||
@ -163,7 +164,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
return new AllocationResult(context.IntUsedRegisters, context.VecUsedRegisters, context.StackAlloc.TotalSize);
|
||||
}
|
||||
|
||||
private void AllocateInterval(AllocationContext context, LiveInterval current, int cIndex)
|
||||
private void AllocateInterval(AllocationContext context, LiveInterval current, int cIndex, int registersCount)
|
||||
{
|
||||
// Check active intervals that already ended.
|
||||
foreach (int iIndex in context.Active)
|
||||
@ -199,17 +200,17 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
}
|
||||
}
|
||||
|
||||
if (!TryAllocateRegWithoutSpill(context, current, cIndex))
|
||||
if (!TryAllocateRegWithoutSpill(context, current, cIndex, registersCount))
|
||||
{
|
||||
AllocateRegWithSpill(context, current, cIndex);
|
||||
AllocateRegWithSpill(context, current, cIndex, registersCount);
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryAllocateRegWithoutSpill(AllocationContext context, LiveInterval current, int cIndex)
|
||||
private bool TryAllocateRegWithoutSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount)
|
||||
{
|
||||
RegisterType regType = current.Local.Type.ToRegisterType();
|
||||
|
||||
Span<int> freePositions = stackalloc int[RegistersCount];
|
||||
Span<int> freePositions = stackalloc int[registersCount];
|
||||
|
||||
context.GetFreePositions(regType, freePositions, out int freePositionsCount);
|
||||
|
||||
@ -278,7 +279,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
{
|
||||
Debug.Assert(splitChild.GetStart() > current.GetStart(), "Split interval has an invalid start position.");
|
||||
|
||||
InsertInterval(splitChild);
|
||||
InsertInterval(splitChild, registersCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -302,12 +303,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
return true;
|
||||
}
|
||||
|
||||
private void AllocateRegWithSpill(AllocationContext context, LiveInterval current, int cIndex)
|
||||
private void AllocateRegWithSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount)
|
||||
{
|
||||
RegisterType regType = current.Local.Type.ToRegisterType();
|
||||
|
||||
Span<int> usePositions = stackalloc int[RegistersCount];
|
||||
Span<int> blockedPositions = stackalloc int[RegistersCount];
|
||||
Span<int> usePositions = stackalloc int[registersCount];
|
||||
Span<int> blockedPositions = stackalloc int[registersCount];
|
||||
|
||||
context.GetFreePositions(regType, usePositions, out _);
|
||||
context.GetFreePositions(regType, blockedPositions, out _);
|
||||
@ -386,7 +387,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
|
||||
Debug.Assert(splitChild.GetStart() > current.GetStart(), "Split interval has an invalid start position.");
|
||||
|
||||
InsertInterval(splitChild);
|
||||
InsertInterval(splitChild, registersCount);
|
||||
|
||||
Spill(context, current);
|
||||
}
|
||||
@ -396,7 +397,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
// so we only need to split the intervals using the selected register.
|
||||
current.Register = new Register(selectedReg, regType);
|
||||
|
||||
SplitAndSpillOverlappingIntervals(context, current);
|
||||
SplitAndSpillOverlappingIntervals(context, current, registersCount);
|
||||
|
||||
context.Active.Set(cIndex);
|
||||
}
|
||||
@ -417,14 +418,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
{
|
||||
Debug.Assert(splitChild.GetStart() > current.GetStart(), "Split interval has an invalid start position.");
|
||||
|
||||
InsertInterval(splitChild);
|
||||
InsertInterval(splitChild, registersCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
Spill(context, splitChild);
|
||||
}
|
||||
|
||||
SplitAndSpillOverlappingIntervals(context, current);
|
||||
SplitAndSpillOverlappingIntervals(context, current, registersCount);
|
||||
|
||||
context.Active.Set(cIndex);
|
||||
}
|
||||
@ -460,7 +461,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
return selected;
|
||||
}
|
||||
|
||||
private void SplitAndSpillOverlappingIntervals(AllocationContext context, LiveInterval current)
|
||||
private void SplitAndSpillOverlappingIntervals(AllocationContext context, LiveInterval current, int registersCount)
|
||||
{
|
||||
foreach (int iIndex in context.Active)
|
||||
{
|
||||
@ -468,7 +469,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
|
||||
if (!interval.IsFixed && interval.Register == current.Register)
|
||||
{
|
||||
SplitAndSpillOverlappingInterval(context, current, interval);
|
||||
SplitAndSpillOverlappingInterval(context, current, interval, registersCount);
|
||||
|
||||
context.Active.Clear(iIndex);
|
||||
}
|
||||
@ -480,7 +481,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
|
||||
if (!interval.IsFixed && interval.Register == current.Register && interval.Overlaps(current))
|
||||
{
|
||||
SplitAndSpillOverlappingInterval(context, current, interval);
|
||||
SplitAndSpillOverlappingInterval(context, current, interval, registersCount);
|
||||
|
||||
context.Inactive.Clear(iIndex);
|
||||
}
|
||||
@ -490,7 +491,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
private void SplitAndSpillOverlappingInterval(
|
||||
AllocationContext context,
|
||||
LiveInterval current,
|
||||
LiveInterval interval)
|
||||
LiveInterval interval,
|
||||
int registersCount)
|
||||
{
|
||||
// If there's a next use after the start of the current interval,
|
||||
// we need to split the spilled interval twice, and re-insert it
|
||||
@ -522,7 +524,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
splitChild = right;
|
||||
}
|
||||
|
||||
InsertInterval(splitChild);
|
||||
InsertInterval(splitChild, registersCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -530,13 +532,13 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
}
|
||||
}
|
||||
|
||||
private void InsertInterval(LiveInterval interval)
|
||||
private void InsertInterval(LiveInterval interval, int registersCount)
|
||||
{
|
||||
Debug.Assert(interval.UsesCount != 0, "Trying to insert a interval without uses.");
|
||||
Debug.Assert(!interval.IsEmpty, "Trying to insert a empty interval.");
|
||||
Debug.Assert(!interval.IsSpilled, "Trying to insert a spilled interval.");
|
||||
|
||||
int startIndex = RegistersCount * 2;
|
||||
int startIndex = registersCount * 2;
|
||||
|
||||
int insertIndex = _intervals.BinarySearch(startIndex, _intervals.Count - startIndex, interval, null);
|
||||
|
||||
@ -790,12 +792,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
return _operationNodes[position / InstructionGap];
|
||||
}
|
||||
|
||||
private void NumberLocals(ControlFlowGraph cfg)
|
||||
private void NumberLocals(ControlFlowGraph cfg, int registersCount)
|
||||
{
|
||||
_operationNodes = new List<(IntrusiveList<Operation>, Operation)>();
|
||||
_intervals = new List<LiveInterval>();
|
||||
|
||||
for (int index = 0; index < RegistersCount; index++)
|
||||
for (int index = 0; index < registersCount; index++)
|
||||
{
|
||||
_intervals.Add(new LiveInterval(new Register(index, RegisterType.Integer)));
|
||||
_intervals.Add(new LiveInterval(new Register(index, RegisterType.Vector)));
|
||||
@ -1041,6 +1043,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
{
|
||||
LiveInterval interval = _intervals[GetOperandId(dest)];
|
||||
|
||||
if (interval.IsFixed)
|
||||
{
|
||||
interval.IsFixedAndUsed = true;
|
||||
}
|
||||
|
||||
interval.SetStart(operationPos + 1);
|
||||
interval.AddUsePosition(operationPos + 1);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
public Register Register;
|
||||
|
||||
public bool IsFixed;
|
||||
public bool IsFixedAndUsed;
|
||||
}
|
||||
|
||||
private readonly Data* _data;
|
||||
@ -44,6 +45,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
public ref int SpillOffset => ref _data->SpillOffset;
|
||||
|
||||
public bool IsFixed => _data->IsFixed;
|
||||
public ref bool IsFixedAndUsed => ref _data->IsFixedAndUsed;
|
||||
public bool IsEmpty => FirstRange == default;
|
||||
public bool IsSplit => Children.Count != 0;
|
||||
public bool IsSpilled => SpillOffset != -1;
|
||||
@ -114,7 +116,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
}
|
||||
else
|
||||
{
|
||||
FirstRange = new LiveRange(position, position + 1);
|
||||
FirstRange = new LiveRange(position, position + 1);
|
||||
End = position + 1;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
public int VecCallerSavedRegisters { get; }
|
||||
public int IntCalleeSavedRegisters { get; }
|
||||
public int VecCalleeSavedRegisters { get; }
|
||||
public int RegistersCount { get; }
|
||||
|
||||
public RegisterMasks(
|
||||
int intAvailableRegisters,
|
||||
@ -18,7 +19,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
int intCallerSavedRegisters,
|
||||
int vecCallerSavedRegisters,
|
||||
int intCalleeSavedRegisters,
|
||||
int vecCalleeSavedRegisters)
|
||||
int vecCalleeSavedRegisters,
|
||||
int registersCount)
|
||||
{
|
||||
IntAvailableRegisters = intAvailableRegisters;
|
||||
VecAvailableRegisters = vecAvailableRegisters;
|
||||
@ -26,6 +28,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||
VecCallerSavedRegisters = vecCallerSavedRegisters;
|
||||
IntCalleeSavedRegisters = intCalleeSavedRegisters;
|
||||
VecCalleeSavedRegisters = vecCalleeSavedRegisters;
|
||||
RegistersCount = registersCount;
|
||||
}
|
||||
|
||||
public int GetAvailableRegisters(RegisterType type)
|
||||
|
@ -16,6 +16,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
static class CodeGenerator
|
||||
{
|
||||
private const int RegistersCount = 16;
|
||||
private const int PageSize = 0x1000;
|
||||
private const int StackGuardSize = 0x2000;
|
||||
|
||||
@ -143,7 +144,8 @@ namespace ARMeilleure.CodeGen.X86
|
||||
CallingConvention.GetIntCallerSavedRegisters(),
|
||||
CallingConvention.GetVecCallerSavedRegisters(),
|
||||
CallingConvention.GetIntCalleeSavedRegisters(),
|
||||
CallingConvention.GetVecCalleeSavedRegisters());
|
||||
CallingConvention.GetVecCalleeSavedRegisters(),
|
||||
RegistersCount);
|
||||
|
||||
AllocationResult allocResult = regAlloc.RunPass(cfg, stackAlloc, regMasks);
|
||||
|
||||
@ -1587,6 +1589,12 @@ namespace ARMeilleure.CodeGen.X86
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
|
||||
|
||||
// We can eliminate the move if source is already 32-bit and the registers are the same.
|
||||
if (dest.Value == source.Value && source.Type == OperandType.I32)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
context.Assembler.Mov(dest, source, OperandType.I32);
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,6 @@ namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
static class IntrinsicTable
|
||||
{
|
||||
private const int BadOp = 0;
|
||||
|
||||
private static IntrinsicInfo[] _intrinTable;
|
||||
|
||||
static IntrinsicTable()
|
||||
|
@ -80,10 +80,7 @@ namespace ARMeilleure.Common
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(null);
|
||||
}
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
lock (_pages)
|
||||
{
|
||||
@ -100,10 +97,7 @@ namespace ARMeilleure.Common
|
||||
/// <exception cref="ArgumentException">Length of <paramref name="levels"/> is less than 2</exception>
|
||||
public AddressTable(Level[] levels)
|
||||
{
|
||||
if (levels == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(levels));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(levels);
|
||||
|
||||
if (levels.Length < 2)
|
||||
{
|
||||
@ -141,10 +135,7 @@ namespace ARMeilleure.Common
|
||||
/// <exception cref="ArgumentException"><paramref name="address"/> is not mapped</exception>
|
||||
public ref TEntry GetValue(ulong address)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(null);
|
||||
}
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
if (!IsValid(address))
|
||||
{
|
||||
|
@ -49,10 +49,7 @@ namespace ARMeilleure.Common
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(null);
|
||||
}
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
return ref _countTable.GetValue(_index);
|
||||
}
|
||||
|
@ -53,10 +53,7 @@ namespace ARMeilleure.Common
|
||||
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
|
||||
public int Allocate()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(null);
|
||||
}
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
lock (_allocated)
|
||||
{
|
||||
@ -83,10 +80,7 @@ namespace ARMeilleure.Common
|
||||
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
|
||||
public void Free(int index)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(null);
|
||||
}
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
lock (_allocated)
|
||||
{
|
||||
@ -108,10 +102,7 @@ namespace ARMeilleure.Common
|
||||
/// <exception cref="ArgumentException">Entry at <paramref name="index"/> is not allocated</exception>
|
||||
public ref TEntry GetValue(int index)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(null);
|
||||
}
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
lock (_allocated)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,7 @@
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitFlowHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
@ -30,7 +31,11 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
|
||||
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, Intrinsic.Arm64FabsS);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitScalarUnaryOpSimd32(context, (m) =>
|
||||
{
|
||||
@ -49,7 +54,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorUnaryOpF32(context, Intrinsic.Arm64FabsV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorUnaryOpSimd32(context, (m) =>
|
||||
{
|
||||
@ -76,7 +85,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vadd_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarBinaryOpF32(context, Intrinsic.Arm64FaddS);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitScalarBinaryOpF32(context, Intrinsic.X86Addss, Intrinsic.X86Addsd);
|
||||
}
|
||||
@ -92,7 +105,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vadd_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorBinaryOpF32(context, Intrinsic.Arm64FaddV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorBinaryOpF32(context, Intrinsic.X86Addps, Intrinsic.X86Addpd);
|
||||
}
|
||||
@ -280,7 +297,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vfma_S(ArmEmitterContext context) // Fused.
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseFma)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarTernaryOpF32(context, Intrinsic.Arm64FmaddS);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseFma)
|
||||
{
|
||||
EmitScalarTernaryOpF32(context, Intrinsic.X86Vfmadd231ss, Intrinsic.X86Vfmadd231sd);
|
||||
}
|
||||
@ -299,7 +320,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vfma_V(ArmEmitterContext context) // Fused.
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseFma)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorTernaryOpF32(context, Intrinsic.Arm64FmlaV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseFma)
|
||||
{
|
||||
EmitVectorTernaryOpF32(context, Intrinsic.X86Vfmadd231ps);
|
||||
}
|
||||
@ -314,7 +339,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vfms_S(ArmEmitterContext context) // Fused.
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseFma)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarTernaryOpF32(context, Intrinsic.Arm64FmsubS);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseFma)
|
||||
{
|
||||
EmitScalarTernaryOpF32(context, Intrinsic.X86Vfnmadd231ss, Intrinsic.X86Vfnmadd231sd);
|
||||
}
|
||||
@ -333,7 +362,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vfms_V(ArmEmitterContext context) // Fused.
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseFma)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorTernaryOpF32(context, Intrinsic.Arm64FmlsV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseFma)
|
||||
{
|
||||
EmitVectorTernaryOpF32(context, Intrinsic.X86Vfnmadd231ps);
|
||||
}
|
||||
@ -348,7 +381,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vfnma_S(ArmEmitterContext context) // Fused.
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseFma)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarTernaryOpF32(context, Intrinsic.Arm64FnmaddS);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseFma)
|
||||
{
|
||||
EmitScalarTernaryOpF32(context, Intrinsic.X86Vfnmsub231ss, Intrinsic.X86Vfnmsub231sd);
|
||||
}
|
||||
@ -367,7 +404,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vfnms_S(ArmEmitterContext context) // Fused.
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseFma)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarTernaryOpF32(context, Intrinsic.Arm64FnmsubS);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseFma)
|
||||
{
|
||||
EmitScalarTernaryOpF32(context, Intrinsic.X86Vfmsub231ss, Intrinsic.X86Vfmsub231sd);
|
||||
}
|
||||
@ -419,7 +460,11 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
|
||||
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, Intrinsic.Arm64FnegS);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitScalarUnaryOpSimd32(context, (m) =>
|
||||
{
|
||||
@ -445,7 +490,11 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;
|
||||
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarBinaryOpF32(context, Intrinsic.Arm64FnmulS);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitScalarBinaryOpSimd32(context, (n, m) =>
|
||||
{
|
||||
@ -473,7 +522,11 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;
|
||||
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarTernaryOpF32(context, Intrinsic.Arm64FnmaddS);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitScalarTernaryOpF32(context, Intrinsic.X86Mulss, Intrinsic.X86Mulsd, Intrinsic.X86Subss, Intrinsic.X86Subsd, isNegD: true);
|
||||
}
|
||||
@ -498,7 +551,11 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;
|
||||
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarTernaryOpF32(context, Intrinsic.Arm64FnmsubS);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitScalarTernaryOpF32(context, Intrinsic.X86Mulss, Intrinsic.X86Mulsd, Intrinsic.X86Addss, Intrinsic.X86Addsd, isNegD: true);
|
||||
}
|
||||
@ -525,7 +582,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorUnaryOpF32(context, Intrinsic.Arm64FnegV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorUnaryOpSimd32(context, (m) =>
|
||||
{
|
||||
@ -554,7 +615,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vdiv_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarBinaryOpF32(context, Intrinsic.Arm64FdivS);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitScalarBinaryOpF32(context, Intrinsic.X86Divss, Intrinsic.X86Divsd);
|
||||
}
|
||||
@ -573,7 +638,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vmaxnm_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse41)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarBinaryOpF32(context, Intrinsic.Arm64FmaxnmS);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41MaxMinNumOpF32(context, true, true);
|
||||
}
|
||||
@ -585,7 +654,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vmaxnm_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse41)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorBinaryOpF32(context, Intrinsic.Arm64FmaxnmV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41MaxMinNumOpF32(context, true, false);
|
||||
}
|
||||
@ -597,7 +670,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vminnm_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse41)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarBinaryOpF32(context, Intrinsic.Arm64FminnmS);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41MaxMinNumOpF32(context, false, true);
|
||||
}
|
||||
@ -609,7 +686,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vminnm_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse41)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorBinaryOpF32(context, Intrinsic.Arm64FminnmV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41MaxMinNumOpF32(context, false, false);
|
||||
}
|
||||
@ -621,7 +702,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vmax_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorBinaryOpF32(context, Intrinsic.Arm64FmaxV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorBinaryOpF32(context, Intrinsic.X86Maxps, Intrinsic.X86Maxpd);
|
||||
}
|
||||
@ -664,7 +749,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vmin_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorBinaryOpF32(context, Intrinsic.Arm64FminV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorBinaryOpF32(context, Intrinsic.X86Minps, Intrinsic.X86Minpd);
|
||||
}
|
||||
@ -707,7 +796,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vmla_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarTernaryOpF32(context, Intrinsic.Arm64FmaddS);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitScalarTernaryOpF32(context, Intrinsic.X86Mulss, Intrinsic.X86Mulsd, Intrinsic.X86Addss, Intrinsic.X86Addsd);
|
||||
}
|
||||
@ -730,7 +823,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vmla_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorTernaryOpF32(context, Intrinsic.Arm64FmlaV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorTernaryOpF32(context, Intrinsic.X86Mulps, Intrinsic.X86Mulpd, Intrinsic.X86Addps, Intrinsic.X86Addpd);
|
||||
}
|
||||
@ -786,7 +883,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vmls_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarTernaryOpF32(context, Intrinsic.Arm64FmlsV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitScalarTernaryOpF32(context, Intrinsic.X86Mulss, Intrinsic.X86Mulsd, Intrinsic.X86Subss, Intrinsic.X86Subsd);
|
||||
}
|
||||
@ -809,7 +910,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vmls_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorTernaryOpF32(context, Intrinsic.Arm64FmlsV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorTernaryOpF32(context, Intrinsic.X86Mulps, Intrinsic.X86Mulpd, Intrinsic.X86Subps, Intrinsic.X86Subpd);
|
||||
}
|
||||
@ -865,7 +970,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vmul_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarBinaryOpF32(context, Intrinsic.Arm64FmulS);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitScalarBinaryOpF32(context, Intrinsic.X86Mulss, Intrinsic.X86Mulsd);
|
||||
}
|
||||
@ -884,7 +993,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vmul_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorBinaryOpF32(context, Intrinsic.Arm64FmulV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorBinaryOpF32(context, Intrinsic.X86Mulps, Intrinsic.X86Mulpd);
|
||||
}
|
||||
@ -975,7 +1088,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vpadd_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorPairwiseOpF32(context, Intrinsic.Arm64FaddpV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2VectorPairwiseOpF32(context, Intrinsic.X86Addps);
|
||||
}
|
||||
@ -1008,7 +1125,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vpmax_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorPairwiseOpF32(context, Intrinsic.Arm64FmaxpV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2VectorPairwiseOpF32(context, Intrinsic.X86Maxps);
|
||||
}
|
||||
@ -1038,7 +1159,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vpmin_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorPairwiseOpF32(context, Intrinsic.Arm64FminpV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2VectorPairwiseOpF32(context, Intrinsic.X86Minps);
|
||||
}
|
||||
@ -1217,7 +1342,11 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
int sizeF = op.Size & 1;
|
||||
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2 && sizeF == 0)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorUnaryOpF32(context, Intrinsic.Arm64FrecpeV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2 && sizeF == 0)
|
||||
{
|
||||
EmitVectorUnaryOpF32(context, Intrinsic.X86Rcpps, 0);
|
||||
}
|
||||
@ -1237,7 +1366,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vrecps(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorBinaryOpF32(context, Intrinsic.Arm64FrecpsV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
|
||||
bool single = (op.Size & 1) == 0;
|
||||
@ -1304,7 +1437,11 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
int sizeF = op.Size & 1;
|
||||
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2 && sizeF == 0)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorUnaryOpF32(context, Intrinsic.Arm64FrsqrteV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2 && sizeF == 0)
|
||||
{
|
||||
EmitVectorUnaryOpF32(context, Intrinsic.X86Rsqrtps, 0);
|
||||
}
|
||||
@ -1324,7 +1461,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vrsqrts(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorBinaryOpF32(context, Intrinsic.Arm64FrsqrtsV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
|
||||
bool single = (op.Size & 1) == 0;
|
||||
@ -1393,7 +1534,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vsqrt_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, Intrinsic.Arm64FsqrtS);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitScalarUnaryOpF32(context, Intrinsic.X86Sqrtss, Intrinsic.X86Sqrtsd);
|
||||
}
|
||||
@ -1408,7 +1553,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vsub_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarBinaryOpF32(context, Intrinsic.Arm64FsubS);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitScalarBinaryOpF32(context, Intrinsic.X86Subss, Intrinsic.X86Subsd);
|
||||
}
|
||||
@ -1420,7 +1569,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vsub_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorBinaryOpF32(context, Intrinsic.Arm64FsubV);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorBinaryOpF32(context, Intrinsic.X86Subps, Intrinsic.X86Subpd);
|
||||
}
|
||||
|
@ -466,12 +466,26 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcmp_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitFcmpOrFcmpe(context, signalNaNs: false);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitFcmpOrFcmpe(context, signalNaNs: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitFcmpOrFcmpe(context, signalNaNs: false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Fcmpe_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitFcmpOrFcmpe(context, signalNaNs: true);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitFcmpOrFcmpe(context, signalNaNs: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitFcmpOrFcmpe(context, signalNaNs: true);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitFccmpOrFccmpe(ArmEmitterContext context, bool signalNaNs)
|
||||
|
@ -17,7 +17,11 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
public static void Vceq_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitCmpOpF32(context, CmpCondition.Equal, false);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.Equal, false);
|
||||
}
|
||||
@ -38,7 +42,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitCmpOpF32(context, CmpCondition.Equal, true);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.Equal, true);
|
||||
}
|
||||
@ -55,7 +63,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vcge_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitCmpOpF32(context, CmpCondition.GreaterThanOrEqual, false);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.GreaterThanOrEqual, false);
|
||||
}
|
||||
@ -78,7 +90,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitCmpOpF32(context, CmpCondition.GreaterThanOrEqual, true);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.GreaterThanOrEqual, true);
|
||||
}
|
||||
@ -95,7 +111,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vcgt_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitCmpOpF32(context, CmpCondition.GreaterThan, false);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.GreaterThan, false);
|
||||
}
|
||||
@ -118,7 +138,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitCmpOpF32(context, CmpCondition.GreaterThan, true);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.GreaterThan, true);
|
||||
}
|
||||
@ -139,7 +163,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitCmpOpF32(context, CmpCondition.LessThanOrEqual, true);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.LessThanOrEqual, true);
|
||||
}
|
||||
@ -160,7 +188,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitCmpOpF32(context, CmpCondition.LessThan, true);
|
||||
}
|
||||
else if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.LessThan, true);
|
||||
}
|
||||
@ -247,12 +279,26 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vcmp(ArmEmitterContext context)
|
||||
{
|
||||
EmitVcmpOrVcmpe(context, false);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVcmpOrVcmpe(context, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitVcmpOrVcmpe(context, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Vcmpe(ArmEmitterContext context)
|
||||
{
|
||||
EmitVcmpOrVcmpe(context, true);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVcmpOrVcmpe(context, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitVcmpOrVcmpe(context, true);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitVcmpOrVcmpe(ArmEmitterContext context, bool signalNaNs)
|
||||
|
@ -164,7 +164,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtas_Gp(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpFToGp(context, Intrinsic.Arm64FcvtasGp);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvts_Gp(context, FPRoundingMode.ToNearestAway, isFixed: false);
|
||||
}
|
||||
@ -176,7 +180,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtas_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpF(context, Intrinsic.Arm64FcvtasS);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtsOpF(context, FPRoundingMode.ToNearestAway, scalar: true);
|
||||
}
|
||||
@ -188,7 +196,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtas_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorUnaryOpF(context, Intrinsic.Arm64FcvtasS);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtsOpF(context, FPRoundingMode.ToNearestAway, scalar: false);
|
||||
}
|
||||
@ -200,7 +212,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtau_Gp(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpFToGp(context, Intrinsic.Arm64FcvtauGp);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvtu_Gp(context, FPRoundingMode.ToNearestAway, isFixed: false);
|
||||
}
|
||||
@ -212,7 +228,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtau_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpF(context, Intrinsic.Arm64FcvtauS);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtuOpF(context, FPRoundingMode.ToNearestAway, scalar: true);
|
||||
}
|
||||
@ -224,7 +244,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtau_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorUnaryOpF(context, Intrinsic.Arm64FcvtauV);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtuOpF(context, FPRoundingMode.ToNearestAway, scalar: false);
|
||||
}
|
||||
@ -240,7 +264,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
int sizeF = op.Size & 1;
|
||||
|
||||
if (Optimizations.UseSse2 && sizeF == 1)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorUnaryOpF(context, Intrinsic.Arm64FcvtlV);
|
||||
}
|
||||
else if (Optimizations.UseSse2 && sizeF == 1)
|
||||
{
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
@ -296,7 +324,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtms_Gp(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpFToGp(context, Intrinsic.Arm64FcvtmsGp);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvts_Gp(context, FPRoundingMode.TowardsMinusInfinity, isFixed: false);
|
||||
}
|
||||
@ -308,7 +340,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtms_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorUnaryOpF(context, Intrinsic.Arm64FcvtmsV);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtsOpF(context, FPRoundingMode.TowardsMinusInfinity, scalar: false);
|
||||
}
|
||||
@ -320,7 +356,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtmu_Gp(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpFToGp(context, Intrinsic.Arm64FcvtmuGp);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvtu_Gp(context, FPRoundingMode.TowardsMinusInfinity, isFixed: false);
|
||||
}
|
||||
@ -336,7 +376,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
int sizeF = op.Size & 1;
|
||||
|
||||
if (Optimizations.UseSse2 && sizeF == 1)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorBinaryOpFRd(context, Intrinsic.Arm64FcvtnV);
|
||||
}
|
||||
else if (Optimizations.UseSse2 && sizeF == 1)
|
||||
{
|
||||
Operand d = GetVec(op.Rd);
|
||||
|
||||
@ -381,7 +425,7 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
for (int index = 0; index < elems; index++)
|
||||
{
|
||||
Operand ne = context.VectorExtract(type, GetVec(op.Rn), 0);
|
||||
Operand ne = context.VectorExtract(type, GetVec(op.Rn), index);
|
||||
|
||||
if (sizeF == 0)
|
||||
{
|
||||
@ -389,8 +433,6 @@ namespace ARMeilleure.Instructions
|
||||
Operand e = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
|
||||
context.LoadFromContext();
|
||||
|
||||
e = context.ZeroExtend16(OperandType.I64, e);
|
||||
|
||||
res = EmitVectorInsert(context, res, e, part + index, 1);
|
||||
}
|
||||
else /* if (sizeF == 1) */
|
||||
@ -407,7 +449,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtns_Gp(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpFToGp(context, Intrinsic.Arm64FcvtnsGp);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvts_Gp(context, FPRoundingMode.ToNearest, isFixed: false);
|
||||
}
|
||||
@ -419,7 +465,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtns_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpF(context, Intrinsic.Arm64FcvtnsS);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtsOpF(context, FPRoundingMode.ToNearest, scalar: true);
|
||||
}
|
||||
@ -431,7 +481,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtns_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorUnaryOpF(context, Intrinsic.Arm64FcvtnsV);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtsOpF(context, FPRoundingMode.ToNearest, scalar: false);
|
||||
}
|
||||
@ -443,7 +497,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtnu_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpF(context, Intrinsic.Arm64FcvtnuS);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtuOpF(context, FPRoundingMode.ToNearest, scalar: true);
|
||||
}
|
||||
@ -455,7 +513,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtnu_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorUnaryOpF(context, Intrinsic.Arm64FcvtnuV);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtuOpF(context, FPRoundingMode.ToNearest, scalar: false);
|
||||
}
|
||||
@ -467,7 +529,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtps_Gp(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpFToGp(context, Intrinsic.Arm64FcvtpsGp);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvts_Gp(context, FPRoundingMode.TowardsPlusInfinity, isFixed: false);
|
||||
}
|
||||
@ -479,7 +545,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtpu_Gp(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpFToGp(context, Intrinsic.Arm64FcvtpuGp);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvtu_Gp(context, FPRoundingMode.TowardsPlusInfinity, isFixed: false);
|
||||
}
|
||||
@ -491,7 +561,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtzs_Gp(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpFToGp(context, Intrinsic.Arm64FcvtzsGp);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvts_Gp(context, FPRoundingMode.TowardsZero, isFixed: false);
|
||||
}
|
||||
@ -503,7 +577,13 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtzs_Gp_Fixed(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarConvertBinaryOpFToGp(context, Intrinsic.Arm64FcvtzsGpFixed, op.FBits);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvts_Gp(context, FPRoundingMode.TowardsZero, isFixed: true);
|
||||
}
|
||||
@ -515,7 +595,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtzs_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpF(context, Intrinsic.Arm64FcvtzsS);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtsOpF(context, FPRoundingMode.TowardsZero, scalar: true);
|
||||
}
|
||||
@ -527,7 +611,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtzs_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorUnaryOpF(context, Intrinsic.Arm64FcvtzsV);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtsOpF(context, FPRoundingMode.TowardsZero, scalar: false);
|
||||
}
|
||||
@ -539,7 +627,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtzs_V_Fixed(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorConvertBinaryOpF(context, Intrinsic.Arm64FcvtzsVFixed, GetFBits(context));
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtsOpF(context, FPRoundingMode.TowardsZero, scalar: false);
|
||||
}
|
||||
@ -551,7 +643,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtzu_Gp(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpFToGp(context, Intrinsic.Arm64FcvtzuGp);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvtu_Gp(context, FPRoundingMode.TowardsZero, isFixed: false);
|
||||
}
|
||||
@ -563,7 +659,13 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtzu_Gp_Fixed(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarConvertBinaryOpFToGp(context, Intrinsic.Arm64FcvtzuGpFixed, op.FBits);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvtu_Gp(context, FPRoundingMode.TowardsZero, isFixed: true);
|
||||
}
|
||||
@ -575,7 +677,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtzu_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpF(context, Intrinsic.Arm64FcvtzuS);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtuOpF(context, FPRoundingMode.TowardsZero, scalar: true);
|
||||
}
|
||||
@ -587,7 +693,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtzu_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorUnaryOpF(context, Intrinsic.Arm64FcvtzuV);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtuOpF(context, FPRoundingMode.TowardsZero, scalar: false);
|
||||
}
|
||||
@ -599,7 +709,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Fcvtzu_V_Fixed(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorConvertBinaryOpF(context, Intrinsic.Arm64FcvtzuVFixed, GetFBits(context));
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41FcvtuOpF(context, FPRoundingMode.TowardsZero, scalar: false);
|
||||
}
|
||||
@ -611,41 +725,59 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Scvtf_Gp(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Int32)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
res = context.SignExtend32(OperandType.I64, res);
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpFFromGp(context, Intrinsic.Arm64ScvtfGp);
|
||||
}
|
||||
else
|
||||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
|
||||
res = EmitFPConvert(context, res, op.Size, signed: true);
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||
if (op.RegisterSize == RegisterSize.Int32)
|
||||
{
|
||||
res = context.SignExtend32(OperandType.I64, res);
|
||||
}
|
||||
|
||||
res = EmitFPConvert(context, res, op.Size, signed: true);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Scvtf_Gp_Fixed(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Int32)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
res = context.SignExtend32(OperandType.I64, res);
|
||||
InstEmitSimdHelperArm64.EmitScalarConvertBinaryOpFFromGp(context, Intrinsic.Arm64ScvtfGpFixed, op.FBits);
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
res = EmitFPConvert(context, res, op.Size, signed: true);
|
||||
if (op.RegisterSize == RegisterSize.Int32)
|
||||
{
|
||||
res = context.SignExtend32(OperandType.I64, res);
|
||||
}
|
||||
|
||||
res = EmitI2fFBitsMul(context, res, op.FBits);
|
||||
res = EmitFPConvert(context, res, op.Size, signed: true);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||
res = EmitI2fFBitsMul(context, res, op.FBits);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Scvtf_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpF(context, Intrinsic.Arm64ScvtfS);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2ScvtfOp(context, scalar: true);
|
||||
}
|
||||
@ -657,7 +789,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Scvtf_S_Fixed(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarConvertBinaryOpF(context, Intrinsic.Arm64ScvtfSFixed, GetFBits(context));
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2ScvtfOp(context, scalar: true);
|
||||
}
|
||||
@ -669,7 +805,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Scvtf_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorUnaryOpF(context, Intrinsic.Arm64ScvtfV);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2ScvtfOp(context, scalar: false);
|
||||
}
|
||||
@ -681,7 +821,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Scvtf_V_Fixed(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorConvertBinaryOpF(context, Intrinsic.Arm64ScvtfVFixed, GetFBits(context));
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2ScvtfOp(context, scalar: false);
|
||||
}
|
||||
@ -693,31 +837,49 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Ucvtf_Gp(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpFFromGp(context, Intrinsic.Arm64UcvtfGp);
|
||||
}
|
||||
else
|
||||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
res = EmitFPConvert(context, res, op.Size, signed: false);
|
||||
res = EmitFPConvert(context, res, op.Size, signed: false);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Ucvtf_Gp_Fixed(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarConvertBinaryOpFFromGp(context, Intrinsic.Arm64UcvtfGpFixed, op.FBits);
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
res = EmitFPConvert(context, res, op.Size, signed: false);
|
||||
res = EmitFPConvert(context, res, op.Size, signed: false);
|
||||
|
||||
res = EmitI2fFBitsMul(context, res, op.FBits);
|
||||
res = EmitI2fFBitsMul(context, res, op.FBits);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Ucvtf_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarUnaryOpF(context, Intrinsic.Arm64UcvtfS);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2UcvtfOp(context, scalar: true);
|
||||
}
|
||||
@ -729,7 +891,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Ucvtf_S_Fixed(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarConvertBinaryOpF(context, Intrinsic.Arm64UcvtfSFixed, GetFBits(context));
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2UcvtfOp(context, scalar: true);
|
||||
}
|
||||
@ -741,7 +907,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Ucvtf_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorUnaryOpF(context, Intrinsic.Arm64UcvtfV);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2UcvtfOp(context, scalar: false);
|
||||
}
|
||||
@ -753,7 +923,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Ucvtf_V_Fixed(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorConvertBinaryOpF(context, Intrinsic.Arm64UcvtfVFixed, GetFBits(context));
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2UcvtfOp(context, scalar: false);
|
||||
}
|
||||
|
@ -59,7 +59,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
if (toInteger)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorUnaryOpF32(context, unsigned ? Intrinsic.Arm64FcvtzuV : Intrinsic.Arm64FcvtzsV);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41ConvertVector32(context, FPRoundingMode.TowardsZero, !unsigned);
|
||||
}
|
||||
@ -153,7 +157,28 @@ namespace ARMeilleure.Instructions
|
||||
bool unsigned = (op.Opc2 & 1) == 0;
|
||||
bool roundWithFpscr = op.Opc != 1;
|
||||
|
||||
if (!roundWithFpscr && Optimizations.UseSse41)
|
||||
if (!roundWithFpscr && Optimizations.UseAdvSimd)
|
||||
{
|
||||
bool doubleSize = floatSize == OperandType.FP64;
|
||||
|
||||
if (doubleSize)
|
||||
{
|
||||
Operand m = GetVecA32(op.Vm >> 1);
|
||||
|
||||
Operand toConvert = InstEmitSimdHelper32Arm64.EmitExtractScalar(context, m, op.Vm, doubleSize);
|
||||
|
||||
Intrinsic inst = (unsigned ? Intrinsic.Arm64FcvtzuGp : Intrinsic.Arm64FcvtzsGp) | Intrinsic.Arm64VDouble;
|
||||
|
||||
Operand asInteger = context.AddIntrinsicInt(inst, toConvert);
|
||||
|
||||
InsertScalar(context, op.Vd, asInteger);
|
||||
}
|
||||
else
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, unsigned ? Intrinsic.Arm64FcvtzuS : Intrinsic.Arm64FcvtzsS);
|
||||
}
|
||||
}
|
||||
else if (!roundWithFpscr && Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41ConvertInt32(context, FPRoundingMode.TowardsZero, !unsigned);
|
||||
}
|
||||
@ -231,7 +256,34 @@ namespace ARMeilleure.Instructions
|
||||
bool unsigned = op.Opc == 0;
|
||||
int rm = op.Opc2 & 3;
|
||||
|
||||
if (Optimizations.UseSse41)
|
||||
Intrinsic inst;
|
||||
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
if (unsigned)
|
||||
{
|
||||
inst = rm switch {
|
||||
0b00 => Intrinsic.Arm64FcvtauS,
|
||||
0b01 => Intrinsic.Arm64FcvtnuS,
|
||||
0b10 => Intrinsic.Arm64FcvtpuS,
|
||||
0b11 => Intrinsic.Arm64FcvtmuS,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
inst = rm switch {
|
||||
0b00 => Intrinsic.Arm64FcvtasS,
|
||||
0b01 => Intrinsic.Arm64FcvtnsS,
|
||||
0b10 => Intrinsic.Arm64FcvtpsS,
|
||||
0b11 => Intrinsic.Arm64FcvtmsS,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
};
|
||||
}
|
||||
|
||||
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, inst);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41ConvertInt32(context, RMToRoundMode(rm), !unsigned);
|
||||
}
|
||||
@ -338,7 +390,19 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
int rm = op.Opc2 & 3;
|
||||
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
Intrinsic inst = rm switch {
|
||||
0b00 => Intrinsic.Arm64FrintaS,
|
||||
0b01 => Intrinsic.Arm64FrintnS,
|
||||
0b10 => Intrinsic.Arm64FrintpS,
|
||||
0b11 => Intrinsic.Arm64FrintmS,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
};
|
||||
|
||||
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, inst);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitScalarUnaryOpSimd32(context, (m) =>
|
||||
{
|
||||
@ -382,12 +446,9 @@ namespace ARMeilleure.Instructions
|
||||
// VRINTA (vector).
|
||||
public static void Vrinta_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
EmitVectorUnaryOpSimd32(context, (m) =>
|
||||
{
|
||||
return EmitSse41RoundToNearestWithTiesToAwayOpF(context, m, scalar: false);
|
||||
});
|
||||
InstEmitSimdHelper32Arm64.EmitVectorUnaryOpF32(context, Intrinsic.Arm64FrintaS);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -398,7 +459,11 @@ namespace ARMeilleure.Instructions
|
||||
// VRINTM (vector).
|
||||
public static void Vrintm_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorUnaryOpF32(context, Intrinsic.Arm64FrintmS);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorUnaryOpSimd32(context, (m) =>
|
||||
{
|
||||
@ -414,7 +479,11 @@ namespace ARMeilleure.Instructions
|
||||
// VRINTN (vector).
|
||||
public static void Vrintn_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorUnaryOpF32(context, Intrinsic.Arm64FrintnS);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorUnaryOpSimd32(context, (m) =>
|
||||
{
|
||||
@ -430,7 +499,11 @@ namespace ARMeilleure.Instructions
|
||||
// VRINTP (vector).
|
||||
public static void Vrintp_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorUnaryOpF32(context, Intrinsic.Arm64FrintpS);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorUnaryOpSimd32(context, (m) =>
|
||||
{
|
||||
@ -448,7 +521,11 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
|
||||
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, Intrinsic.Arm64FrintzS);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitScalarUnaryOpSimd32(context, (m) =>
|
||||
{
|
||||
|
366
ARMeilleure/Instructions/InstEmitSimdHelper32Arm64.cs
Normal file
366
ARMeilleure/Instructions/InstEmitSimdHelper32Arm64.cs
Normal file
@ -0,0 +1,366 @@
|
||||
|
||||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
using Func1I = Func<Operand, Operand>;
|
||||
using Func2I = Func<Operand, Operand, Operand>;
|
||||
using Func3I = Func<Operand, Operand, Operand, Operand>;
|
||||
|
||||
static class InstEmitSimdHelper32Arm64
|
||||
{
|
||||
// Intrinsic Helpers
|
||||
|
||||
public static Operand EmitMoveDoubleWordToSide(ArmEmitterContext context, Operand input, int originalV, int targetV)
|
||||
{
|
||||
Debug.Assert(input.Type == OperandType.V128);
|
||||
|
||||
int originalSide = originalV & 1;
|
||||
int targetSide = targetV & 1;
|
||||
|
||||
if (originalSide == targetSide)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
Intrinsic vType = Intrinsic.Arm64VDWord | Intrinsic.Arm64V128;
|
||||
|
||||
if (targetSide == 1)
|
||||
{
|
||||
return context.AddIntrinsic(Intrinsic.Arm64DupVe | vType, input, Const(OperandType.I32, 0)); // Low to high.
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.AddIntrinsic(Intrinsic.Arm64DupVe | vType, input, Const(OperandType.I32, 1)); // High to low.
|
||||
}
|
||||
}
|
||||
|
||||
public static Operand EmitDoubleWordInsert(ArmEmitterContext context, Operand target, Operand value, int targetV)
|
||||
{
|
||||
Debug.Assert(target.Type == OperandType.V128 && value.Type == OperandType.V128);
|
||||
|
||||
int targetSide = targetV & 1;
|
||||
Operand idx = Const(targetSide);
|
||||
|
||||
return context.AddIntrinsic(Intrinsic.Arm64InsVe | Intrinsic.Arm64VDWord, target, idx, value, idx);
|
||||
}
|
||||
|
||||
public static Operand EmitScalarInsert(ArmEmitterContext context, Operand target, Operand value, int reg, bool doubleWidth)
|
||||
{
|
||||
Debug.Assert(target.Type == OperandType.V128 && value.Type == OperandType.V128);
|
||||
|
||||
// Insert from index 0 in value to index in target.
|
||||
int index = reg & (doubleWidth ? 1 : 3);
|
||||
|
||||
if (doubleWidth)
|
||||
{
|
||||
return context.AddIntrinsic(Intrinsic.Arm64InsVe | Intrinsic.Arm64VDWord, target, Const(index), value, Const(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.AddIntrinsic(Intrinsic.Arm64InsVe | Intrinsic.Arm64VWord, target, Const(index), value, Const(0));
|
||||
}
|
||||
}
|
||||
|
||||
public static Operand EmitExtractScalar(ArmEmitterContext context, Operand target, int reg, bool doubleWidth)
|
||||
{
|
||||
int index = reg & (doubleWidth ? 1 : 3);
|
||||
if (index == 0) return target; // Element is already at index 0, so just return the vector directly.
|
||||
|
||||
if (doubleWidth)
|
||||
{
|
||||
return context.AddIntrinsic(Intrinsic.Arm64DupSe | Intrinsic.Arm64VDWord, target, Const(1)); // Extract high (index 1).
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.AddIntrinsic(Intrinsic.Arm64DupSe | Intrinsic.Arm64VWord, target, Const(index)); // Extract element at index.
|
||||
}
|
||||
}
|
||||
|
||||
// Vector Operand Templates
|
||||
|
||||
public static void EmitVectorUnaryOpSimd32(ArmEmitterContext context, Func1I vectorFunc)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
Operand m = GetVecA32(op.Qm);
|
||||
Operand d = GetVecA32(op.Qd);
|
||||
|
||||
if (!op.Q) // Register swap: move relevant doubleword to destination side.
|
||||
{
|
||||
m = EmitMoveDoubleWordToSide(context, m, op.Vm, op.Vd);
|
||||
}
|
||||
|
||||
Operand res = vectorFunc(m);
|
||||
|
||||
if (!op.Q) // Register insert.
|
||||
{
|
||||
res = EmitDoubleWordInsert(context, d, res, op.Vd);
|
||||
}
|
||||
|
||||
context.Copy(d, res);
|
||||
}
|
||||
|
||||
public static void EmitVectorUnaryOpF32(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
inst |= ((op.Size & 1) != 0 ? Intrinsic.Arm64VDouble : Intrinsic.Arm64VFloat) | Intrinsic.Arm64V128;
|
||||
EmitVectorUnaryOpSimd32(context, (m) => context.AddIntrinsic(inst, m));
|
||||
}
|
||||
|
||||
public static void EmitVectorBinaryOpSimd32(ArmEmitterContext context, Func2I vectorFunc, int side = -1)
|
||||
{
|
||||
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
|
||||
|
||||
Operand n = GetVecA32(op.Qn);
|
||||
Operand m = GetVecA32(op.Qm);
|
||||
Operand d = GetVecA32(op.Qd);
|
||||
|
||||
if (side == -1)
|
||||
{
|
||||
side = op.Vd;
|
||||
}
|
||||
|
||||
if (!op.Q) // Register swap: move relevant doubleword to destination side.
|
||||
{
|
||||
n = EmitMoveDoubleWordToSide(context, n, op.Vn, side);
|
||||
m = EmitMoveDoubleWordToSide(context, m, op.Vm, side);
|
||||
}
|
||||
|
||||
Operand res = vectorFunc(n, m);
|
||||
|
||||
if (!op.Q) // Register insert.
|
||||
{
|
||||
if (side != op.Vd)
|
||||
{
|
||||
res = EmitMoveDoubleWordToSide(context, res, side, op.Vd);
|
||||
}
|
||||
res = EmitDoubleWordInsert(context, d, res, op.Vd);
|
||||
}
|
||||
|
||||
context.Copy(d, res);
|
||||
}
|
||||
|
||||
public static void EmitVectorBinaryOpF32(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
|
||||
|
||||
inst |= ((op.Size & 1) != 0 ? Intrinsic.Arm64VDouble : Intrinsic.Arm64VFloat) | Intrinsic.Arm64V128;
|
||||
EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(inst, n, m));
|
||||
}
|
||||
|
||||
public static void EmitVectorTernaryOpSimd32(ArmEmitterContext context, Func3I vectorFunc)
|
||||
{
|
||||
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
|
||||
|
||||
Operand n = GetVecA32(op.Qn);
|
||||
Operand m = GetVecA32(op.Qm);
|
||||
Operand d = GetVecA32(op.Qd);
|
||||
Operand initialD = d;
|
||||
|
||||
if (!op.Q) // Register swap: move relevant doubleword to destination side.
|
||||
{
|
||||
n = EmitMoveDoubleWordToSide(context, n, op.Vn, op.Vd);
|
||||
m = EmitMoveDoubleWordToSide(context, m, op.Vm, op.Vd);
|
||||
}
|
||||
|
||||
Operand res = vectorFunc(d, n, m);
|
||||
|
||||
if (!op.Q) // Register insert.
|
||||
{
|
||||
res = EmitDoubleWordInsert(context, initialD, res, op.Vd);
|
||||
}
|
||||
|
||||
context.Copy(initialD, res);
|
||||
}
|
||||
|
||||
public static void EmitVectorTernaryOpF32(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
|
||||
|
||||
inst |= ((op.Size & 1) != 0 ? Intrinsic.Arm64VDouble : Intrinsic.Arm64VFloat) | Intrinsic.Arm64V128;
|
||||
EmitVectorTernaryOpSimd32(context, (d, n, m) => context.AddIntrinsic(inst, d, n, m));
|
||||
}
|
||||
|
||||
public static void EmitScalarUnaryOpSimd32(ArmEmitterContext context, Func1I scalarFunc)
|
||||
{
|
||||
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
|
||||
|
||||
bool doubleSize = (op.Size & 1) != 0;
|
||||
int shift = doubleSize ? 1 : 2;
|
||||
Operand m = GetVecA32(op.Vm >> shift);
|
||||
Operand d = GetVecA32(op.Vd >> shift);
|
||||
|
||||
m = EmitExtractScalar(context, m, op.Vm, doubleSize);
|
||||
|
||||
Operand res = scalarFunc(m);
|
||||
|
||||
// Insert scalar into vector.
|
||||
res = EmitScalarInsert(context, d, res, op.Vd, doubleSize);
|
||||
|
||||
context.Copy(d, res);
|
||||
}
|
||||
|
||||
public static void EmitScalarUnaryOpF32(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
|
||||
|
||||
inst |= ((op.Size & 1) != 0 ? Intrinsic.Arm64VDouble : Intrinsic.Arm64VFloat) | Intrinsic.Arm64V128;
|
||||
EmitScalarUnaryOpSimd32(context, (m) => (inst == 0) ? m : context.AddIntrinsic(inst, m));
|
||||
}
|
||||
|
||||
public static void EmitScalarBinaryOpSimd32(ArmEmitterContext context, Func2I scalarFunc)
|
||||
{
|
||||
OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;
|
||||
|
||||
bool doubleSize = (op.Size & 1) != 0;
|
||||
int shift = doubleSize ? 1 : 2;
|
||||
Operand n = GetVecA32(op.Vn >> shift);
|
||||
Operand m = GetVecA32(op.Vm >> shift);
|
||||
Operand d = GetVecA32(op.Vd >> shift);
|
||||
|
||||
n = EmitExtractScalar(context, n, op.Vn, doubleSize);
|
||||
m = EmitExtractScalar(context, m, op.Vm, doubleSize);
|
||||
|
||||
Operand res = scalarFunc(n, m);
|
||||
|
||||
// Insert scalar into vector.
|
||||
res = EmitScalarInsert(context, d, res, op.Vd, doubleSize);
|
||||
|
||||
context.Copy(d, res);
|
||||
}
|
||||
|
||||
public static void EmitScalarBinaryOpF32(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;
|
||||
|
||||
inst |= ((op.Size & 1) != 0 ? Intrinsic.Arm64VDouble : Intrinsic.Arm64VFloat) | Intrinsic.Arm64V128;
|
||||
EmitScalarBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(inst, n, m));
|
||||
}
|
||||
|
||||
public static void EmitScalarTernaryOpSimd32(ArmEmitterContext context, Func3I scalarFunc)
|
||||
{
|
||||
OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;
|
||||
|
||||
bool doubleSize = (op.Size & 1) != 0;
|
||||
int shift = doubleSize ? 1 : 2;
|
||||
Operand n = GetVecA32(op.Vn >> shift);
|
||||
Operand m = GetVecA32(op.Vm >> shift);
|
||||
Operand d = GetVecA32(op.Vd >> shift);
|
||||
Operand initialD = d;
|
||||
|
||||
n = EmitExtractScalar(context, n, op.Vn, doubleSize);
|
||||
m = EmitExtractScalar(context, m, op.Vm, doubleSize);
|
||||
d = EmitExtractScalar(context, d, op.Vd, doubleSize);
|
||||
|
||||
Operand res = scalarFunc(d, n, m);
|
||||
|
||||
// Insert scalar into vector.
|
||||
res = EmitScalarInsert(context, initialD, res, op.Vd, doubleSize);
|
||||
|
||||
context.Copy(initialD, res);
|
||||
}
|
||||
|
||||
public static void EmitScalarTernaryOpF32(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;
|
||||
|
||||
inst |= ((op.Size & 1) != 0 ? Intrinsic.Arm64VDouble : Intrinsic.Arm64VFloat) | Intrinsic.Arm64V128;
|
||||
EmitScalarTernaryOpSimd32(context, (d, n, m) => context.AddIntrinsic(inst, d, n, m));
|
||||
}
|
||||
|
||||
// Pairwise
|
||||
|
||||
public static void EmitVectorPairwiseOpF32(ArmEmitterContext context, Intrinsic inst32)
|
||||
{
|
||||
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
|
||||
|
||||
inst32 |= Intrinsic.Arm64V64 | Intrinsic.Arm64VFloat;
|
||||
EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(inst32, n, m), 0);
|
||||
}
|
||||
|
||||
public static void EmitVcmpOrVcmpe(ArmEmitterContext context, bool signalNaNs)
|
||||
{
|
||||
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
|
||||
|
||||
bool cmpWithZero = (op.Opc & 2) != 0;
|
||||
|
||||
Intrinsic inst = signalNaNs ? Intrinsic.Arm64FcmpeS : Intrinsic.Arm64FcmpS;
|
||||
inst |= ((op.Size & 1) != 0 ? Intrinsic.Arm64VDouble : Intrinsic.Arm64VFloat) | Intrinsic.Arm64V128;
|
||||
|
||||
bool doubleSize = (op.Size & 1) != 0;
|
||||
int shift = doubleSize ? 1 : 2;
|
||||
Operand n = GetVecA32(op.Vd >> shift);
|
||||
Operand m = GetVecA32(op.Vm >> shift);
|
||||
|
||||
n = EmitExtractScalar(context, n, op.Vd, doubleSize);
|
||||
m = cmpWithZero ? Const(0) : EmitExtractScalar(context, m, op.Vm, doubleSize);
|
||||
|
||||
Operand nzcv = context.AddIntrinsicInt(inst, n, m);
|
||||
|
||||
Operand one = Const(1);
|
||||
|
||||
SetFpFlag(context, FPState.VFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(28)), one));
|
||||
SetFpFlag(context, FPState.CFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(29)), one));
|
||||
SetFpFlag(context, FPState.ZFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(30)), one));
|
||||
SetFpFlag(context, FPState.NFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(31)), one));
|
||||
}
|
||||
|
||||
public static void EmitCmpOpF32(ArmEmitterContext context, CmpCondition cond, bool zero)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
int sizeF = op.Size & 1;
|
||||
|
||||
Intrinsic inst;
|
||||
if (zero)
|
||||
{
|
||||
inst = cond switch
|
||||
{
|
||||
CmpCondition.Equal => Intrinsic.Arm64FcmeqVz,
|
||||
CmpCondition.GreaterThan => Intrinsic.Arm64FcmgtVz,
|
||||
CmpCondition.GreaterThanOrEqual => Intrinsic.Arm64FcmgeVz,
|
||||
CmpCondition.LessThan => Intrinsic.Arm64FcmltVz,
|
||||
CmpCondition.LessThanOrEqual => Intrinsic.Arm64FcmleVz,
|
||||
_ => throw new InvalidOperationException()
|
||||
};
|
||||
}
|
||||
else {
|
||||
inst = cond switch
|
||||
{
|
||||
CmpCondition.Equal => Intrinsic.Arm64FcmeqV,
|
||||
CmpCondition.GreaterThan => Intrinsic.Arm64FcmgtV,
|
||||
CmpCondition.GreaterThanOrEqual => Intrinsic.Arm64FcmgeV,
|
||||
_ => throw new InvalidOperationException()
|
||||
};
|
||||
}
|
||||
|
||||
inst |= (sizeF != 0 ? Intrinsic.Arm64VDouble : Intrinsic.Arm64VFloat) | Intrinsic.Arm64V128;
|
||||
|
||||
if (zero)
|
||||
{
|
||||
EmitVectorUnaryOpSimd32(context, (m) =>
|
||||
{
|
||||
return context.AddIntrinsic(inst, m);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitVectorBinaryOpSimd32(context, (n, m) =>
|
||||
{
|
||||
return context.AddIntrinsic(inst, n, m);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
720
ARMeilleure/Instructions/InstEmitSimdHelperArm64.cs
Normal file
720
ARMeilleure/Instructions/InstEmitSimdHelperArm64.cs
Normal file
@ -0,0 +1,720 @@
|
||||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
static class InstEmitSimdHelperArm64
|
||||
{
|
||||
public static void EmitScalarUnaryOpF(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n));
|
||||
}
|
||||
|
||||
public static void EmitScalarUnaryOpFFromGp(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n));
|
||||
}
|
||||
|
||||
public static void EmitScalarUnaryOpFToGp(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
SetIntOrZR(context, op.Rd, op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (inst, n)
|
||||
: context.AddIntrinsicLong(inst, n));
|
||||
}
|
||||
|
||||
public static void EmitScalarBinaryOpF(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m));
|
||||
}
|
||||
|
||||
public static void EmitScalarBinaryOpFByElem(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m, Const(op.Index)));
|
||||
}
|
||||
|
||||
public static void EmitScalarTernaryOpF(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
Operand a = GetVec(op.Ra);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, a, n, m));
|
||||
}
|
||||
|
||||
public static void EmitScalarTernaryOpFRdByElem(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
context.Copy(d, context.AddIntrinsic(inst, d, n, m, Const(op.Index)));
|
||||
}
|
||||
|
||||
public static void EmitScalarUnaryOp(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n));
|
||||
}
|
||||
|
||||
public static void EmitScalarBinaryOp(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m));
|
||||
}
|
||||
|
||||
public static void EmitScalarBinaryOpRd(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n));
|
||||
}
|
||||
|
||||
public static void EmitScalarTernaryOpRd(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
context.Copy(d, context.AddIntrinsic(inst, d, n, m));
|
||||
}
|
||||
|
||||
public static void EmitScalarShiftBinaryOp(ArmEmitterContext context, Intrinsic inst, int shift)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, Const(shift)));
|
||||
}
|
||||
|
||||
public static void EmitScalarShiftTernaryOpRd(ArmEmitterContext context, Intrinsic inst, int shift)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n, Const(shift)));
|
||||
}
|
||||
|
||||
public static void EmitScalarSaturatingShiftTernaryOpRd(ArmEmitterContext context, Intrinsic inst, int shift)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n, Const(shift)));
|
||||
|
||||
context.SetPendingQcFlagSync();
|
||||
}
|
||||
|
||||
public static void EmitScalarSaturatingUnaryOp(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
Operand result = context.AddIntrinsic(inst, n);
|
||||
|
||||
context.Copy(GetVec(op.Rd), result);
|
||||
|
||||
context.SetPendingQcFlagSync();
|
||||
}
|
||||
|
||||
public static void EmitScalarSaturatingBinaryOp(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
Operand result = context.AddIntrinsic(inst, n, m);
|
||||
|
||||
context.Copy(GetVec(op.Rd), result);
|
||||
|
||||
context.SetPendingQcFlagSync();
|
||||
}
|
||||
|
||||
public static void EmitScalarSaturatingBinaryOpRd(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
Operand result = context.AddIntrinsic(inst, d, n);
|
||||
|
||||
context.Copy(GetVec(op.Rd), result);
|
||||
|
||||
context.SetPendingQcFlagSync();
|
||||
}
|
||||
|
||||
public static void EmitScalarConvertBinaryOpF(ArmEmitterContext context, Intrinsic inst, int fBits)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, Const(fBits)));
|
||||
}
|
||||
|
||||
public static void EmitScalarConvertBinaryOpFFromGp(ArmEmitterContext context, Intrinsic inst, int fBits)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, Const(fBits)));
|
||||
}
|
||||
|
||||
public static void EmitScalarConvertBinaryOpFToGp(ArmEmitterContext context, Intrinsic inst, int fBits)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
SetIntOrZR(context, op.Rd, op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (inst, n, Const(fBits))
|
||||
: context.AddIntrinsicLong(inst, n, Const(fBits)));
|
||||
}
|
||||
|
||||
public static void EmitVectorUnaryOpF(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n));
|
||||
}
|
||||
|
||||
public static void EmitVectorBinaryOpF(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m));
|
||||
}
|
||||
|
||||
public static void EmitVectorBinaryOpFRd(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n));
|
||||
}
|
||||
|
||||
public static void EmitVectorBinaryOpFByElem(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m, Const(op.Index)));
|
||||
}
|
||||
|
||||
public static void EmitVectorTernaryOpFRd(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(d, context.AddIntrinsic(inst, d, n, m));
|
||||
}
|
||||
|
||||
public static void EmitVectorTernaryOpFRdByElem(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(d, context.AddIntrinsic(inst, d, n, m, Const(op.Index)));
|
||||
}
|
||||
|
||||
public static void EmitVectorUnaryOp(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n));
|
||||
}
|
||||
|
||||
public static void EmitVectorBinaryOp(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m));
|
||||
}
|
||||
|
||||
public static void EmitVectorBinaryOpRd(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n));
|
||||
}
|
||||
|
||||
public static void EmitVectorBinaryOpByElem(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m, Const(op.Index)));
|
||||
}
|
||||
|
||||
public static void EmitVectorTernaryOpRd(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(d, context.AddIntrinsic(inst, d, n, m));
|
||||
}
|
||||
|
||||
public static void EmitVectorTernaryOpRdByElem(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(d, context.AddIntrinsic(inst, d, n, m, Const(op.Index)));
|
||||
}
|
||||
|
||||
public static void EmitVectorShiftBinaryOp(ArmEmitterContext context, Intrinsic inst, int shift)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, Const(shift)));
|
||||
}
|
||||
|
||||
public static void EmitVectorShiftTernaryOpRd(ArmEmitterContext context, Intrinsic inst, int shift)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n, Const(shift)));
|
||||
}
|
||||
|
||||
public static void EmitVectorSaturatingShiftTernaryOpRd(ArmEmitterContext context, Intrinsic inst, int shift)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n, Const(shift)));
|
||||
|
||||
context.SetPendingQcFlagSync();
|
||||
}
|
||||
|
||||
public static void EmitVectorSaturatingUnaryOp(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
Operand result = context.AddIntrinsic(inst, n);
|
||||
|
||||
context.Copy(GetVec(op.Rd), result);
|
||||
|
||||
context.SetPendingQcFlagSync();
|
||||
}
|
||||
|
||||
public static void EmitVectorSaturatingBinaryOp(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
Operand result = context.AddIntrinsic(inst, n, m);
|
||||
|
||||
context.Copy(GetVec(op.Rd), result);
|
||||
|
||||
context.SetPendingQcFlagSync();
|
||||
}
|
||||
|
||||
public static void EmitVectorSaturatingBinaryOpRd(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
Operand result = context.AddIntrinsic(inst, d, n);
|
||||
|
||||
context.Copy(GetVec(op.Rd), result);
|
||||
|
||||
context.SetPendingQcFlagSync();
|
||||
}
|
||||
|
||||
public static void EmitVectorSaturatingBinaryOpByElem(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
Operand result = context.AddIntrinsic(inst, n, m, Const(op.Index));
|
||||
|
||||
context.Copy(GetVec(op.Rd), result);
|
||||
|
||||
context.SetPendingQcFlagSync();
|
||||
}
|
||||
|
||||
public static void EmitVectorConvertBinaryOpF(ArmEmitterContext context, Intrinsic inst, int fBits)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, Const(fBits)));
|
||||
}
|
||||
|
||||
public static void EmitVectorLookupTable(ArmEmitterContext context, Intrinsic inst)
|
||||
{
|
||||
OpCodeSimdTbl op = (OpCodeSimdTbl)context.CurrOp;
|
||||
|
||||
Operand[] operands = new Operand[op.Size + 1];
|
||||
|
||||
operands[op.Size] = GetVec(op.Rm);
|
||||
|
||||
for (int index = 0; index < op.Size; index++)
|
||||
{
|
||||
operands[index] = GetVec((op.Rn + index) & 0x1F);
|
||||
}
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
inst |= Intrinsic.Arm64V128;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, operands));
|
||||
}
|
||||
|
||||
public static void EmitFcmpOrFcmpe(ArmEmitterContext context, bool signalNaNs)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
bool cmpWithZero = !(op is OpCodeSimdFcond) ? op.Bit3 : false;
|
||||
|
||||
Intrinsic inst = signalNaNs ? Intrinsic.Arm64FcmpeS : Intrinsic.Arm64FcmpS;
|
||||
|
||||
if ((op.Size & 1) != 0)
|
||||
{
|
||||
inst |= Intrinsic.Arm64VDouble;
|
||||
}
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = cmpWithZero ? Const(0) : GetVec(op.Rm);
|
||||
|
||||
Operand nzcv = context.AddIntrinsicInt(inst, n, m);
|
||||
|
||||
Operand one = Const(1);
|
||||
|
||||
SetFlag(context, PState.VFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(28)), one));
|
||||
SetFlag(context, PState.CFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(29)), one));
|
||||
SetFlag(context, PState.ZFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(30)), one));
|
||||
SetFlag(context, PState.NFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(31)), one));
|
||||
}
|
||||
}
|
||||
}
|
@ -14,7 +14,11 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
public static void And_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorBinaryOp(context, Intrinsic.Arm64AndV);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
@ -38,7 +42,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Bic_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorBinaryOp(context, Intrinsic.Arm64BicV);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
@ -98,12 +106,26 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Bif_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitBifBit(context, notRm: true);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorTernaryOpRd(context, Intrinsic.Arm64BifV);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitBifBit(context, notRm: true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Bit_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitBifBit(context, notRm: false);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorTernaryOpRd(context, Intrinsic.Arm64BitV);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitBifBit(context, notRm: false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitBifBit(ArmEmitterContext context, bool notRm)
|
||||
@ -167,7 +189,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Bsl_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorTernaryOpRd(context, Intrinsic.Arm64BslV);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
@ -200,7 +226,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Eor_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorBinaryOp(context, Intrinsic.Arm64EorV);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
@ -249,7 +279,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Orn_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorBinaryOp(context, Intrinsic.Arm64OrnV);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
@ -280,7 +314,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Orr_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorBinaryOp(context, Intrinsic.Arm64OrrV);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
|
@ -13,7 +13,11 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
public static void Vand_I(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(Intrinsic.Arm64AndV | Intrinsic.Arm64V128, n, m));
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(Intrinsic.X86Pand, n, m));
|
||||
}
|
||||
@ -25,7 +29,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vbic_I(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(Intrinsic.Arm64BicV | Intrinsic.Arm64V128, n, m));
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(Intrinsic.X86Pandn, m, n));
|
||||
}
|
||||
@ -73,17 +81,35 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vbif(ArmEmitterContext context)
|
||||
{
|
||||
EmitBifBit(context, true);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorTernaryOpSimd32(context, (d, n, m) => context.AddIntrinsic(Intrinsic.Arm64BifV | Intrinsic.Arm64V128, d, n, m));
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitBifBit(context, true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Vbit(ArmEmitterContext context)
|
||||
{
|
||||
EmitBifBit(context, false);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorTernaryOpSimd32(context, (d, n, m) => context.AddIntrinsic(Intrinsic.Arm64BitV | Intrinsic.Arm64V128, d, n, m));
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitBifBit(context, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Vbsl(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorTernaryOpSimd32(context, (d, n, m) => context.AddIntrinsic(Intrinsic.Arm64BslV | Intrinsic.Arm64V128, d, n, m));
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorTernaryOpSimd32(context, (d, n, m) =>
|
||||
{
|
||||
@ -105,7 +131,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Veor_I(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(Intrinsic.Arm64EorV | Intrinsic.Arm64V128, n, m));
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(Intrinsic.X86Pxor, n, m));
|
||||
}
|
||||
@ -117,7 +147,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vorn_I(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(Intrinsic.Arm64OrnV | Intrinsic.Arm64V128, n, m));
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
Operand mask = context.VectorOne();
|
||||
|
||||
@ -135,7 +169,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Vorr_I(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(Intrinsic.Arm64OrrV | Intrinsic.Arm64V128, n, m));
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(Intrinsic.X86Por, n, m));
|
||||
}
|
||||
|
@ -392,7 +392,11 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCode32SimdCmpZ op = (OpCode32SimdCmpZ)context.CurrOp;
|
||||
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
EmitVectorZipUzpOpSimd32(context, Intrinsic.Arm64Zip1V, Intrinsic.Arm64Zip2V);
|
||||
}
|
||||
else if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitVectorShuffleOpSimd32(context, (m, d) =>
|
||||
{
|
||||
@ -461,7 +465,11 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCode32SimdCmpZ op = (OpCode32SimdCmpZ)context.CurrOp;
|
||||
|
||||
if (Optimizations.UseSsse3)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
EmitVectorZipUzpOpSimd32(context, Intrinsic.Arm64Uzp1V, Intrinsic.Arm64Uzp2V);
|
||||
}
|
||||
else if (Optimizations.UseSsse3)
|
||||
{
|
||||
EmitVectorShuffleOpSimd32(context, (m, d) =>
|
||||
{
|
||||
@ -559,6 +567,52 @@ namespace ARMeilleure.Instructions
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitVectorZipUzpOpSimd32(ArmEmitterContext context, Intrinsic inst1, Intrinsic inst2)
|
||||
{
|
||||
OpCode32SimdCmpZ op = (OpCode32SimdCmpZ)context.CurrOp;
|
||||
|
||||
bool overlap = op.Qm == op.Qd;
|
||||
|
||||
Operand d = GetVecA32(op.Qd);
|
||||
Operand m = GetVecA32(op.Qm);
|
||||
|
||||
Operand dPart = d;
|
||||
Operand mPart = m;
|
||||
|
||||
if (!op.Q) // Register swap: move relevant doubleword to destination side.
|
||||
{
|
||||
dPart = InstEmitSimdHelper32Arm64.EmitMoveDoubleWordToSide(context, d, op.Vd, 0);
|
||||
mPart = InstEmitSimdHelper32Arm64.EmitMoveDoubleWordToSide(context, m, op.Vm, 0);
|
||||
}
|
||||
|
||||
Intrinsic vSize = op.Q ? Intrinsic.Arm64V128 : Intrinsic.Arm64V64;
|
||||
|
||||
vSize |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
|
||||
|
||||
Operand resD = context.AddIntrinsic(inst1 | vSize, dPart, mPart);
|
||||
Operand resM = context.AddIntrinsic(inst2 | vSize, dPart, mPart);
|
||||
|
||||
if (!op.Q) // Register insert.
|
||||
{
|
||||
resD = context.AddIntrinsic(Intrinsic.Arm64InsVe | Intrinsic.Arm64VDWord, d, Const(op.Vd & 1), resD, Const(0));
|
||||
|
||||
if (overlap)
|
||||
{
|
||||
resD = context.AddIntrinsic(Intrinsic.Arm64InsVe | Intrinsic.Arm64VDWord, resD, Const(op.Vm & 1), resM, Const(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
resM = context.AddIntrinsic(Intrinsic.Arm64InsVe | Intrinsic.Arm64VDWord, m, Const(op.Vm & 1), resM, Const(0));
|
||||
}
|
||||
}
|
||||
|
||||
context.Copy(d, resD);
|
||||
if (!overlap)
|
||||
{
|
||||
context.Copy(m, resM);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitVectorShuffleOpSimd32(ArmEmitterContext context, Func<Operand, Operand, (Operand, Operand)> shuffleFunc)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
@ -26,7 +26,15 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Rshrn_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSsse3)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorShiftTernaryOpRd(context, Intrinsic.Arm64RshrnV, shift);
|
||||
}
|
||||
else if (Optimizations.UseSsse3)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
@ -80,7 +88,14 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
int shift = GetImmShl(op);
|
||||
|
||||
EmitScalarUnaryOpZx(context, (op1) => context.ShiftLeft(op1, Const(shift)));
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarShiftBinaryOp(context, Intrinsic.Arm64ShlS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarUnaryOpZx(context, (op1) => context.ShiftLeft(op1, Const(shift)));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Shl_V(ArmEmitterContext context)
|
||||
@ -90,7 +105,11 @@ namespace ARMeilleure.Instructions
|
||||
int shift = GetImmShl(op);
|
||||
int eSize = 8 << op.Size;
|
||||
|
||||
if (shift >= eSize)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorShiftBinaryOp(context, Intrinsic.Arm64ShlV, shift);
|
||||
}
|
||||
else if (shift >= eSize)
|
||||
{
|
||||
if ((op.RegisterSize == RegisterSize.Simd64))
|
||||
{
|
||||
@ -143,7 +162,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
int shift = 8 << op.Size;
|
||||
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorUnaryOp(context, Intrinsic.Arm64ShllV);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
@ -170,7 +193,15 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Shrn_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSsse3)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorShiftTernaryOpRd(context, Intrinsic.Arm64ShrnV, shift);
|
||||
}
|
||||
else if (Optimizations.UseSsse3)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
@ -205,89 +236,259 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Sli_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitSli(context, scalar: true);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShl(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarShiftTernaryOpRd(context, Intrinsic.Arm64SliS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitSli(context, scalar: true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sli_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitSli(context, scalar: false);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShl(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorShiftTernaryOpRd(context, Intrinsic.Arm64SliV, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitSli(context, scalar: false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sqrshl_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Round | ShlRegFlags.Saturating);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorSaturatingBinaryOp(context, Intrinsic.Arm64SqrshlV);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Round | ShlRegFlags.Saturating);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sqrshrn_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxSx);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarSaturatingShiftTernaryOpRd(context, Intrinsic.Arm64SqrshrnS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxSx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sqrshrn_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxSx);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorSaturatingShiftTernaryOpRd(context, Intrinsic.Arm64SqrshrnV, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxSx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sqrshrun_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxZx);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarSaturatingShiftTernaryOpRd(context, Intrinsic.Arm64SqrshrunS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxZx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sqrshrun_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxZx);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorSaturatingShiftTernaryOpRd(context, Intrinsic.Arm64SqrshrunV, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxZx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sqshl_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Saturating);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorSaturatingBinaryOp(context, Intrinsic.Arm64SqshlV);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Saturating);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sqshrn_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxSx);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarSaturatingShiftTernaryOpRd(context, Intrinsic.Arm64SqshrnS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxSx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sqshrn_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxSx);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorSaturatingShiftTernaryOpRd(context, Intrinsic.Arm64SqshrnV, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxSx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sqshrun_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxZx);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarSaturatingShiftTernaryOpRd(context, Intrinsic.Arm64SqshrunS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxZx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sqshrun_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxZx);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorSaturatingShiftTernaryOpRd(context, Intrinsic.Arm64SqshrunV, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxZx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sri_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitSri(context, scalar: true);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarShiftTernaryOpRd(context, Intrinsic.Arm64SriS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitSri(context, scalar: true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sri_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitSri(context, scalar: false);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorShiftTernaryOpRd(context, Intrinsic.Arm64SriV, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitSri(context, scalar: false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Srshl_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Round);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorBinaryOp(context, Intrinsic.Arm64SrshlV);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Round);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Srshr_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitScalarShrImmOpSx(context, ShrImmFlags.Round);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarShiftBinaryOp(context, Intrinsic.Arm64SrshrS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarShrImmOpSx(context, ShrImmFlags.Round);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Srshr_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
if (Optimizations.UseSse2 && op.Size > 0 && op.Size < 3)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorShiftBinaryOp(context, Intrinsic.Arm64SrshrV, shift);
|
||||
}
|
||||
else if (Optimizations.UseSse2 && op.Size > 0 && op.Size < 3)
|
||||
{
|
||||
int shift = GetImmShr(op);
|
||||
int eSize = 8 << op.Size;
|
||||
@ -325,14 +526,31 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Srsra_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitScalarShrImmOpSx(context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarShiftTernaryOpRd(context, Intrinsic.Arm64SrsraS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarShrImmOpSx(context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Srsra_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
if (Optimizations.UseSse2 && op.Size > 0 && op.Size < 3)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorShiftTernaryOpRd(context, Intrinsic.Arm64SrsraV, shift);
|
||||
}
|
||||
else if (Optimizations.UseSse2 && op.Size > 0 && op.Size < 3)
|
||||
{
|
||||
int shift = GetImmShr(op);
|
||||
int eSize = 8 << op.Size;
|
||||
@ -372,12 +590,26 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Sshl_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Scalar | ShlRegFlags.Signed);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarBinaryOp(context, Intrinsic.Arm64SshlS);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Scalar | ShlRegFlags.Signed);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sshl_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Signed);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorBinaryOp(context, Intrinsic.Arm64SshlV);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Signed);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sshll_V(ArmEmitterContext context)
|
||||
@ -386,7 +618,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
int shift = GetImmShl(op);
|
||||
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorShiftBinaryOp(context, Intrinsic.Arm64SshllV, shift);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
@ -416,7 +652,18 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Sshr_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitShrImmOp(context, ShrImmFlags.ScalarSx);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarShiftBinaryOp(context, Intrinsic.Arm64SshrS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShrImmOp(context, ShrImmFlags.ScalarSx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sshr_V(ArmEmitterContext context)
|
||||
@ -425,7 +672,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
if (Optimizations.UseGfni && op.Size == 0)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorShiftBinaryOp(context, Intrinsic.Arm64SshrV, shift);
|
||||
}
|
||||
else if (Optimizations.UseGfni && op.Size == 0)
|
||||
{
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
@ -478,14 +729,31 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Ssra_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitScalarShrImmOpSx(context, ShrImmFlags.Accumulate);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarShiftTernaryOpRd(context, Intrinsic.Arm64SsraS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarShrImmOpSx(context, ShrImmFlags.Accumulate);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Ssra_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
if (Optimizations.UseSse2 && op.Size > 0 && op.Size < 3)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorShiftTernaryOpRd(context, Intrinsic.Arm64SsraV, shift);
|
||||
}
|
||||
else if (Optimizations.UseSse2 && op.Size > 0 && op.Size < 3)
|
||||
{
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
@ -515,49 +783,131 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Uqrshl_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Round | ShlRegFlags.Saturating);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorSaturatingBinaryOp(context, Intrinsic.Arm64UqrshlV);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Round | ShlRegFlags.Saturating);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Uqrshrn_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarZxZx);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarSaturatingShiftTernaryOpRd(context, Intrinsic.Arm64UqrshrnS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarZxZx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Uqrshrn_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorZxZx);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorSaturatingShiftTernaryOpRd(context, Intrinsic.Arm64UqrshrnV, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorZxZx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Uqshl_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Saturating);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorSaturatingBinaryOp(context, Intrinsic.Arm64UqshlV);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Saturating);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Uqshrn_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarZxZx);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarSaturatingShiftTernaryOpRd(context, Intrinsic.Arm64UqshrnS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarZxZx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Uqshrn_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorZxZx);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorSaturatingShiftTernaryOpRd(context, Intrinsic.Arm64UqshrnV, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorZxZx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Urshl_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Round);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorBinaryOp(context, Intrinsic.Arm64UrshlV);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Round);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Urshr_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitScalarShrImmOpZx(context, ShrImmFlags.Round);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarShiftBinaryOp(context, Intrinsic.Arm64UrshrS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarShrImmOpZx(context, ShrImmFlags.Round);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Urshr_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
if (Optimizations.UseSse2 && op.Size > 0)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorShiftBinaryOp(context, Intrinsic.Arm64UrshrV, shift);
|
||||
}
|
||||
else if (Optimizations.UseSse2 && op.Size > 0)
|
||||
{
|
||||
int shift = GetImmShr(op);
|
||||
int eSize = 8 << op.Size;
|
||||
@ -593,14 +943,31 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Ursra_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitScalarShrImmOpZx(context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarShiftTernaryOpRd(context, Intrinsic.Arm64UrsraS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarShrImmOpZx(context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Ursra_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
if (Optimizations.UseSse2 && op.Size > 0)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorShiftTernaryOpRd(context, Intrinsic.Arm64UrsraV, shift);
|
||||
}
|
||||
else if (Optimizations.UseSse2 && op.Size > 0)
|
||||
{
|
||||
int shift = GetImmShr(op);
|
||||
int eSize = 8 << op.Size;
|
||||
@ -638,12 +1005,26 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Ushl_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Scalar);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitScalarBinaryOp(context, Intrinsic.Arm64UshlS);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.Scalar);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Ushl_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.None);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorBinaryOp(context, Intrinsic.Arm64UshlV);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShlRegOp(context, ShlRegFlags.None);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Ushll_V(ArmEmitterContext context)
|
||||
@ -652,7 +1033,11 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
int shift = GetImmShl(op);
|
||||
|
||||
if (Optimizations.UseSse41)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelperArm64.EmitVectorShiftBinaryOp(context, Intrinsic.Arm64UshllV, shift);
|
||||
}
|
||||
else if (Optimizations.UseSse41)
|
||||
{
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
@ -682,14 +1067,31 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Ushr_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitShrImmOp(context, ShrImmFlags.ScalarZx);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarShiftBinaryOp(context, Intrinsic.Arm64UshrS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitShrImmOp(context, ShrImmFlags.ScalarZx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Ushr_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
if (Optimizations.UseSse2 && op.Size > 0)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorShiftBinaryOp(context, Intrinsic.Arm64UshrV, shift);
|
||||
}
|
||||
else if (Optimizations.UseSse2 && op.Size > 0)
|
||||
{
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
@ -714,14 +1116,31 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void Usra_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitScalarShrImmOpZx(context, ShrImmFlags.Accumulate);
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitScalarShiftTernaryOpRd(context, Intrinsic.Arm64UsraS, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarShrImmOpZx(context, ShrImmFlags.Accumulate);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Usra_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
if (Optimizations.UseSse2 && op.Size > 0)
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
InstEmitSimdHelperArm64.EmitVectorShiftTernaryOpRd(context, Intrinsic.Arm64UsraV, shift);
|
||||
}
|
||||
else if (Optimizations.UseSse2 && op.Size > 0)
|
||||
{
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
|
@ -150,6 +150,8 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
context.SyncQcFlag();
|
||||
|
||||
Operand fpsr = Const(0);
|
||||
|
||||
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||
@ -196,6 +198,8 @@ namespace ARMeilleure.Instructions
|
||||
{
|
||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
context.ClearQcFlagIfModified();
|
||||
|
||||
Operand fpsr = GetIntOrZR(context, op.Rt);
|
||||
fpsr = context.ConvertI64ToI32(fpsr);
|
||||
|
||||
|
@ -48,10 +48,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
|
||||
public void AddSuccessor(BasicBlock block)
|
||||
{
|
||||
if (block == null)
|
||||
{
|
||||
ThrowNull(nameof(block));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(block);
|
||||
|
||||
if ((uint)_succCount + 1 > MaxSuccessors)
|
||||
{
|
||||
@ -100,10 +97,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
|
||||
public void SetSuccessor(int index, BasicBlock block)
|
||||
{
|
||||
if (block == null)
|
||||
{
|
||||
ThrowNull(nameof(block));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(block);
|
||||
|
||||
if ((uint)index >= (uint)_succCount)
|
||||
{
|
||||
@ -144,7 +138,6 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
}
|
||||
}
|
||||
|
||||
private static void ThrowNull(string name) => throw new ArgumentNullException(name);
|
||||
private static void ThrowOutOfRange(string name) => throw new ArgumentOutOfRangeException(name);
|
||||
private static void ThrowSuccessorOverflow() => throw new OverflowException($"BasicBlock can only have {MaxSuccessors} successors.");
|
||||
|
||||
|
@ -2,6 +2,8 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
{
|
||||
enum Intrinsic : ushort
|
||||
{
|
||||
// X86 (SSE and AVX)
|
||||
|
||||
X86Addpd,
|
||||
X86Addps,
|
||||
X86Addsd,
|
||||
@ -172,6 +174,458 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
X86Vfnmsub231sd,
|
||||
X86Vfnmsub231ss,
|
||||
X86Xorpd,
|
||||
X86Xorps
|
||||
X86Xorps,
|
||||
|
||||
// Arm64 (FP and Advanced SIMD)
|
||||
|
||||
Arm64AbsS,
|
||||
Arm64AbsV,
|
||||
Arm64AddhnV,
|
||||
Arm64AddpS,
|
||||
Arm64AddpV,
|
||||
Arm64AddvV,
|
||||
Arm64AddS,
|
||||
Arm64AddV,
|
||||
Arm64AesdV,
|
||||
Arm64AeseV,
|
||||
Arm64AesimcV,
|
||||
Arm64AesmcV,
|
||||
Arm64AndV,
|
||||
Arm64BicVi,
|
||||
Arm64BicV,
|
||||
Arm64BifV,
|
||||
Arm64BitV,
|
||||
Arm64BslV,
|
||||
Arm64ClsV,
|
||||
Arm64ClzV,
|
||||
Arm64CmeqS,
|
||||
Arm64CmeqV,
|
||||
Arm64CmeqSz,
|
||||
Arm64CmeqVz,
|
||||
Arm64CmgeS,
|
||||
Arm64CmgeV,
|
||||
Arm64CmgeSz,
|
||||
Arm64CmgeVz,
|
||||
Arm64CmgtS,
|
||||
Arm64CmgtV,
|
||||
Arm64CmgtSz,
|
||||
Arm64CmgtVz,
|
||||
Arm64CmhiS,
|
||||
Arm64CmhiV,
|
||||
Arm64CmhsS,
|
||||
Arm64CmhsV,
|
||||
Arm64CmleSz,
|
||||
Arm64CmleVz,
|
||||
Arm64CmltSz,
|
||||
Arm64CmltVz,
|
||||
Arm64CmtstS,
|
||||
Arm64CmtstV,
|
||||
Arm64CntV,
|
||||
Arm64DupSe,
|
||||
Arm64DupVe,
|
||||
Arm64DupGp,
|
||||
Arm64EorV,
|
||||
Arm64ExtV,
|
||||
Arm64FabdS,
|
||||
Arm64FabdV,
|
||||
Arm64FabsV,
|
||||
Arm64FabsS,
|
||||
Arm64FacgeS,
|
||||
Arm64FacgeV,
|
||||
Arm64FacgtS,
|
||||
Arm64FacgtV,
|
||||
Arm64FaddpS,
|
||||
Arm64FaddpV,
|
||||
Arm64FaddV,
|
||||
Arm64FaddS,
|
||||
Arm64FccmpeS,
|
||||
Arm64FccmpS,
|
||||
Arm64FcmeqS,
|
||||
Arm64FcmeqV,
|
||||
Arm64FcmeqSz,
|
||||
Arm64FcmeqVz,
|
||||
Arm64FcmgeS,
|
||||
Arm64FcmgeV,
|
||||
Arm64FcmgeSz,
|
||||
Arm64FcmgeVz,
|
||||
Arm64FcmgtS,
|
||||
Arm64FcmgtV,
|
||||
Arm64FcmgtSz,
|
||||
Arm64FcmgtVz,
|
||||
Arm64FcmleSz,
|
||||
Arm64FcmleVz,
|
||||
Arm64FcmltSz,
|
||||
Arm64FcmltVz,
|
||||
Arm64FcmpeS,
|
||||
Arm64FcmpS,
|
||||
Arm64FcselS,
|
||||
Arm64FcvtasS,
|
||||
Arm64FcvtasV,
|
||||
Arm64FcvtasGp,
|
||||
Arm64FcvtauS,
|
||||
Arm64FcvtauV,
|
||||
Arm64FcvtauGp,
|
||||
Arm64FcvtlV,
|
||||
Arm64FcvtmsS,
|
||||
Arm64FcvtmsV,
|
||||
Arm64FcvtmsGp,
|
||||
Arm64FcvtmuS,
|
||||
Arm64FcvtmuV,
|
||||
Arm64FcvtmuGp,
|
||||
Arm64FcvtnsS,
|
||||
Arm64FcvtnsV,
|
||||
Arm64FcvtnsGp,
|
||||
Arm64FcvtnuS,
|
||||
Arm64FcvtnuV,
|
||||
Arm64FcvtnuGp,
|
||||
Arm64FcvtnV,
|
||||
Arm64FcvtpsS,
|
||||
Arm64FcvtpsV,
|
||||
Arm64FcvtpsGp,
|
||||
Arm64FcvtpuS,
|
||||
Arm64FcvtpuV,
|
||||
Arm64FcvtpuGp,
|
||||
Arm64FcvtxnS,
|
||||
Arm64FcvtxnV,
|
||||
Arm64FcvtzsSFixed,
|
||||
Arm64FcvtzsVFixed,
|
||||
Arm64FcvtzsS,
|
||||
Arm64FcvtzsV,
|
||||
Arm64FcvtzsGpFixed,
|
||||
Arm64FcvtzsGp,
|
||||
Arm64FcvtzuSFixed,
|
||||
Arm64FcvtzuVFixed,
|
||||
Arm64FcvtzuS,
|
||||
Arm64FcvtzuV,
|
||||
Arm64FcvtzuGpFixed,
|
||||
Arm64FcvtzuGp,
|
||||
Arm64FcvtS,
|
||||
Arm64FdivV,
|
||||
Arm64FdivS,
|
||||
Arm64FmaddS,
|
||||
Arm64FmaxnmpS,
|
||||
Arm64FmaxnmpV,
|
||||
Arm64FmaxnmvV,
|
||||
Arm64FmaxnmV,
|
||||
Arm64FmaxnmS,
|
||||
Arm64FmaxpS,
|
||||
Arm64FmaxpV,
|
||||
Arm64FmaxvV,
|
||||
Arm64FmaxV,
|
||||
Arm64FmaxS,
|
||||
Arm64FminnmpS,
|
||||
Arm64FminnmpV,
|
||||
Arm64FminnmvV,
|
||||
Arm64FminnmV,
|
||||
Arm64FminnmS,
|
||||
Arm64FminpS,
|
||||
Arm64FminpV,
|
||||
Arm64FminvV,
|
||||
Arm64FminV,
|
||||
Arm64FminS,
|
||||
Arm64FmlaSe,
|
||||
Arm64FmlaVe,
|
||||
Arm64FmlaV,
|
||||
Arm64FmlsSe,
|
||||
Arm64FmlsVe,
|
||||
Arm64FmlsV,
|
||||
Arm64FmovVi,
|
||||
Arm64FmovS,
|
||||
Arm64FmovGp,
|
||||
Arm64FmovSi,
|
||||
Arm64FmsubS,
|
||||
Arm64FmulxSe,
|
||||
Arm64FmulxVe,
|
||||
Arm64FmulxS,
|
||||
Arm64FmulxV,
|
||||
Arm64FmulSe,
|
||||
Arm64FmulVe,
|
||||
Arm64FmulV,
|
||||
Arm64FmulS,
|
||||
Arm64FnegV,
|
||||
Arm64FnegS,
|
||||
Arm64FnmaddS,
|
||||
Arm64FnmsubS,
|
||||
Arm64FnmulS,
|
||||
Arm64FrecpeS,
|
||||
Arm64FrecpeV,
|
||||
Arm64FrecpsS,
|
||||
Arm64FrecpsV,
|
||||
Arm64FrecpxS,
|
||||
Arm64FrintaV,
|
||||
Arm64FrintaS,
|
||||
Arm64FrintiV,
|
||||
Arm64FrintiS,
|
||||
Arm64FrintmV,
|
||||
Arm64FrintmS,
|
||||
Arm64FrintnV,
|
||||
Arm64FrintnS,
|
||||
Arm64FrintpV,
|
||||
Arm64FrintpS,
|
||||
Arm64FrintxV,
|
||||
Arm64FrintxS,
|
||||
Arm64FrintzV,
|
||||
Arm64FrintzS,
|
||||
Arm64FrsqrteS,
|
||||
Arm64FrsqrteV,
|
||||
Arm64FrsqrtsS,
|
||||
Arm64FrsqrtsV,
|
||||
Arm64FsqrtV,
|
||||
Arm64FsqrtS,
|
||||
Arm64FsubV,
|
||||
Arm64FsubS,
|
||||
Arm64InsVe,
|
||||
Arm64InsGp,
|
||||
Arm64Ld1rV,
|
||||
Arm64Ld1Vms,
|
||||
Arm64Ld1Vss,
|
||||
Arm64Ld2rV,
|
||||
Arm64Ld2Vms,
|
||||
Arm64Ld2Vss,
|
||||
Arm64Ld3rV,
|
||||
Arm64Ld3Vms,
|
||||
Arm64Ld3Vss,
|
||||
Arm64Ld4rV,
|
||||
Arm64Ld4Vms,
|
||||
Arm64Ld4Vss,
|
||||
Arm64MlaVe,
|
||||
Arm64MlaV,
|
||||
Arm64MlsVe,
|
||||
Arm64MlsV,
|
||||
Arm64MoviV,
|
||||
Arm64MrsFpsr,
|
||||
Arm64MsrFpsr,
|
||||
Arm64MulVe,
|
||||
Arm64MulV,
|
||||
Arm64MvniV,
|
||||
Arm64NegS,
|
||||
Arm64NegV,
|
||||
Arm64NotV,
|
||||
Arm64OrnV,
|
||||
Arm64OrrVi,
|
||||
Arm64OrrV,
|
||||
Arm64PmullV,
|
||||
Arm64PmulV,
|
||||
Arm64RaddhnV,
|
||||
Arm64RbitV,
|
||||
Arm64Rev16V,
|
||||
Arm64Rev32V,
|
||||
Arm64Rev64V,
|
||||
Arm64RshrnV,
|
||||
Arm64RsubhnV,
|
||||
Arm64SabalV,
|
||||
Arm64SabaV,
|
||||
Arm64SabdlV,
|
||||
Arm64SabdV,
|
||||
Arm64SadalpV,
|
||||
Arm64SaddlpV,
|
||||
Arm64SaddlvV,
|
||||
Arm64SaddlV,
|
||||
Arm64SaddwV,
|
||||
Arm64ScvtfSFixed,
|
||||
Arm64ScvtfVFixed,
|
||||
Arm64ScvtfS,
|
||||
Arm64ScvtfV,
|
||||
Arm64ScvtfGpFixed,
|
||||
Arm64ScvtfGp,
|
||||
Arm64Sha1cV,
|
||||
Arm64Sha1hV,
|
||||
Arm64Sha1mV,
|
||||
Arm64Sha1pV,
|
||||
Arm64Sha1su0V,
|
||||
Arm64Sha1su1V,
|
||||
Arm64Sha256h2V,
|
||||
Arm64Sha256hV,
|
||||
Arm64Sha256su0V,
|
||||
Arm64Sha256su1V,
|
||||
Arm64ShaddV,
|
||||
Arm64ShllV,
|
||||
Arm64ShlS,
|
||||
Arm64ShlV,
|
||||
Arm64ShrnV,
|
||||
Arm64ShsubV,
|
||||
Arm64SliS,
|
||||
Arm64SliV,
|
||||
Arm64SmaxpV,
|
||||
Arm64SmaxvV,
|
||||
Arm64SmaxV,
|
||||
Arm64SminpV,
|
||||
Arm64SminvV,
|
||||
Arm64SminV,
|
||||
Arm64SmlalVe,
|
||||
Arm64SmlalV,
|
||||
Arm64SmlslVe,
|
||||
Arm64SmlslV,
|
||||
Arm64SmovV,
|
||||
Arm64SmullVe,
|
||||
Arm64SmullV,
|
||||
Arm64SqabsS,
|
||||
Arm64SqabsV,
|
||||
Arm64SqaddS,
|
||||
Arm64SqaddV,
|
||||
Arm64SqdmlalSe,
|
||||
Arm64SqdmlalVe,
|
||||
Arm64SqdmlalS,
|
||||
Arm64SqdmlalV,
|
||||
Arm64SqdmlslSe,
|
||||
Arm64SqdmlslVe,
|
||||
Arm64SqdmlslS,
|
||||
Arm64SqdmlslV,
|
||||
Arm64SqdmulhSe,
|
||||
Arm64SqdmulhVe,
|
||||
Arm64SqdmulhS,
|
||||
Arm64SqdmulhV,
|
||||
Arm64SqdmullSe,
|
||||
Arm64SqdmullVe,
|
||||
Arm64SqdmullS,
|
||||
Arm64SqdmullV,
|
||||
Arm64SqnegS,
|
||||
Arm64SqnegV,
|
||||
Arm64SqrdmulhSe,
|
||||
Arm64SqrdmulhVe,
|
||||
Arm64SqrdmulhS,
|
||||
Arm64SqrdmulhV,
|
||||
Arm64SqrshlS,
|
||||
Arm64SqrshlV,
|
||||
Arm64SqrshrnS,
|
||||
Arm64SqrshrnV,
|
||||
Arm64SqrshrunS,
|
||||
Arm64SqrshrunV,
|
||||
Arm64SqshluS,
|
||||
Arm64SqshluV,
|
||||
Arm64SqshlSi,
|
||||
Arm64SqshlVi,
|
||||
Arm64SqshlS,
|
||||
Arm64SqshlV,
|
||||
Arm64SqshrnS,
|
||||
Arm64SqshrnV,
|
||||
Arm64SqshrunS,
|
||||
Arm64SqshrunV,
|
||||
Arm64SqsubS,
|
||||
Arm64SqsubV,
|
||||
Arm64SqxtnS,
|
||||
Arm64SqxtnV,
|
||||
Arm64SqxtunS,
|
||||
Arm64SqxtunV,
|
||||
Arm64SrhaddV,
|
||||
Arm64SriS,
|
||||
Arm64SriV,
|
||||
Arm64SrshlS,
|
||||
Arm64SrshlV,
|
||||
Arm64SrshrS,
|
||||
Arm64SrshrV,
|
||||
Arm64SrsraS,
|
||||
Arm64SrsraV,
|
||||
Arm64SshllV,
|
||||
Arm64SshlS,
|
||||
Arm64SshlV,
|
||||
Arm64SshrS,
|
||||
Arm64SshrV,
|
||||
Arm64SsraS,
|
||||
Arm64SsraV,
|
||||
Arm64SsublV,
|
||||
Arm64SsubwV,
|
||||
Arm64St1Vms,
|
||||
Arm64St1Vss,
|
||||
Arm64St2Vms,
|
||||
Arm64St2Vss,
|
||||
Arm64St3Vms,
|
||||
Arm64St3Vss,
|
||||
Arm64St4Vms,
|
||||
Arm64St4Vss,
|
||||
Arm64SubhnV,
|
||||
Arm64SubS,
|
||||
Arm64SubV,
|
||||
Arm64SuqaddS,
|
||||
Arm64SuqaddV,
|
||||
Arm64TblV,
|
||||
Arm64TbxV,
|
||||
Arm64Trn1V,
|
||||
Arm64Trn2V,
|
||||
Arm64UabalV,
|
||||
Arm64UabaV,
|
||||
Arm64UabdlV,
|
||||
Arm64UabdV,
|
||||
Arm64UadalpV,
|
||||
Arm64UaddlpV,
|
||||
Arm64UaddlvV,
|
||||
Arm64UaddlV,
|
||||
Arm64UaddwV,
|
||||
Arm64UcvtfSFixed,
|
||||
Arm64UcvtfVFixed,
|
||||
Arm64UcvtfS,
|
||||
Arm64UcvtfV,
|
||||
Arm64UcvtfGpFixed,
|
||||
Arm64UcvtfGp,
|
||||
Arm64UhaddV,
|
||||
Arm64UhsubV,
|
||||
Arm64UmaxpV,
|
||||
Arm64UmaxvV,
|
||||
Arm64UmaxV,
|
||||
Arm64UminpV,
|
||||
Arm64UminvV,
|
||||
Arm64UminV,
|
||||
Arm64UmlalVe,
|
||||
Arm64UmlalV,
|
||||
Arm64UmlslVe,
|
||||
Arm64UmlslV,
|
||||
Arm64UmovV,
|
||||
Arm64UmullVe,
|
||||
Arm64UmullV,
|
||||
Arm64UqaddS,
|
||||
Arm64UqaddV,
|
||||
Arm64UqrshlS,
|
||||
Arm64UqrshlV,
|
||||
Arm64UqrshrnS,
|
||||
Arm64UqrshrnV,
|
||||
Arm64UqshlSi,
|
||||
Arm64UqshlVi,
|
||||
Arm64UqshlS,
|
||||
Arm64UqshlV,
|
||||
Arm64UqshrnS,
|
||||
Arm64UqshrnV,
|
||||
Arm64UqsubS,
|
||||
Arm64UqsubV,
|
||||
Arm64UqxtnS,
|
||||
Arm64UqxtnV,
|
||||
Arm64UrecpeV,
|
||||
Arm64UrhaddV,
|
||||
Arm64UrshlS,
|
||||
Arm64UrshlV,
|
||||
Arm64UrshrS,
|
||||
Arm64UrshrV,
|
||||
Arm64UrsqrteV,
|
||||
Arm64UrsraS,
|
||||
Arm64UrsraV,
|
||||
Arm64UshllV,
|
||||
Arm64UshlS,
|
||||
Arm64UshlV,
|
||||
Arm64UshrS,
|
||||
Arm64UshrV,
|
||||
Arm64UsqaddS,
|
||||
Arm64UsqaddV,
|
||||
Arm64UsraS,
|
||||
Arm64UsraV,
|
||||
Arm64UsublV,
|
||||
Arm64UsubwV,
|
||||
Arm64Uzp1V,
|
||||
Arm64Uzp2V,
|
||||
Arm64XtnV,
|
||||
Arm64Zip1V,
|
||||
Arm64Zip2V,
|
||||
|
||||
Arm64VTypeShift = 13,
|
||||
Arm64VTypeMask = 1 << Arm64VTypeShift,
|
||||
Arm64V64 = 0 << Arm64VTypeShift,
|
||||
Arm64V128 = 1 << Arm64VTypeShift,
|
||||
|
||||
Arm64VSizeShift = 14,
|
||||
Arm64VSizeMask = 3 << Arm64VSizeShift,
|
||||
Arm64VFloat = 0 << Arm64VSizeShift,
|
||||
Arm64VDouble = 1 << Arm64VSizeShift,
|
||||
Arm64VByte = 0 << Arm64VSizeShift,
|
||||
Arm64VHWord = 1 << Arm64VSizeShift,
|
||||
Arm64VWord = 2 << Arm64VSizeShift,
|
||||
Arm64VDWord = 3 << Arm64VSizeShift
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
x1 = 0,
|
||||
x2 = 1,
|
||||
x4 = 2,
|
||||
x8 = 3
|
||||
x8 = 3,
|
||||
x16 = 4
|
||||
}
|
||||
}
|
@ -259,6 +259,20 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
}
|
||||
}
|
||||
|
||||
public Span<Operation> GetUses(ref Span<Operation> buffer)
|
||||
{
|
||||
ReadOnlySpan<Operation> uses = Uses;
|
||||
|
||||
if (buffer.Length < uses.Length)
|
||||
{
|
||||
buffer = Allocators.Default.AllocateSpan<Operation>((uint)uses.Length);
|
||||
}
|
||||
|
||||
uses.CopyTo(buffer);
|
||||
|
||||
return buffer.Slice(0, uses.Length);
|
||||
}
|
||||
|
||||
private static void New<T>(ref T* data, ref ushort count, ref ushort capacity, ushort initialCapacity) where T : unmanaged
|
||||
{
|
||||
count = 0;
|
||||
@ -378,14 +392,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (Kind == OperandKind.LocalVariable)
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
else
|
||||
{
|
||||
return (int)Value ^ ((int)Kind << 16) ^ ((int)Type << 20);
|
||||
}
|
||||
return ((ulong)_data).GetHashCode();
|
||||
}
|
||||
|
||||
public bool Equals(Operand operand)
|
||||
|
@ -47,5 +47,19 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||
|
||||
throw new InvalidOperationException($"Invalid operand type \"{type}\".");
|
||||
}
|
||||
|
||||
public static int GetSizeInBytesLog2(this OperandType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case OperandType.FP32: return 2;
|
||||
case OperandType.FP64: return 3;
|
||||
case OperandType.I32: return 2;
|
||||
case OperandType.I64: return 3;
|
||||
case OperandType.V128: return 4;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Invalid operand type \"{type}\".");
|
||||
}
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ namespace ARMeilleure.Memory
|
||||
{
|
||||
class ReservedRegion
|
||||
{
|
||||
private const int DefaultGranularity = 65536; // Mapping granularity in Windows.
|
||||
public const int DefaultGranularity = 65536; // Mapping granularity in Windows.
|
||||
|
||||
public IJitMemoryBlock Block { get; }
|
||||
|
||||
|
13
ARMeilleure/Native/JitSupportDarwin.cs
Normal file
13
ARMeilleure/Native/JitSupportDarwin.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
namespace ARMeilleure.Native
|
||||
{
|
||||
[SupportedOSPlatform("macos")]
|
||||
public static partial class JitSupportDarwin
|
||||
{
|
||||
[LibraryImport("libarmeilleure-jitsupport", EntryPoint = "armeilleure_jit_memcpy")]
|
||||
public static partial void Copy(IntPtr dst, IntPtr src, ulong n);
|
||||
}
|
||||
}
|
BIN
ARMeilleure/Native/libs/libarmeilleure-jitsupport.dylib
Normal file
BIN
ARMeilleure/Native/libs/libarmeilleure-jitsupport.dylib
Normal file
Binary file not shown.
8
ARMeilleure/Native/macos_jit_support/Makefile
Normal file
8
ARMeilleure/Native/macos_jit_support/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
NAME = libarmeilleure-jitsupport.dylib
|
||||
|
||||
all: ${NAME}
|
||||
|
||||
${NAME}:
|
||||
clang -O3 -dynamiclib support.c -o ${NAME}
|
||||
clean:
|
||||
rm -f ${NAME}
|
14
ARMeilleure/Native/macos_jit_support/support.c
Normal file
14
ARMeilleure/Native/macos_jit_support/support.c
Normal file
@ -0,0 +1,14 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <libkern/OSCacheControl.h>
|
||||
|
||||
void armeilleure_jit_memcpy(void *dst, const void *src, size_t n) {
|
||||
pthread_jit_write_protect_np(0);
|
||||
memcpy(dst, src, n);
|
||||
pthread_jit_write_protect_np(1);
|
||||
|
||||
// Ensure that the instruction cache for this range is invalidated.
|
||||
sys_icache_invalidate(dst, n);
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
using ARMeilleure.CodeGen.X86;
|
||||
using System.Runtime.Intrinsics.Arm;
|
||||
|
||||
namespace ARMeilleure
|
||||
{
|
||||
using Arm64HardwareCapabilities = ARMeilleure.CodeGen.Arm64.HardwareCapabilities;
|
||||
using X86HardwareCapabilities = ARMeilleure.CodeGen.X86.HardwareCapabilities;
|
||||
|
||||
public static class Optimizations
|
||||
{
|
||||
public static bool FastFP { get; set; } = true;
|
||||
@ -9,6 +12,9 @@ namespace ARMeilleure
|
||||
public static bool AllowLcqInFunctionTable { get; set; } = true;
|
||||
public static bool UseUnmanagedDispatchLoop { get; set; } = true;
|
||||
|
||||
public static bool UseAdvSimdIfAvailable { get; set; } = true;
|
||||
public static bool UseArm64PmullIfAvailable { get; set; } = true;
|
||||
|
||||
public static bool UseSseIfAvailable { get; set; } = true;
|
||||
public static bool UseSse2IfAvailable { get; set; } = true;
|
||||
public static bool UseSse3IfAvailable { get; set; } = true;
|
||||
@ -26,23 +32,26 @@ namespace ARMeilleure
|
||||
|
||||
public static bool ForceLegacySse
|
||||
{
|
||||
get => HardwareCapabilities.ForceLegacySse;
|
||||
set => HardwareCapabilities.ForceLegacySse = value;
|
||||
get => X86HardwareCapabilities.ForceLegacySse;
|
||||
set => X86HardwareCapabilities.ForceLegacySse = value;
|
||||
}
|
||||
|
||||
internal static bool UseSse => UseSseIfAvailable && HardwareCapabilities.SupportsSse;
|
||||
internal static bool UseSse2 => UseSse2IfAvailable && HardwareCapabilities.SupportsSse2;
|
||||
internal static bool UseSse3 => UseSse3IfAvailable && HardwareCapabilities.SupportsSse3;
|
||||
internal static bool UseSsse3 => UseSsse3IfAvailable && HardwareCapabilities.SupportsSsse3;
|
||||
internal static bool UseSse41 => UseSse41IfAvailable && HardwareCapabilities.SupportsSse41;
|
||||
internal static bool UseSse42 => UseSse42IfAvailable && HardwareCapabilities.SupportsSse42;
|
||||
internal static bool UsePopCnt => UsePopCntIfAvailable && HardwareCapabilities.SupportsPopcnt;
|
||||
internal static bool UseAvx => UseAvxIfAvailable && HardwareCapabilities.SupportsAvx && !ForceLegacySse;
|
||||
internal static bool UseF16c => UseF16cIfAvailable && HardwareCapabilities.SupportsF16c;
|
||||
internal static bool UseFma => UseFmaIfAvailable && HardwareCapabilities.SupportsFma;
|
||||
internal static bool UseAesni => UseAesniIfAvailable && HardwareCapabilities.SupportsAesni;
|
||||
internal static bool UsePclmulqdq => UsePclmulqdqIfAvailable && HardwareCapabilities.SupportsPclmulqdq;
|
||||
internal static bool UseSha => UseShaIfAvailable && HardwareCapabilities.SupportsSha;
|
||||
internal static bool UseGfni => UseGfniIfAvailable && HardwareCapabilities.SupportsGfni;
|
||||
internal static bool UseAdvSimd => UseAdvSimdIfAvailable && Arm64HardwareCapabilities.SupportsAdvSimd;
|
||||
internal static bool UseArm64Pmull => UseArm64PmullIfAvailable && Arm64HardwareCapabilities.SupportsPmull;
|
||||
|
||||
internal static bool UseSse => UseSseIfAvailable && X86HardwareCapabilities.SupportsSse;
|
||||
internal static bool UseSse2 => UseSse2IfAvailable && X86HardwareCapabilities.SupportsSse2;
|
||||
internal static bool UseSse3 => UseSse3IfAvailable && X86HardwareCapabilities.SupportsSse3;
|
||||
internal static bool UseSsse3 => UseSsse3IfAvailable && X86HardwareCapabilities.SupportsSsse3;
|
||||
internal static bool UseSse41 => UseSse41IfAvailable && X86HardwareCapabilities.SupportsSse41;
|
||||
internal static bool UseSse42 => UseSse42IfAvailable && X86HardwareCapabilities.SupportsSse42;
|
||||
internal static bool UsePopCnt => UsePopCntIfAvailable && X86HardwareCapabilities.SupportsPopcnt;
|
||||
internal static bool UseAvx => UseAvxIfAvailable && X86HardwareCapabilities.SupportsAvx && !ForceLegacySse;
|
||||
internal static bool UseF16c => UseF16cIfAvailable && X86HardwareCapabilities.SupportsF16c;
|
||||
internal static bool UseFma => UseFmaIfAvailable && X86HardwareCapabilities.SupportsFma;
|
||||
internal static bool UseAesni => UseAesniIfAvailable && X86HardwareCapabilities.SupportsAesni;
|
||||
internal static bool UsePclmulqdq => UsePclmulqdqIfAvailable && X86HardwareCapabilities.SupportsPclmulqdq;
|
||||
internal static bool UseSha => UseShaIfAvailable && X86HardwareCapabilities.SupportsSha;
|
||||
internal static bool UseGfni => UseGfniIfAvailable && X86HardwareCapabilities.SupportsGfni;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Memory;
|
||||
using ARMeilleure.Translation;
|
||||
using ARMeilleure.Translation.Cache;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
@ -69,8 +71,8 @@ namespace ARMeilleure.Signal
|
||||
|
||||
private const uint EXCEPTION_ACCESS_VIOLATION = 0xc0000005;
|
||||
|
||||
private const ulong PageSize = 0x1000;
|
||||
private const ulong PageMask = PageSize - 1;
|
||||
private static ulong _pageSize = GetPageSize();
|
||||
private static ulong _pageMask = _pageSize - 1;
|
||||
|
||||
private static IntPtr _handlerConfig;
|
||||
private static IntPtr _signalHandlerPtr;
|
||||
@ -79,6 +81,19 @@ namespace ARMeilleure.Signal
|
||||
private static readonly object _lock = new object();
|
||||
private static bool _initialized;
|
||||
|
||||
private static ulong GetPageSize()
|
||||
{
|
||||
// TODO: This needs to be based on the current memory manager configuration.
|
||||
if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
return 1UL << 14;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1UL << 12;
|
||||
}
|
||||
}
|
||||
|
||||
static NativeSignalHandler()
|
||||
{
|
||||
_handlerConfig = Marshal.AllocHGlobal(Unsafe.SizeOf<SignalHandlerConfig>());
|
||||
@ -87,7 +102,12 @@ namespace ARMeilleure.Signal
|
||||
config = new SignalHandlerConfig();
|
||||
}
|
||||
|
||||
public static void InitializeSignalHandler()
|
||||
public static void InitializeJitCache(IJitMemoryAllocator allocator)
|
||||
{
|
||||
JitCache.Initialize(allocator);
|
||||
}
|
||||
|
||||
public static void InitializeSignalHandler(Func<IntPtr, IntPtr, IntPtr> customSignalHandlerFactory = null)
|
||||
{
|
||||
if (_initialized) return;
|
||||
|
||||
@ -95,10 +115,9 @@ namespace ARMeilleure.Signal
|
||||
{
|
||||
if (_initialized) return;
|
||||
|
||||
bool unix = OperatingSystem.IsLinux() || OperatingSystem.IsMacOS();
|
||||
ref SignalHandlerConfig config = ref GetConfigRef();
|
||||
|
||||
if (unix)
|
||||
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
{
|
||||
// Unix siginfo struct locations.
|
||||
// NOTE: These are incredibly likely to be different between kernel version and architectures.
|
||||
@ -108,7 +127,13 @@ namespace ARMeilleure.Signal
|
||||
|
||||
_signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateUnixSignalHandler(_handlerConfig));
|
||||
|
||||
SigAction old = UnixSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr);
|
||||
if (customSignalHandlerFactory != null)
|
||||
{
|
||||
_signalHandlerPtr = customSignalHandlerFactory(UnixSignalHandlerRegistration.GetSegfaultExceptionHandler().sa_handler, _signalHandlerPtr);
|
||||
}
|
||||
|
||||
var old = UnixSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr);
|
||||
|
||||
config.UnixOldSigaction = (nuint)(ulong)old.sa_handler;
|
||||
config.UnixOldSigaction3Arg = old.sa_flags & 4;
|
||||
}
|
||||
@ -119,6 +144,11 @@ namespace ARMeilleure.Signal
|
||||
|
||||
_signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateWindowsSignalHandler(_handlerConfig));
|
||||
|
||||
if (customSignalHandlerFactory != null)
|
||||
{
|
||||
_signalHandlerPtr = customSignalHandlerFactory(IntPtr.Zero, _signalHandlerPtr);
|
||||
}
|
||||
|
||||
_signalHandlerHandle = WindowsSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr);
|
||||
}
|
||||
|
||||
@ -197,7 +227,7 @@ namespace ARMeilleure.Signal
|
||||
// Only call tracking if in range.
|
||||
context.BranchIfFalse(nextLabel, inRange, BasicBlockFrequency.Cold);
|
||||
|
||||
Operand offset = context.BitwiseAnd(context.Subtract(faultAddress, rangeAddress), Const(~PageMask));
|
||||
Operand offset = context.BitwiseAnd(context.Subtract(faultAddress, rangeAddress), Const(~_pageMask));
|
||||
|
||||
// Call the tracking action, with the pointer's relative offset to the base address.
|
||||
Operand trackingActionPtr = context.Load(OperandType.I64, Const((ulong)signalStructPtr + rangeBaseOffset + 20));
|
||||
@ -208,7 +238,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
// Tracking action should be non-null to call it, otherwise assume false return.
|
||||
context.BranchIfFalse(skipActionLabel, trackingActionPtr);
|
||||
Operand result = context.Call(trackingActionPtr, OperandType.I32, offset, Const(PageSize), isWrite, Const(0));
|
||||
Operand result = context.Call(trackingActionPtr, OperandType.I32, offset, Const(_pageSize), isWrite, Const(0));
|
||||
context.Copy(inRegionLocal, result);
|
||||
|
||||
context.MarkLabel(skipActionLabel);
|
||||
@ -278,7 +308,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
OperandType[] argTypes = new OperandType[] { OperandType.I32, OperandType.I64, OperandType.I64 };
|
||||
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq).Map<UnixExceptionHandler>();
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<UnixExceptionHandler>();
|
||||
}
|
||||
|
||||
private static VectoredExceptionHandler GenerateWindowsSignalHandler(IntPtr signalStructPtr)
|
||||
@ -332,7 +362,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq).Map<VectoredExceptionHandler>();
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<VectoredExceptionHandler>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
namespace ARMeilleure.Signal
|
||||
@ -32,7 +32,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq).Map<DebugPartialUnmap>();
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DebugPartialUnmap>();
|
||||
}
|
||||
|
||||
public static DebugThreadLocalMapGetOrReserve GenerateDebugThreadLocalMapGetOrReserve(IntPtr structPtr)
|
||||
@ -49,7 +49,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq).Map<DebugThreadLocalMapGetOrReserve>();
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DebugThreadLocalMapGetOrReserve>();
|
||||
}
|
||||
|
||||
public static DebugNativeWriteLoop GenerateDebugNativeWriteLoop()
|
||||
@ -78,7 +78,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq).Map<DebugNativeWriteLoop>();
|
||||
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DebugNativeWriteLoop>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,32 +3,47 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Signal
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
unsafe struct SigSet
|
||||
static partial class UnixSignalHandlerRegistration
|
||||
{
|
||||
fixed long sa_mask[16];
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public unsafe struct SigSet
|
||||
{
|
||||
fixed long sa_mask[16];
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct SigAction
|
||||
{
|
||||
public IntPtr sa_handler;
|
||||
public SigSet sa_mask;
|
||||
public int sa_flags;
|
||||
public IntPtr sa_restorer;
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct SigAction
|
||||
{
|
||||
public IntPtr sa_handler;
|
||||
public SigSet sa_mask;
|
||||
public int sa_flags;
|
||||
public IntPtr sa_restorer;
|
||||
}
|
||||
|
||||
static class UnixSignalHandlerRegistration
|
||||
{
|
||||
private const int SIGSEGV = 11;
|
||||
private const int SIGBUS = 10;
|
||||
private const int SA_SIGINFO = 0x00000004;
|
||||
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
private static extern int sigaction(int signum, ref SigAction sigAction, out SigAction oldAction);
|
||||
[LibraryImport("libc", SetLastError = true)]
|
||||
private static partial int sigaction(int signum, ref SigAction sigAction, out SigAction oldAction);
|
||||
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
private static extern int sigemptyset(ref SigSet set);
|
||||
[LibraryImport("libc", SetLastError = true)]
|
||||
private static partial int sigaction(int signum, IntPtr sigAction, out SigAction oldAction);
|
||||
|
||||
[LibraryImport("libc", SetLastError = true)]
|
||||
private static partial int sigemptyset(ref SigSet set);
|
||||
|
||||
public static SigAction GetSegfaultExceptionHandler()
|
||||
{
|
||||
int result = sigaction(SIGSEGV, IntPtr.Zero, out SigAction old);
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Could not get SIGSEGV sigaction. Error: {result}");
|
||||
}
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
public static SigAction RegisterExceptionHandler(IntPtr action)
|
||||
{
|
||||
@ -49,7 +64,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
result = sigaction(SIGBUS, ref sig, out SigAction oldb);
|
||||
result = sigaction(SIGBUS, ref sig, out _);
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
|
@ -3,19 +3,19 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Signal
|
||||
{
|
||||
unsafe class WindowsSignalHandlerRegistration
|
||||
unsafe partial class WindowsSignalHandlerRegistration
|
||||
{
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern IntPtr AddVectoredExceptionHandler(uint first, IntPtr handler);
|
||||
[LibraryImport("kernel32.dll")]
|
||||
private static partial IntPtr AddVectoredExceptionHandler(uint first, IntPtr handler);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern ulong RemoveVectoredExceptionHandler(IntPtr handle);
|
||||
[LibraryImport("kernel32.dll")]
|
||||
private static partial ulong RemoveVectoredExceptionHandler(IntPtr handle);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
|
||||
static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
|
||||
[LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "LoadLibraryA")]
|
||||
private static partial IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
|
||||
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
|
||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||
private static partial IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName);
|
||||
|
||||
private static IntPtr _getCurrentThreadIdPtr;
|
||||
|
||||
|
@ -6,7 +6,6 @@ using ARMeilleure.Instructions;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Memory;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation.PTC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
@ -40,18 +39,19 @@ namespace ARMeilleure.Translation
|
||||
}
|
||||
}
|
||||
|
||||
private bool _pendingQcFlagSync;
|
||||
|
||||
public OpCode CurrOp { get; set; }
|
||||
|
||||
public IMemoryManager Memory { get; }
|
||||
|
||||
public bool HasPtc { get; }
|
||||
|
||||
public EntryTable<uint> CountTable { get; }
|
||||
public AddressTable<ulong> FunctionTable { get; }
|
||||
public TranslatorStubs Stubs { get; }
|
||||
|
||||
public ulong EntryAddress { get; }
|
||||
public bool HighCq { get; }
|
||||
public bool HasPtc { get; }
|
||||
public Aarch32Mode Mode { get; }
|
||||
|
||||
private int _ifThenBlockStateIndex = 0;
|
||||
@ -66,15 +66,16 @@ namespace ARMeilleure.Translation
|
||||
TranslatorStubs stubs,
|
||||
ulong entryAddress,
|
||||
bool highCq,
|
||||
bool hasPtc,
|
||||
Aarch32Mode mode)
|
||||
{
|
||||
HasPtc = Ptc.State != PtcState.Disabled;
|
||||
Memory = memory;
|
||||
CountTable = countTable;
|
||||
FunctionTable = funcTable;
|
||||
Stubs = stubs;
|
||||
EntryAddress = entryAddress;
|
||||
HighCq = highCq;
|
||||
HasPtc = hasPtc;
|
||||
Mode = mode;
|
||||
|
||||
_labels = new Dictionary<ulong, Operand>();
|
||||
@ -82,6 +83,8 @@ namespace ARMeilleure.Translation
|
||||
|
||||
public override Operand Call(MethodInfo info, params Operand[] callArgs)
|
||||
{
|
||||
SyncQcFlag();
|
||||
|
||||
if (!HasPtc)
|
||||
{
|
||||
return base.Call(info, callArgs);
|
||||
@ -140,6 +143,51 @@ namespace ARMeilleure.Translation
|
||||
_optOpLastFlagSet = null;
|
||||
}
|
||||
|
||||
public void SetPendingQcFlagSync()
|
||||
{
|
||||
_pendingQcFlagSync = true;
|
||||
}
|
||||
|
||||
public void SyncQcFlag()
|
||||
{
|
||||
if (_pendingQcFlagSync)
|
||||
{
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
Operand fpsr = AddIntrinsicInt(Intrinsic.Arm64MrsFpsr);
|
||||
|
||||
uint qcFlagMask = (uint)FPSR.Qc;
|
||||
|
||||
Operand qcClearLabel = Label();
|
||||
|
||||
BranchIfFalse(qcClearLabel, BitwiseAnd(fpsr, Const(qcFlagMask)));
|
||||
|
||||
AddIntrinsicNoRet(Intrinsic.Arm64MsrFpsr, Const(0));
|
||||
InstEmitHelper.SetFpFlag(this, FPState.QcFlag, Const(1));
|
||||
|
||||
MarkLabel(qcClearLabel);
|
||||
}
|
||||
|
||||
_pendingQcFlagSync = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearQcFlag()
|
||||
{
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
AddIntrinsicNoRet(Intrinsic.Arm64MsrFpsr, Const(0));
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearQcFlagIfModified()
|
||||
{
|
||||
if (_pendingQcFlagSync && Optimizations.UseAdvSimd)
|
||||
{
|
||||
AddIntrinsicNoRet(Intrinsic.Arm64MsrFpsr, Const(0));
|
||||
}
|
||||
}
|
||||
|
||||
public Operand TryGetComparisonResult(Condition condition)
|
||||
{
|
||||
if (_optOpLastCompare == null || _optOpLastCompare != _optOpLastFlagSet)
|
||||
|
@ -1,6 +1,7 @@
|
||||
using ARMeilleure.CodeGen;
|
||||
using ARMeilleure.CodeGen.Unwinding;
|
||||
using ARMeilleure.Memory;
|
||||
using ARMeilleure.Native;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@ -17,6 +18,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
private const int CacheSize = 2047 * 1024 * 1024;
|
||||
|
||||
private static ReservedRegion _jitRegion;
|
||||
private static JitCacheInvalidation _jitCacheInvalidator;
|
||||
|
||||
private static CacheMemoryAllocator _cacheAllocator;
|
||||
|
||||
@ -25,8 +27,6 @@ namespace ARMeilleure.Translation.Cache
|
||||
private static readonly object _lock = new object();
|
||||
private static bool _initialized;
|
||||
|
||||
public static IntPtr Base => _jitRegion.Pointer;
|
||||
|
||||
public static void Initialize(IJitMemoryAllocator allocator)
|
||||
{
|
||||
if (_initialized) return;
|
||||
@ -36,6 +36,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
if (_initialized) return;
|
||||
|
||||
_jitRegion = new ReservedRegion(allocator, CacheSize);
|
||||
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
|
||||
|
||||
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
|
||||
|
||||
@ -60,11 +61,24 @@ namespace ARMeilleure.Translation.Cache
|
||||
|
||||
IntPtr funcPtr = _jitRegion.Pointer + funcOffset;
|
||||
|
||||
ReprotectAsWritable(funcOffset, code.Length);
|
||||
if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fixed (byte *codePtr = code)
|
||||
{
|
||||
JitSupportDarwin.Copy(funcPtr, (IntPtr)codePtr, (ulong)code.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ReprotectAsWritable(funcOffset, code.Length);
|
||||
Marshal.Copy(code, 0, funcPtr, code.Length);
|
||||
ReprotectAsExecutable(funcOffset, code.Length);
|
||||
|
||||
Marshal.Copy(code, 0, funcPtr, code.Length);
|
||||
|
||||
ReprotectAsExecutable(funcOffset, code.Length);
|
||||
_jitCacheInvalidator.Invalidate(funcPtr, (ulong)code.Length);
|
||||
}
|
||||
|
||||
Add(funcOffset, code.Length, func.UnwindInfo);
|
||||
|
||||
|
79
ARMeilleure/Translation/Cache/JitCacheInvalidation.cs
Normal file
79
ARMeilleure/Translation/Cache/JitCacheInvalidation.cs
Normal file
@ -0,0 +1,79 @@
|
||||
using ARMeilleure.Memory;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Translation.Cache
|
||||
{
|
||||
class JitCacheInvalidation
|
||||
{
|
||||
private static int[] _invalidationCode = new int[]
|
||||
{
|
||||
unchecked((int)0xd53b0022), // mrs x2, ctr_el0
|
||||
unchecked((int)0xd3504c44), // ubfx x4, x2, #16, #4
|
||||
unchecked((int)0x52800083), // mov w3, #0x4
|
||||
unchecked((int)0x12000c45), // and w5, w2, #0xf
|
||||
unchecked((int)0x1ac42064), // lsl w4, w3, w4
|
||||
unchecked((int)0x51000482), // sub w2, w4, #0x1
|
||||
unchecked((int)0x8a220002), // bic x2, x0, x2
|
||||
unchecked((int)0x1ac52063), // lsl w3, w3, w5
|
||||
unchecked((int)0xeb01005f), // cmp x2, x1
|
||||
unchecked((int)0x93407c84), // sxtw x4, w4
|
||||
unchecked((int)0x540000a2), // b.cs 3c <do_ic_clear>
|
||||
unchecked((int)0xd50b7b22), // dc cvau, x2
|
||||
unchecked((int)0x8b040042), // add x2, x2, x4
|
||||
unchecked((int)0xeb02003f), // cmp x1, x2
|
||||
unchecked((int)0x54ffffa8), // b.hi 2c <dc_clear_loop>
|
||||
unchecked((int)0xd5033b9f), // dsb ish
|
||||
unchecked((int)0x51000462), // sub w2, w3, #0x1
|
||||
unchecked((int)0x93407c63), // sxtw x3, w3
|
||||
unchecked((int)0x8a220000), // bic x0, x0, x2
|
||||
unchecked((int)0xeb00003f), // cmp x1, x0
|
||||
unchecked((int)0x540000a9), // b.ls 64 <exit>
|
||||
unchecked((int)0xd50b7520), // ic ivau, x0
|
||||
unchecked((int)0x8b030000), // add x0, x0, x3
|
||||
unchecked((int)0xeb00003f), // cmp x1, x0
|
||||
unchecked((int)0x54ffffa8), // b.hi 54 <ic_clear_loop>
|
||||
unchecked((int)0xd5033b9f), // dsb ish
|
||||
unchecked((int)0xd5033fdf), // isb
|
||||
unchecked((int)0xd65f03c0), // ret
|
||||
};
|
||||
|
||||
private delegate void InvalidateCache(ulong start, ulong end);
|
||||
|
||||
private InvalidateCache _invalidateCache;
|
||||
private ReservedRegion _invalidateCacheCodeRegion;
|
||||
|
||||
private readonly bool _needsInvalidation;
|
||||
|
||||
public JitCacheInvalidation(IJitMemoryAllocator allocator)
|
||||
{
|
||||
// On macOS, a different path is used to write to the JIT cache, which does the invalidation.
|
||||
if (!OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
ulong size = (ulong)_invalidationCode.Length * sizeof(int);
|
||||
ulong mask = (ulong)ReservedRegion.DefaultGranularity - 1;
|
||||
|
||||
size = (size + mask) & ~mask;
|
||||
|
||||
_invalidateCacheCodeRegion = new ReservedRegion(allocator, size);
|
||||
_invalidateCacheCodeRegion.ExpandIfNeeded(size);
|
||||
|
||||
Marshal.Copy(_invalidationCode, 0, _invalidateCacheCodeRegion.Pointer, _invalidationCode.Length);
|
||||
|
||||
_invalidateCacheCodeRegion.Block.MapAsRx(0, size);
|
||||
|
||||
_invalidateCache = Marshal.GetDelegateForFunctionPointer<InvalidateCache>(_invalidateCacheCodeRegion.Pointer);
|
||||
|
||||
_needsInvalidation = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Invalidate(IntPtr basePointer, ulong size)
|
||||
{
|
||||
if (_needsInvalidation)
|
||||
{
|
||||
_invalidateCache((ulong)basePointer, (ulong)basePointer + size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Translation.Cache
|
||||
{
|
||||
static class JitUnwindWindows
|
||||
static partial class JitUnwindWindows
|
||||
{
|
||||
private const int MaxUnwindCodesArraySize = 32; // Must be an even value.
|
||||
|
||||
@ -42,14 +42,15 @@ namespace ARMeilleure.Translation.Cache
|
||||
|
||||
private unsafe delegate RuntimeFunction* GetRuntimeFunctionCallback(ulong controlPc, IntPtr context);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
private static unsafe extern bool RtlInstallFunctionTableCallback(
|
||||
[LibraryImport("kernel32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static unsafe partial bool RtlInstallFunctionTableCallback(
|
||||
ulong tableIdentifier,
|
||||
ulong baseAddress,
|
||||
uint length,
|
||||
GetRuntimeFunctionCallback callback,
|
||||
IntPtr context,
|
||||
string outOfProcessCallbackDll);
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string outOfProcessCallbackDll);
|
||||
|
||||
private static GetRuntimeFunctionCallback _getRuntimeFunctionCallback;
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
using ARMeilleure.CodeGen;
|
||||
using ARMeilleure.CodeGen.Optimizations;
|
||||
using ARMeilleure.CodeGen.X86;
|
||||
using ARMeilleure.Diagnostics;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
@ -12,7 +13,8 @@ namespace ARMeilleure.Translation
|
||||
ControlFlowGraph cfg,
|
||||
OperandType[] argTypes,
|
||||
OperandType retType,
|
||||
CompilerOptions options)
|
||||
CompilerOptions options,
|
||||
Architecture target)
|
||||
{
|
||||
CompilerContext cctx = new(cfg, argTypes, retType, options);
|
||||
|
||||
@ -49,7 +51,18 @@ namespace ARMeilleure.Translation
|
||||
Logger.EndPass(PassName.RegisterToLocal, cfg);
|
||||
}
|
||||
|
||||
return CodeGenerator.Generate(cctx);
|
||||
if (target == Architecture.X64)
|
||||
{
|
||||
return CodeGen.X86.CodeGenerator.Generate(cctx);
|
||||
}
|
||||
else if (target == Architecture.Arm64)
|
||||
{
|
||||
return CodeGen.Arm64.CodeGenerator.Generate(cctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException(target.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -25,10 +25,7 @@ namespace ARMeilleure.Translation
|
||||
|
||||
public static Delegate GetDelegate(MethodInfo info)
|
||||
{
|
||||
if (info == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(info));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(info);
|
||||
|
||||
Type[] parameters = info.GetParameters().Select(pI => pI.ParameterType).ToArray();
|
||||
Type returnType = info.ReturnType;
|
||||
|
@ -35,10 +35,7 @@ namespace ARMeilleure.Translation
|
||||
|
||||
public static IntPtr GetDelegateFuncPtr(MethodInfo info)
|
||||
{
|
||||
if (info == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(info));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(info);
|
||||
|
||||
string key = GetKey(info);
|
||||
|
||||
@ -52,10 +49,7 @@ namespace ARMeilleure.Translation
|
||||
|
||||
public static int GetDelegateIndex(MethodInfo info)
|
||||
{
|
||||
if (info == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(info));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(info);
|
||||
|
||||
string key = GetKey(info);
|
||||
|
||||
|
@ -67,10 +67,7 @@ namespace ARMeilleure.Translation
|
||||
/// <returns>True if the value was added, false if the start key was already in the dictionary</returns>
|
||||
public bool AddOrUpdate(K start, K end, V value, Func<K, V, V> updateFactoryCallback)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
|
||||
return BSTInsert(start, end, value, updateFactoryCallback, out IntervalTreeNode<K, V> node);
|
||||
}
|
||||
@ -85,10 +82,7 @@ namespace ARMeilleure.Translation
|
||||
/// <returns><paramref name="value"/> if <paramref name="start"/> is not yet on the tree, or the existing value otherwise</returns>
|
||||
public V GetOrAdd(K start, K end, V value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
|
||||
BSTInsert(start, end, value, null, out IntervalTreeNode<K, V> node);
|
||||
return node.Value;
|
||||
@ -152,10 +146,7 @@ namespace ARMeilleure.Translation
|
||||
/// <returns>Node reference in the tree</returns>
|
||||
private IntervalTreeNode<K, V> GetNode(K key)
|
||||
{
|
||||
if (key == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(key));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
|
||||
IntervalTreeNode<K, V> node = _root;
|
||||
while (node != null)
|
||||
|
10
ARMeilleure/Translation/PTC/IPtcLoadState.cs
Normal file
10
ARMeilleure/Translation/PTC/IPtcLoadState.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace ARMeilleure.Translation.PTC
|
||||
{
|
||||
public interface IPtcLoadState
|
||||
{
|
||||
event Action<PtcLoadingState, int, int> PtcStateChanged;
|
||||
void Continue();
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
using ARMeilleure.CodeGen;
|
||||
using ARMeilleure.CodeGen.Linking;
|
||||
using ARMeilleure.CodeGen.Unwinding;
|
||||
using ARMeilleure.CodeGen.X86;
|
||||
using ARMeilleure.Common;
|
||||
using ARMeilleure.Memory;
|
||||
using Ryujinx.Common;
|
||||
@ -22,12 +21,15 @@ using static ARMeilleure.Translation.PTC.PtcFormatter;
|
||||
|
||||
namespace ARMeilleure.Translation.PTC
|
||||
{
|
||||
public static class Ptc
|
||||
using Arm64HardwareCapabilities = ARMeilleure.CodeGen.Arm64.HardwareCapabilities;
|
||||
using X86HardwareCapabilities = ARMeilleure.CodeGen.X86.HardwareCapabilities;
|
||||
|
||||
class Ptc : IPtcLoadState
|
||||
{
|
||||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||
|
||||
private const uint InternalVersion = 3713; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
private const uint InternalVersion = 4272; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
|
||||
private const string ActualDir = "0";
|
||||
private const string BackupDir = "1";
|
||||
@ -35,45 +37,49 @@ namespace ARMeilleure.Translation.PTC
|
||||
private const string TitleIdTextDefault = "0000000000000000";
|
||||
private const string DisplayVersionDefault = "0";
|
||||
|
||||
internal static readonly Symbol PageTableSymbol = new(SymbolType.Special, 1);
|
||||
internal static readonly Symbol CountTableSymbol = new(SymbolType.Special, 2);
|
||||
internal static readonly Symbol DispatchStubSymbol = new(SymbolType.Special, 3);
|
||||
public static readonly Symbol PageTableSymbol = new(SymbolType.Special, 1);
|
||||
public static readonly Symbol CountTableSymbol = new(SymbolType.Special, 2);
|
||||
public static readonly Symbol DispatchStubSymbol = new(SymbolType.Special, 3);
|
||||
|
||||
private const byte FillingByte = 0x00;
|
||||
private const CompressionLevel SaveCompressionLevel = CompressionLevel.Fastest;
|
||||
|
||||
public PtcProfiler Profiler { get; }
|
||||
|
||||
// Carriers.
|
||||
private static MemoryStream _infosStream;
|
||||
private static List<byte[]> _codesList;
|
||||
private static MemoryStream _relocsStream;
|
||||
private static MemoryStream _unwindInfosStream;
|
||||
private MemoryStream _infosStream;
|
||||
private List<byte[]> _codesList;
|
||||
private MemoryStream _relocsStream;
|
||||
private MemoryStream _unwindInfosStream;
|
||||
|
||||
private static readonly ulong _outerHeaderMagic;
|
||||
private static readonly ulong _innerHeaderMagic;
|
||||
private readonly ulong _outerHeaderMagic;
|
||||
private readonly ulong _innerHeaderMagic;
|
||||
|
||||
private static readonly ManualResetEvent _waitEvent;
|
||||
private readonly ManualResetEvent _waitEvent;
|
||||
|
||||
private static readonly object _lock;
|
||||
private readonly object _lock;
|
||||
|
||||
private static bool _disposed;
|
||||
private bool _disposed;
|
||||
|
||||
internal static string TitleIdText { get; private set; }
|
||||
internal static string DisplayVersion { get; private set; }
|
||||
public string TitleIdText { get; private set; }
|
||||
public string DisplayVersion { get; private set; }
|
||||
|
||||
private static MemoryManagerMode _memoryMode;
|
||||
private MemoryManagerType _memoryMode;
|
||||
|
||||
internal static string CachePathActual { get; private set; }
|
||||
internal static string CachePathBackup { get; private set; }
|
||||
public string CachePathActual { get; private set; }
|
||||
public string CachePathBackup { get; private set; }
|
||||
|
||||
internal static PtcState State { get; private set; }
|
||||
public PtcState State { get; private set; }
|
||||
|
||||
// Progress reporting helpers.
|
||||
private static volatile int _translateCount;
|
||||
private static volatile int _translateTotalCount;
|
||||
public static event Action<PtcLoadingState, int, int> PtcStateChanged;
|
||||
private volatile int _translateCount;
|
||||
private volatile int _translateTotalCount;
|
||||
public event Action<PtcLoadingState, int, int> PtcStateChanged;
|
||||
|
||||
static Ptc()
|
||||
public Ptc()
|
||||
{
|
||||
Profiler = new PtcProfiler(this);
|
||||
|
||||
InitializeCarriers();
|
||||
|
||||
_outerHeaderMagic = BinaryPrimitives.ReadUInt64LittleEndian(EncodingCache.UTF8NoBOM.GetBytes(OuterHeaderMagicString).AsSpan());
|
||||
@ -94,12 +100,12 @@ namespace ARMeilleure.Translation.PTC
|
||||
Disable();
|
||||
}
|
||||
|
||||
public static void Initialize(string titleIdText, string displayVersion, bool enabled, MemoryManagerMode memoryMode)
|
||||
public void Initialize(string titleIdText, string displayVersion, bool enabled, MemoryManagerType memoryMode)
|
||||
{
|
||||
Wait();
|
||||
|
||||
PtcProfiler.Wait();
|
||||
PtcProfiler.ClearEntries();
|
||||
Profiler.Wait();
|
||||
Profiler.ClearEntries();
|
||||
|
||||
Logger.Info?.Print(LogClass.Ptc, $"Initializing Profiled Persistent Translation Cache (enabled: {enabled}).");
|
||||
|
||||
@ -137,12 +143,12 @@ namespace ARMeilleure.Translation.PTC
|
||||
CachePathBackup = Path.Combine(workPathBackup, DisplayVersion);
|
||||
|
||||
PreLoad();
|
||||
PtcProfiler.PreLoad();
|
||||
Profiler.PreLoad();
|
||||
|
||||
Enable();
|
||||
}
|
||||
|
||||
private static void InitializeCarriers()
|
||||
private void InitializeCarriers()
|
||||
{
|
||||
_infosStream = new MemoryStream();
|
||||
_codesList = new List<byte[]>();
|
||||
@ -150,7 +156,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
_unwindInfosStream = new MemoryStream();
|
||||
}
|
||||
|
||||
private static void DisposeCarriers()
|
||||
private void DisposeCarriers()
|
||||
{
|
||||
_infosStream.Dispose();
|
||||
_codesList.Clear();
|
||||
@ -158,12 +164,12 @@ namespace ARMeilleure.Translation.PTC
|
||||
_unwindInfosStream.Dispose();
|
||||
}
|
||||
|
||||
private static bool AreCarriersEmpty()
|
||||
private bool AreCarriersEmpty()
|
||||
{
|
||||
return _infosStream.Length == 0L && _codesList.Count == 0 && _relocsStream.Length == 0L && _unwindInfosStream.Length == 0L;
|
||||
}
|
||||
|
||||
private static void ResetCarriersIfNeeded()
|
||||
private void ResetCarriersIfNeeded()
|
||||
{
|
||||
if (AreCarriersEmpty())
|
||||
{
|
||||
@ -175,7 +181,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
InitializeCarriers();
|
||||
}
|
||||
|
||||
private static void PreLoad()
|
||||
private void PreLoad()
|
||||
{
|
||||
string fileNameActual = string.Concat(CachePathActual, ".cache");
|
||||
string fileNameBackup = string.Concat(CachePathBackup, ".cache");
|
||||
@ -199,7 +205,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe bool Load(string fileName, bool isBackup)
|
||||
private unsafe bool Load(string fileName, bool isBackup)
|
||||
{
|
||||
using (FileStream compressedStream = new(fileName, FileMode.Open))
|
||||
using (DeflateStream deflateStream = new(compressedStream, CompressionMode.Decompress, true))
|
||||
@ -255,6 +261,13 @@ namespace ARMeilleure.Translation.PTC
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outerHeader.Architecture != (uint)RuntimeInformation.ProcessArchitecture)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
IntPtr intPtr = IntPtr.Zero;
|
||||
|
||||
try
|
||||
@ -376,12 +389,12 @@ namespace ARMeilleure.Translation.PTC
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void InvalidateCompressedStream(FileStream compressedStream)
|
||||
private void InvalidateCompressedStream(FileStream compressedStream)
|
||||
{
|
||||
compressedStream.SetLength(0L);
|
||||
}
|
||||
|
||||
private static void PreSave()
|
||||
private void PreSave()
|
||||
{
|
||||
_waitEvent.Reset();
|
||||
|
||||
@ -409,7 +422,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
_waitEvent.Set();
|
||||
}
|
||||
|
||||
private static unsafe void Save(string fileName)
|
||||
private unsafe void Save(string fileName)
|
||||
{
|
||||
int translatedFuncsCount;
|
||||
|
||||
@ -431,6 +444,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
outerHeader.FeatureInfo = GetFeatureInfo();
|
||||
outerHeader.MemoryManagerMode = GetMemoryManagerMode();
|
||||
outerHeader.OSPlatform = GetOSPlatform();
|
||||
outerHeader.Architecture = (uint)RuntimeInformation.ProcessArchitecture;
|
||||
|
||||
outerHeader.UncompressedStreamSize =
|
||||
(long)Unsafe.SizeOf<InnerHeader>() +
|
||||
@ -517,7 +531,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
internal static void LoadTranslations(Translator translator)
|
||||
public void LoadTranslations(Translator translator)
|
||||
{
|
||||
if (AreCarriersEmpty())
|
||||
{
|
||||
@ -550,7 +564,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
|
||||
bool isEntryChanged = infoEntry.Hash != ComputeHash(translator.Memory, infoEntry.Address, infoEntry.GuestSize);
|
||||
|
||||
if (isEntryChanged || (!infoEntry.HighCq && PtcProfiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out var value) && value.HighCq))
|
||||
if (isEntryChanged || (!infoEntry.HighCq && Profiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out var value) && value.HighCq))
|
||||
{
|
||||
infoEntry.Stubbed = true;
|
||||
infoEntry.CodeLength = 0;
|
||||
@ -601,38 +615,38 @@ namespace ARMeilleure.Translation.PTC
|
||||
Logger.Info?.Print(LogClass.Ptc, $"{translator.Functions.Count} translated functions loaded");
|
||||
}
|
||||
|
||||
private static int GetEntriesCount()
|
||||
private int GetEntriesCount()
|
||||
{
|
||||
return _codesList.Count;
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
private static void SkipCode(int index, int codeLength)
|
||||
private void SkipCode(int index, int codeLength)
|
||||
{
|
||||
Debug.Assert(_codesList[index].Length == 0);
|
||||
Debug.Assert(codeLength == 0);
|
||||
}
|
||||
|
||||
private static void SkipReloc(int relocEntriesCount)
|
||||
private void SkipReloc(int relocEntriesCount)
|
||||
{
|
||||
_relocsStream.Seek(relocEntriesCount * RelocEntry.Stride, SeekOrigin.Current);
|
||||
}
|
||||
|
||||
private static void SkipUnwindInfo(BinaryReader unwindInfosReader)
|
||||
private void SkipUnwindInfo(BinaryReader unwindInfosReader)
|
||||
{
|
||||
int pushEntriesLength = unwindInfosReader.ReadInt32();
|
||||
|
||||
_unwindInfosStream.Seek(pushEntriesLength * UnwindPushEntry.Stride + UnwindInfo.Stride, SeekOrigin.Current);
|
||||
}
|
||||
|
||||
private static byte[] ReadCode(int index, int codeLength)
|
||||
private byte[] ReadCode(int index, int codeLength)
|
||||
{
|
||||
Debug.Assert(_codesList[index].Length == codeLength);
|
||||
|
||||
return _codesList[index];
|
||||
}
|
||||
|
||||
private static RelocEntry[] GetRelocEntries(BinaryReader relocsReader, int relocEntriesCount)
|
||||
private RelocEntry[] GetRelocEntries(BinaryReader relocsReader, int relocEntriesCount)
|
||||
{
|
||||
RelocEntry[] relocEntries = new RelocEntry[relocEntriesCount];
|
||||
|
||||
@ -648,7 +662,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
return relocEntries;
|
||||
}
|
||||
|
||||
private static void PatchCode(Translator translator, Span<byte> code, RelocEntry[] relocEntries, out Counter<uint> callCounter)
|
||||
private void PatchCode(Translator translator, Span<byte> code, RelocEntry[] relocEntries, out Counter<uint> callCounter)
|
||||
{
|
||||
callCounter = null;
|
||||
|
||||
@ -702,7 +716,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
private static UnwindInfo ReadUnwindInfo(BinaryReader unwindInfosReader)
|
||||
private UnwindInfo ReadUnwindInfo(BinaryReader unwindInfosReader)
|
||||
{
|
||||
int pushEntriesLength = unwindInfosReader.ReadInt32();
|
||||
|
||||
@ -723,7 +737,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
return new UnwindInfo(pushEntries, prologueSize);
|
||||
}
|
||||
|
||||
private static TranslatedFunction FastTranslate(
|
||||
private TranslatedFunction FastTranslate(
|
||||
byte[] code,
|
||||
Counter<uint> callCounter,
|
||||
ulong guestSize,
|
||||
@ -736,19 +750,19 @@ namespace ARMeilleure.Translation.PTC
|
||||
return new TranslatedFunction(gFunc, callCounter, guestSize, highCq);
|
||||
}
|
||||
|
||||
private static void UpdateInfo(InfoEntry infoEntry)
|
||||
private void UpdateInfo(InfoEntry infoEntry)
|
||||
{
|
||||
_infosStream.Seek(-Unsafe.SizeOf<InfoEntry>(), SeekOrigin.Current);
|
||||
|
||||
SerializeStructure(_infosStream, infoEntry);
|
||||
}
|
||||
|
||||
private static void StubCode(int index)
|
||||
private void StubCode(int index)
|
||||
{
|
||||
_codesList[index] = Array.Empty<byte>();
|
||||
}
|
||||
|
||||
private static void StubReloc(int relocEntriesCount)
|
||||
private void StubReloc(int relocEntriesCount)
|
||||
{
|
||||
for (int i = 0; i < relocEntriesCount * RelocEntry.Stride; i++)
|
||||
{
|
||||
@ -756,7 +770,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
private static void StubUnwindInfo(BinaryReader unwindInfosReader)
|
||||
private void StubUnwindInfo(BinaryReader unwindInfosReader)
|
||||
{
|
||||
int pushEntriesLength = unwindInfosReader.ReadInt32();
|
||||
|
||||
@ -766,9 +780,9 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
internal static void MakeAndSaveTranslations(Translator translator)
|
||||
public void MakeAndSaveTranslations(Translator translator)
|
||||
{
|
||||
var profiledFuncsToTranslate = PtcProfiler.GetProfiledFuncsToTranslate(translator.Functions);
|
||||
var profiledFuncsToTranslate = Profiler.GetProfiledFuncsToTranslate(translator.Functions);
|
||||
|
||||
_translateCount = 0;
|
||||
_translateTotalCount = profiledFuncsToTranslate.Count;
|
||||
@ -811,7 +825,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
{
|
||||
ulong address = item.address;
|
||||
|
||||
Debug.Assert(PtcProfiler.IsAddressInStaticCodeRange(address));
|
||||
Debug.Assert(Profiler.IsAddressInStaticCodeRange(address));
|
||||
|
||||
TranslatedFunction func = translator.Translate(address, item.funcProfile.Mode, item.funcProfile.HighCq);
|
||||
|
||||
@ -861,7 +875,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
preSaveThread.Start();
|
||||
}
|
||||
|
||||
private static void ReportProgress(object state)
|
||||
private void ReportProgress(object state)
|
||||
{
|
||||
const int refreshRate = 50; // ms.
|
||||
|
||||
@ -882,12 +896,12 @@ namespace ARMeilleure.Translation.PTC
|
||||
while (!endEvent.WaitOne(refreshRate));
|
||||
}
|
||||
|
||||
internal static Hash128 ComputeHash(IMemoryManager memory, ulong address, ulong guestSize)
|
||||
public static Hash128 ComputeHash(IMemoryManager memory, ulong address, ulong guestSize)
|
||||
{
|
||||
return XXHash128.ComputeHash(memory.GetSpan(address, checked((int)(guestSize))));
|
||||
}
|
||||
|
||||
internal static void WriteCompiledFunction(ulong address, ulong guestSize, Hash128 hash, bool highCq, CompiledFunction compiledFunc)
|
||||
public void WriteCompiledFunction(ulong address, ulong guestSize, Hash128 hash, bool highCq, CompiledFunction compiledFunc)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
@ -936,26 +950,41 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteCode(ReadOnlySpan<byte> code)
|
||||
private void WriteCode(ReadOnlySpan<byte> code)
|
||||
{
|
||||
_codesList.Add(code.ToArray());
|
||||
}
|
||||
|
||||
internal static bool GetEndianness()
|
||||
public static bool GetEndianness()
|
||||
{
|
||||
return BitConverter.IsLittleEndian;
|
||||
}
|
||||
|
||||
private static FeatureInfo GetFeatureInfo()
|
||||
{
|
||||
return new FeatureInfo(
|
||||
(uint)HardwareCapabilities.FeatureInfo1Ecx,
|
||||
(uint)HardwareCapabilities.FeatureInfo1Edx,
|
||||
(uint)HardwareCapabilities.FeatureInfo7Ebx,
|
||||
(uint)HardwareCapabilities.FeatureInfo7Ecx);
|
||||
if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
return new FeatureInfo(
|
||||
(ulong)Arm64HardwareCapabilities.LinuxFeatureInfoHwCap,
|
||||
(ulong)Arm64HardwareCapabilities.LinuxFeatureInfoHwCap2,
|
||||
(ulong)Arm64HardwareCapabilities.MacOsFeatureInfo,
|
||||
0);
|
||||
}
|
||||
else if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
|
||||
{
|
||||
return new FeatureInfo(
|
||||
(ulong)X86HardwareCapabilities.FeatureInfo1Ecx,
|
||||
(ulong)X86HardwareCapabilities.FeatureInfo1Edx,
|
||||
(ulong)X86HardwareCapabilities.FeatureInfo7Ebx,
|
||||
(ulong)X86HardwareCapabilities.FeatureInfo7Ecx);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new FeatureInfo(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte GetMemoryManagerMode()
|
||||
private byte GetMemoryManagerMode()
|
||||
{
|
||||
return (byte)_memoryMode;
|
||||
}
|
||||
@ -972,7 +1001,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
return osPlatform;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 58*/)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 78*/)]
|
||||
private struct OuterHeader
|
||||
{
|
||||
public ulong Magic;
|
||||
@ -983,6 +1012,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
public FeatureInfo FeatureInfo;
|
||||
public byte MemoryManagerMode;
|
||||
public uint OSPlatform;
|
||||
public uint Architecture;
|
||||
|
||||
public long UncompressedStreamSize;
|
||||
|
||||
@ -1003,8 +1033,8 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 16*/)]
|
||||
private record struct FeatureInfo(uint FeatureInfo0, uint FeatureInfo1, uint FeatureInfo2, uint FeatureInfo3);
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 32*/)]
|
||||
private record struct FeatureInfo(ulong FeatureInfo0, ulong FeatureInfo1, ulong FeatureInfo2, ulong FeatureInfo3);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 128*/)]
|
||||
private struct InnerHeader
|
||||
@ -1050,12 +1080,12 @@ namespace ARMeilleure.Translation.PTC
|
||||
public int RelocEntriesCount;
|
||||
}
|
||||
|
||||
private static void Enable()
|
||||
private void Enable()
|
||||
{
|
||||
State = PtcState.Enabled;
|
||||
}
|
||||
|
||||
public static void Continue()
|
||||
public void Continue()
|
||||
{
|
||||
if (State == PtcState.Enabled)
|
||||
{
|
||||
@ -1063,7 +1093,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
public static void Close()
|
||||
public void Close()
|
||||
{
|
||||
if (State == PtcState.Enabled ||
|
||||
State == PtcState.Continuing)
|
||||
@ -1072,17 +1102,17 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Disable()
|
||||
public void Disable()
|
||||
{
|
||||
State = PtcState.Disabled;
|
||||
}
|
||||
|
||||
private static void Wait()
|
||||
private void Wait()
|
||||
{
|
||||
_waitEvent.WaitOne();
|
||||
}
|
||||
|
||||
public static void Dispose()
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
|
@ -16,7 +16,7 @@ using static ARMeilleure.Translation.PTC.PtcFormatter;
|
||||
|
||||
namespace ARMeilleure.Translation.PTC
|
||||
{
|
||||
public static class PtcProfiler
|
||||
class PtcProfiler
|
||||
{
|
||||
private const string OuterHeaderMagicString = "Pohd\0\0\0\0";
|
||||
|
||||
@ -26,27 +26,31 @@ namespace ARMeilleure.Translation.PTC
|
||||
|
||||
private const CompressionLevel SaveCompressionLevel = CompressionLevel.Fastest;
|
||||
|
||||
private static readonly System.Timers.Timer _timer;
|
||||
private readonly Ptc _ptc;
|
||||
|
||||
private static readonly ulong _outerHeaderMagic;
|
||||
private readonly System.Timers.Timer _timer;
|
||||
|
||||
private static readonly ManualResetEvent _waitEvent;
|
||||
private readonly ulong _outerHeaderMagic;
|
||||
|
||||
private static readonly object _lock;
|
||||
private readonly ManualResetEvent _waitEvent;
|
||||
|
||||
private static bool _disposed;
|
||||
private readonly object _lock;
|
||||
|
||||
private static Hash128 _lastHash;
|
||||
private bool _disposed;
|
||||
|
||||
internal static Dictionary<ulong, FuncProfile> ProfiledFuncs { get; private set; }
|
||||
private Hash128 _lastHash;
|
||||
|
||||
internal static bool Enabled { get; private set; }
|
||||
public Dictionary<ulong, FuncProfile> ProfiledFuncs { get; private set; }
|
||||
|
||||
public static ulong StaticCodeStart { internal get; set; }
|
||||
public static ulong StaticCodeSize { internal get; set; }
|
||||
public bool Enabled { get; private set; }
|
||||
|
||||
static PtcProfiler()
|
||||
public ulong StaticCodeStart { get; set; }
|
||||
public ulong StaticCodeSize { get; set; }
|
||||
|
||||
public PtcProfiler(Ptc ptc)
|
||||
{
|
||||
_ptc = ptc;
|
||||
|
||||
_timer = new System.Timers.Timer((double)SaveInterval * 1000d);
|
||||
_timer.Elapsed += PreSave;
|
||||
|
||||
@ -63,7 +67,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
Enabled = false;
|
||||
}
|
||||
|
||||
internal static void AddEntry(ulong address, ExecutionMode mode, bool highCq)
|
||||
public void AddEntry(ulong address, ExecutionMode mode, bool highCq)
|
||||
{
|
||||
if (IsAddressInStaticCodeRange(address))
|
||||
{
|
||||
@ -76,7 +80,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
internal static void UpdateEntry(ulong address, ExecutionMode mode, bool highCq)
|
||||
public void UpdateEntry(ulong address, ExecutionMode mode, bool highCq)
|
||||
{
|
||||
if (IsAddressInStaticCodeRange(address))
|
||||
{
|
||||
@ -91,12 +95,12 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsAddressInStaticCodeRange(ulong address)
|
||||
public bool IsAddressInStaticCodeRange(ulong address)
|
||||
{
|
||||
return address >= StaticCodeStart && address < StaticCodeStart + StaticCodeSize;
|
||||
}
|
||||
|
||||
internal static ConcurrentQueue<(ulong address, FuncProfile funcProfile)> GetProfiledFuncsToTranslate(TranslatorCache<TranslatedFunction> funcs)
|
||||
public ConcurrentQueue<(ulong address, FuncProfile funcProfile)> GetProfiledFuncsToTranslate(TranslatorCache<TranslatedFunction> funcs)
|
||||
{
|
||||
var profiledFuncsToTranslate = new ConcurrentQueue<(ulong address, FuncProfile funcProfile)>();
|
||||
|
||||
@ -111,18 +115,18 @@ namespace ARMeilleure.Translation.PTC
|
||||
return profiledFuncsToTranslate;
|
||||
}
|
||||
|
||||
internal static void ClearEntries()
|
||||
public void ClearEntries()
|
||||
{
|
||||
ProfiledFuncs.Clear();
|
||||
ProfiledFuncs.TrimExcess();
|
||||
}
|
||||
|
||||
internal static void PreLoad()
|
||||
public void PreLoad()
|
||||
{
|
||||
_lastHash = default;
|
||||
|
||||
string fileNameActual = string.Concat(Ptc.CachePathActual, ".info");
|
||||
string fileNameBackup = string.Concat(Ptc.CachePathBackup, ".info");
|
||||
string fileNameActual = string.Concat(_ptc.CachePathActual, ".info");
|
||||
string fileNameBackup = string.Concat(_ptc.CachePathBackup, ".info");
|
||||
|
||||
FileInfo fileInfoActual = new FileInfo(fileNameActual);
|
||||
FileInfo fileInfoBackup = new FileInfo(fileNameBackup);
|
||||
@ -143,7 +147,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
private static bool Load(string fileName, bool isBackup)
|
||||
private bool Load(string fileName, bool isBackup)
|
||||
{
|
||||
using (FileStream compressedStream = new(fileName, FileMode.Open))
|
||||
using (DeflateStream deflateStream = new(compressedStream, CompressionMode.Decompress, true))
|
||||
@ -228,22 +232,22 @@ namespace ARMeilleure.Translation.PTC
|
||||
return DeserializeDictionary<ulong, FuncProfile>(stream, (stream) => DeserializeStructure<FuncProfile>(stream));
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> GetReadOnlySpan(MemoryStream memoryStream)
|
||||
private ReadOnlySpan<byte> GetReadOnlySpan(MemoryStream memoryStream)
|
||||
{
|
||||
return new(memoryStream.GetBuffer(), (int)memoryStream.Position, (int)memoryStream.Length - (int)memoryStream.Position);
|
||||
}
|
||||
|
||||
private static void InvalidateCompressedStream(FileStream compressedStream)
|
||||
private void InvalidateCompressedStream(FileStream compressedStream)
|
||||
{
|
||||
compressedStream.SetLength(0L);
|
||||
}
|
||||
|
||||
private static void PreSave(object source, System.Timers.ElapsedEventArgs e)
|
||||
private void PreSave(object source, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
_waitEvent.Reset();
|
||||
|
||||
string fileNameActual = string.Concat(Ptc.CachePathActual, ".info");
|
||||
string fileNameBackup = string.Concat(Ptc.CachePathBackup, ".info");
|
||||
string fileNameActual = string.Concat(_ptc.CachePathActual, ".info");
|
||||
string fileNameBackup = string.Concat(_ptc.CachePathBackup, ".info");
|
||||
|
||||
FileInfo fileInfoActual = new FileInfo(fileNameActual);
|
||||
|
||||
@ -257,7 +261,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
_waitEvent.Set();
|
||||
}
|
||||
|
||||
private static void Save(string fileName)
|
||||
private void Save(string fileName)
|
||||
{
|
||||
int profiledFuncsCount;
|
||||
|
||||
@ -329,7 +333,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
private static void Serialize(Stream stream, Dictionary<ulong, FuncProfile> profiledFuncs)
|
||||
private void Serialize(Stream stream, Dictionary<ulong, FuncProfile> profiledFuncs)
|
||||
{
|
||||
SerializeDictionary(stream, profiledFuncs, (stream, structure) => SerializeStructure(stream, structure));
|
||||
}
|
||||
@ -361,7 +365,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 5*/)]
|
||||
internal struct FuncProfile
|
||||
public struct FuncProfile
|
||||
{
|
||||
public ExecutionMode Mode;
|
||||
public bool HighCq;
|
||||
@ -373,10 +377,10 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Start()
|
||||
public void Start()
|
||||
{
|
||||
if (Ptc.State == PtcState.Enabled ||
|
||||
Ptc.State == PtcState.Continuing)
|
||||
if (_ptc.State == PtcState.Enabled ||
|
||||
_ptc.State == PtcState.Continuing)
|
||||
{
|
||||
Enabled = true;
|
||||
|
||||
@ -384,7 +388,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
public void Stop()
|
||||
{
|
||||
Enabled = false;
|
||||
|
||||
@ -394,12 +398,12 @@ namespace ARMeilleure.Translation.PTC
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Wait()
|
||||
public void Wait()
|
||||
{
|
||||
_waitEvent.WaitOne();
|
||||
}
|
||||
|
||||
public static void Dispose()
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
|
@ -140,7 +140,7 @@ namespace ARMeilleure.Translation
|
||||
}
|
||||
}
|
||||
|
||||
Array.Clear(localDefs, 0, localDefs.Length);
|
||||
Array.Clear(localDefs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
@ -44,6 +45,8 @@ namespace ARMeilleure.Translation
|
||||
private readonly IJitMemoryAllocator _allocator;
|
||||
private readonly ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>> _oldFuncs;
|
||||
|
||||
private readonly Ptc _ptc;
|
||||
|
||||
internal TranslatorCache<TranslatedFunction> Functions { get; }
|
||||
internal AddressTable<ulong> FunctionTable { get; }
|
||||
internal EntryTable<uint> CountTable { get; }
|
||||
@ -63,6 +66,8 @@ namespace ARMeilleure.Translation
|
||||
|
||||
_oldFuncs = new ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>>();
|
||||
|
||||
_ptc = new Ptc();
|
||||
|
||||
Queue = new TranslatorQueue();
|
||||
|
||||
JitCache.Initialize(allocator);
|
||||
@ -80,22 +85,37 @@ namespace ARMeilleure.Translation
|
||||
}
|
||||
}
|
||||
|
||||
public IPtcLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled)
|
||||
{
|
||||
_ptc.Initialize(titleIdText, displayVersion, enabled, Memory.Type);
|
||||
return _ptc;
|
||||
}
|
||||
|
||||
public void PrepareCodeRange(ulong address, ulong size)
|
||||
{
|
||||
if (_ptc.Profiler.StaticCodeSize == 0)
|
||||
{
|
||||
_ptc.Profiler.StaticCodeStart = address;
|
||||
_ptc.Profiler.StaticCodeSize = size;
|
||||
}
|
||||
}
|
||||
|
||||
public void Execute(State.ExecutionContext context, ulong address)
|
||||
{
|
||||
if (Interlocked.Increment(ref _threadCount) == 1)
|
||||
{
|
||||
IsReadyForTranslation.WaitOne();
|
||||
|
||||
if (Ptc.State == PtcState.Enabled)
|
||||
if (_ptc.State == PtcState.Enabled)
|
||||
{
|
||||
Debug.Assert(Functions.Count == 0);
|
||||
Ptc.LoadTranslations(this);
|
||||
Ptc.MakeAndSaveTranslations(this);
|
||||
_ptc.LoadTranslations(this);
|
||||
_ptc.MakeAndSaveTranslations(this);
|
||||
}
|
||||
|
||||
PtcProfiler.Start();
|
||||
_ptc.Profiler.Start();
|
||||
|
||||
Ptc.Disable();
|
||||
_ptc.Disable();
|
||||
|
||||
// Simple heuristic, should be user configurable in future. (1 for 4 core/ht or less, 2 for 6 core + ht
|
||||
// etc). All threads are normal priority except from the last, which just fills as much of the last core
|
||||
@ -148,6 +168,12 @@ namespace ARMeilleure.Translation
|
||||
Stubs.Dispose();
|
||||
FunctionTable.Dispose();
|
||||
CountTable.Dispose();
|
||||
|
||||
_ptc.Close();
|
||||
_ptc.Profiler.Stop();
|
||||
|
||||
_ptc.Dispose();
|
||||
_ptc.Profiler.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,9 +215,9 @@ namespace ARMeilleure.Translation
|
||||
func = oldFunc;
|
||||
}
|
||||
|
||||
if (PtcProfiler.Enabled)
|
||||
if (_ptc.Profiler.Enabled)
|
||||
{
|
||||
PtcProfiler.AddEntry(address, mode, highCq: false);
|
||||
_ptc.Profiler.AddEntry(address, mode, highCq: false);
|
||||
}
|
||||
|
||||
RegisterFunction(address, func);
|
||||
@ -217,6 +243,7 @@ namespace ARMeilleure.Translation
|
||||
Stubs,
|
||||
address,
|
||||
highCq,
|
||||
_ptc.State != PtcState.Disabled,
|
||||
mode: Aarch32Mode.User);
|
||||
|
||||
Logger.StartPass(PassName.Decoding);
|
||||
@ -256,13 +283,13 @@ namespace ARMeilleure.Translation
|
||||
options |= CompilerOptions.Relocatable;
|
||||
}
|
||||
|
||||
CompiledFunction compiledFunc = Compiler.Compile(cfg, argTypes, retType, options);
|
||||
CompiledFunction compiledFunc = Compiler.Compile(cfg, argTypes, retType, options, RuntimeInformation.ProcessArchitecture);
|
||||
|
||||
if (context.HasPtc && !singleStep)
|
||||
{
|
||||
Hash128 hash = Ptc.ComputeHash(Memory, address, funcSize);
|
||||
|
||||
Ptc.WriteCompiledFunction(address, funcSize, hash, highCq, compiledFunc);
|
||||
_ptc.WriteCompiledFunction(address, funcSize, hash, highCq, compiledFunc);
|
||||
}
|
||||
|
||||
GuestFunction func = compiledFunc.Map<GuestFunction>();
|
||||
@ -284,9 +311,9 @@ namespace ARMeilleure.Translation
|
||||
return func;
|
||||
});
|
||||
|
||||
if (PtcProfiler.Enabled)
|
||||
if (_ptc.Profiler.Enabled)
|
||||
{
|
||||
PtcProfiler.UpdateEntry(request.Address, request.Mode, highCq: true);
|
||||
_ptc.Profiler.UpdateEntry(request.Address, request.Mode, highCq: true);
|
||||
}
|
||||
|
||||
RegisterFunction(request.Address, func);
|
||||
@ -333,9 +360,14 @@ namespace ARMeilleure.Translation
|
||||
}
|
||||
}
|
||||
|
||||
if (block.Address == context.EntryAddress && !context.HighCq)
|
||||
if (block.Address == context.EntryAddress)
|
||||
{
|
||||
EmitRejitCheck(context, out counter);
|
||||
if (!context.HighCq)
|
||||
{
|
||||
EmitRejitCheck(context, out counter);
|
||||
}
|
||||
|
||||
context.ClearQcFlag();
|
||||
}
|
||||
|
||||
context.CurrBlock = block;
|
||||
@ -360,9 +392,14 @@ namespace ARMeilleure.Translation
|
||||
|
||||
bool isLastOp = opcIndex == block.OpCodes.Count - 1;
|
||||
|
||||
if (isLastOp && block.Branch != null && !block.Branch.Exit && block.Branch.Address <= block.Address)
|
||||
if (isLastOp)
|
||||
{
|
||||
EmitSynchronization(context);
|
||||
context.SyncQcFlag();
|
||||
|
||||
if (block.Branch != null && !block.Branch.Exit && block.Branch.Address <= block.Address)
|
||||
{
|
||||
EmitSynchronization(context);
|
||||
}
|
||||
}
|
||||
|
||||
Operand lblPredicateSkip = default;
|
||||
|
@ -30,10 +30,7 @@ namespace ARMeilleure.Translation
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(null);
|
||||
}
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
return _dispatchStub.Value;
|
||||
}
|
||||
@ -47,10 +44,7 @@ namespace ARMeilleure.Translation
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(null);
|
||||
}
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
return _slowDispatchStub.Value;
|
||||
}
|
||||
@ -64,10 +58,7 @@ namespace ARMeilleure.Translation
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(null);
|
||||
}
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
return _dispatchLoop.Value;
|
||||
}
|
||||
@ -81,7 +72,9 @@ namespace ARMeilleure.Translation
|
||||
/// <exception cref="ArgumentNullException"><paramref name="translator"/> is null</exception>
|
||||
public TranslatorStubs(Translator translator)
|
||||
{
|
||||
_translator = translator ?? throw new ArgumentNullException(nameof(translator));
|
||||
ArgumentNullException.ThrowIfNull(translator);
|
||||
|
||||
_translator = translator;
|
||||
_dispatchStub = new(GenerateDispatchStub, isThreadSafe: true);
|
||||
_dispatchLoop = new(GenerateDispatchLoop, isThreadSafe: true);
|
||||
}
|
||||
@ -178,7 +171,7 @@ namespace ARMeilleure.Translation
|
||||
var retType = OperandType.I64;
|
||||
var argTypes = new[] { OperandType.I64 };
|
||||
|
||||
var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq).Map<GuestFunction>();
|
||||
var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<GuestFunction>();
|
||||
|
||||
return Marshal.GetFunctionPointerForDelegate(func);
|
||||
}
|
||||
@ -204,7 +197,7 @@ namespace ARMeilleure.Translation
|
||||
var retType = OperandType.I64;
|
||||
var argTypes = new[] { OperandType.I64 };
|
||||
|
||||
var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq).Map<GuestFunction>();
|
||||
var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<GuestFunction>();
|
||||
|
||||
return Marshal.GetFunctionPointerForDelegate(func);
|
||||
}
|
||||
@ -242,7 +235,7 @@ namespace ARMeilleure.Translation
|
||||
var retType = OperandType.None;
|
||||
var argTypes = new[] { OperandType.I64, OperandType.I64 };
|
||||
|
||||
return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq).Map<DispatcherFunction>();
|
||||
return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<DispatcherFunction>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
54
Directory.Packages.props
Normal file
54
Directory.Packages.props
Normal file
@ -0,0 +1,54 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Avalonia" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Svg" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="0.10.18" />
|
||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageVersion Include="Concentus" Version="1.1.7" />
|
||||
<PackageVersion Include="Crc32.NET" Version="1.2.0" />
|
||||
<PackageVersion Include="DiscordRichPresence" Version="1.1.3.18" />
|
||||
<PackageVersion Include="DynamicData" Version="7.12.11" />
|
||||
<PackageVersion Include="FluentAvaloniaUI" Version="1.4.5" />
|
||||
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
|
||||
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
|
||||
<PackageVersion Include="jp2masa.Avalonia.Flexbox" Version="0.2.0" />
|
||||
<PackageVersion Include="LibHac" Version="0.17.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
|
||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||
<PackageVersion Include="NUnit" Version="3.13.3" />
|
||||
<PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
|
||||
<PackageVersion Include="OpenTK.Core" Version="4.7.5" />
|
||||
<PackageVersion Include="OpenTK.Graphics" Version="4.7.5" />
|
||||
<PackageVersion Include="OpenTK.OpenAL" Version="4.7.5" />
|
||||
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.7.5" />
|
||||
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build13" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||
<PackageVersion Include="Ryujinx.GtkSharp" Version="3.24.24.59-ryujinx" />
|
||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.26.1-build23" />
|
||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||
<PackageVersion Include="SharpZipLib" Version="1.4.1" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.16.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.16.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.16.0" />
|
||||
<PackageVersion Include="SixLabors.ImageSharp" Version="1.0.4" />
|
||||
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
|
||||
<PackageVersion Include="SPB" Version="0.0.4-build28" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="7.0.0" />
|
||||
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.25.1" />
|
||||
<PackageVersion Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
|
||||
<PackageVersion Include="System.Management" Version="7.0.0" />
|
||||
<PackageVersion Include="System.Net.NameResolution" Version="4.3.0" />
|
||||
<PackageVersion Include="System.Threading.ThreadPool" Version="4.3.0" />
|
||||
<PackageVersion Include="XamlNameReferenceGenerator" Version="1.5.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,11 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTK.OpenAL" Version="4.7.5" />
|
||||
<PackageReference Include="OpenTK.OpenAL" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -15,6 +15,8 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||
{
|
||||
private IHardwareDeviceDriver _realDriver;
|
||||
|
||||
public static bool IsSupported => true;
|
||||
|
||||
public CompatLayerHardwareDeviceDriver(IHardwareDeviceDriver realDevice)
|
||||
{
|
||||
_realDriver = realDevice;
|
||||
@ -51,6 +53,40 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||
};
|
||||
}
|
||||
|
||||
private SampleFormat SelectHardwareSampleFormat(SampleFormat targetSampleFormat)
|
||||
{
|
||||
if (_realDriver.SupportsSampleFormat(targetSampleFormat))
|
||||
{
|
||||
return targetSampleFormat;
|
||||
}
|
||||
|
||||
// Attempt conversion from PCM16.
|
||||
if (targetSampleFormat == SampleFormat.PcmInt16)
|
||||
{
|
||||
// Prefer PCM32 if we need to convert.
|
||||
if (_realDriver.SupportsSampleFormat(SampleFormat.PcmInt32))
|
||||
{
|
||||
return SampleFormat.PcmInt32;
|
||||
}
|
||||
|
||||
// If not supported, PCM float provides the best quality with a cost lower than PCM24.
|
||||
if (_realDriver.SupportsSampleFormat(SampleFormat.PcmFloat))
|
||||
{
|
||||
return SampleFormat.PcmFloat;
|
||||
}
|
||||
|
||||
// TODO: Implement PCM24 conversion.
|
||||
|
||||
// If nothing is truly supported, attempt PCM8 at the cost of loosing quality.
|
||||
if (_realDriver.SupportsSampleFormat(SampleFormat.PcmInt8))
|
||||
{
|
||||
return SampleFormat.PcmInt8;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentException("No valid sample format configuration found!");
|
||||
}
|
||||
|
||||
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount, float volume)
|
||||
{
|
||||
if (channelCount == 0)
|
||||
@ -77,15 +113,26 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
SampleFormat hardwareSampleFormat = SelectHardwareSampleFormat(sampleFormat);
|
||||
uint hardwareChannelCount = SelectHardwareChannelCount(channelCount);
|
||||
|
||||
IHardwareDeviceSession realSession = _realDriver.OpenDeviceSession(direction, memoryManager, sampleFormat, sampleRate, hardwareChannelCount, volume);
|
||||
IHardwareDeviceSession realSession = _realDriver.OpenDeviceSession(direction, memoryManager, hardwareSampleFormat, sampleRate, hardwareChannelCount, volume);
|
||||
|
||||
if (hardwareChannelCount == channelCount)
|
||||
if (hardwareChannelCount == channelCount && hardwareSampleFormat == sampleFormat)
|
||||
{
|
||||
return realSession;
|
||||
}
|
||||
|
||||
if (hardwareSampleFormat != sampleFormat)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Audio, $"{sampleFormat} isn't supported by the audio device, conversion to {hardwareSampleFormat} will happen.");
|
||||
|
||||
if (hardwareSampleFormat < sampleFormat)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Audio, $"{hardwareSampleFormat} has lower quality than {sampleFormat}, expect some loss in audio fidelity.");
|
||||
}
|
||||
}
|
||||
|
||||
if (direction == Direction.Input)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Audio, $"The selected audio backend doesn't support the requested audio input configuration, fallback to dummy...");
|
||||
@ -103,7 +150,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||
}
|
||||
|
||||
// If we need to do post processing before sending to the hardware device, wrap around it.
|
||||
return new CompatLayerHardwareDeviceSession(realSessionOutputBase, channelCount);
|
||||
return new CompatLayerHardwareDeviceSession(realSessionOutputBase, sampleFormat, channelCount);
|
||||
}
|
||||
|
||||
public bool SupportsChannelCount(uint channelCount)
|
||||
|
@ -1,5 +1,6 @@
|
||||
using Ryujinx.Audio.Backends.Common;
|
||||
using Ryujinx.Audio.Common;
|
||||
using Ryujinx.Audio.Renderer.Dsp;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
@ -8,11 +9,13 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||
class CompatLayerHardwareDeviceSession : HardwareDeviceSessionOutputBase
|
||||
{
|
||||
private HardwareDeviceSessionOutputBase _realSession;
|
||||
private SampleFormat _userSampleFormat;
|
||||
private uint _userChannelCount;
|
||||
|
||||
public CompatLayerHardwareDeviceSession(HardwareDeviceSessionOutputBase realSession, uint userChannelCount) : base(realSession.MemoryManager, realSession.RequestedSampleFormat, realSession.RequestedSampleRate, userChannelCount)
|
||||
public CompatLayerHardwareDeviceSession(HardwareDeviceSessionOutputBase realSession, SampleFormat userSampleFormat, uint userChannelCount) : base(realSession.MemoryManager, realSession.RequestedSampleFormat, realSession.RequestedSampleRate, userChannelCount)
|
||||
{
|
||||
_realSession = realSession;
|
||||
_userSampleFormat = userSampleFormat;
|
||||
_userChannelCount = userChannelCount;
|
||||
}
|
||||
|
||||
@ -38,53 +41,86 @@ namespace Ryujinx.Audio.Backends.CompatLayer
|
||||
|
||||
public override void QueueBuffer(AudioBuffer buffer)
|
||||
{
|
||||
SampleFormat realSampleFormat = _realSession.RequestedSampleFormat;
|
||||
|
||||
if (_userSampleFormat != realSampleFormat)
|
||||
{
|
||||
if (_userSampleFormat != SampleFormat.PcmInt16)
|
||||
{
|
||||
throw new NotImplementedException("Converting formats other than PCM16 is not supported.");
|
||||
}
|
||||
|
||||
int userSampleCount = buffer.Data.Length / BackendHelper.GetSampleSize(_userSampleFormat);
|
||||
|
||||
ReadOnlySpan<short> samples = MemoryMarshal.Cast<byte, short>(buffer.Data);
|
||||
byte[] convertedSamples = new byte[BackendHelper.GetSampleSize(realSampleFormat) * userSampleCount];
|
||||
|
||||
switch (realSampleFormat)
|
||||
{
|
||||
case SampleFormat.PcmInt8:
|
||||
PcmHelper.Convert(MemoryMarshal.Cast<byte, sbyte>(convertedSamples), samples);
|
||||
break;
|
||||
case SampleFormat.PcmInt32:
|
||||
PcmHelper.Convert(MemoryMarshal.Cast<byte, int>(convertedSamples), samples);
|
||||
break;
|
||||
case SampleFormat.PcmFloat:
|
||||
PcmHelper.ConvertSampleToPcmFloat(MemoryMarshal.Cast<byte, float>(convertedSamples), samples);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException($"Sample format conversion from {_userSampleFormat} to {realSampleFormat} not implemented.");
|
||||
}
|
||||
|
||||
buffer.Data = convertedSamples;
|
||||
}
|
||||
|
||||
_realSession.QueueBuffer(buffer);
|
||||
}
|
||||
|
||||
public override bool RegisterBuffer(AudioBuffer buffer, byte[] samples)
|
||||
{
|
||||
if (RequestedSampleFormat != SampleFormat.PcmInt16)
|
||||
{
|
||||
throw new NotImplementedException("Downmixing formats other than PCM16 is not supported.");
|
||||
}
|
||||
|
||||
if (samples == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
short[] downmixedBufferPCM16;
|
||||
|
||||
ReadOnlySpan<short> samplesPCM16 = MemoryMarshal.Cast<byte, short>(samples);
|
||||
|
||||
if (_userChannelCount == 6)
|
||||
if (_userChannelCount != _realSession.RequestedChannelCount)
|
||||
{
|
||||
downmixedBufferPCM16 = Downmixing.DownMixSurroundToStereo(samplesPCM16);
|
||||
|
||||
if (_realSession.RequestedChannelCount == 1)
|
||||
if (_userSampleFormat != SampleFormat.PcmInt16)
|
||||
{
|
||||
downmixedBufferPCM16 = Downmixing.DownMixStereoToMono(downmixedBufferPCM16);
|
||||
throw new NotImplementedException("Downmixing formats other than PCM16 is not supported.");
|
||||
}
|
||||
}
|
||||
else if (_userChannelCount == 2 && _realSession.RequestedChannelCount == 1)
|
||||
{
|
||||
downmixedBufferPCM16 = Downmixing.DownMixStereoToMono(samplesPCM16);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException($"Downmixing from {_userChannelCount} to {_realSession.RequestedChannelCount} not implemented.");
|
||||
}
|
||||
|
||||
byte[] downmixedBuffer = MemoryMarshal.Cast<short, byte>(downmixedBufferPCM16).ToArray();
|
||||
ReadOnlySpan<short> samplesPCM16 = MemoryMarshal.Cast<byte, short>(samples);
|
||||
|
||||
if (_userChannelCount == 6)
|
||||
{
|
||||
samplesPCM16 = Downmixing.DownMixSurroundToStereo(samplesPCM16);
|
||||
|
||||
if (_realSession.RequestedChannelCount == 1)
|
||||
{
|
||||
samplesPCM16 = Downmixing.DownMixStereoToMono(samplesPCM16);
|
||||
}
|
||||
}
|
||||
else if (_userChannelCount == 2 && _realSession.RequestedChannelCount == 1)
|
||||
{
|
||||
samplesPCM16 = Downmixing.DownMixStereoToMono(samplesPCM16);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException($"Downmixing from {_userChannelCount} to {_realSession.RequestedChannelCount} not implemented.");
|
||||
}
|
||||
|
||||
samples = MemoryMarshal.Cast<short, byte>(samplesPCM16).ToArray();
|
||||
}
|
||||
|
||||
AudioBuffer fakeBuffer = new AudioBuffer
|
||||
{
|
||||
BufferTag = buffer.BufferTag,
|
||||
DataPointer = buffer.DataPointer,
|
||||
DataSize = (ulong)downmixedBuffer.Length
|
||||
DataSize = (ulong)samples.Length
|
||||
};
|
||||
|
||||
bool result = _realSession.RegisterBuffer(fakeBuffer, downmixedBuffer);
|
||||
bool result = _realSession.RegisterBuffer(fakeBuffer, samples);
|
||||
|
||||
if (result)
|
||||
{
|
||||
|
@ -12,6 +12,8 @@ namespace Ryujinx.Audio.Backends.Dummy
|
||||
private ManualResetEvent _updateRequiredEvent;
|
||||
private ManualResetEvent _pauseEvent;
|
||||
|
||||
public static bool IsSupported => true;
|
||||
|
||||
public DummyHardwareDeviceDriver()
|
||||
{
|
||||
_updateRequiredEvent = new ManualResetEvent(false);
|
||||
|
@ -26,6 +26,8 @@ namespace Ryujinx.Audio.Integration
|
||||
bool SupportsSampleFormat(SampleFormat sampleFormat);
|
||||
bool SupportsChannelCount(uint channelCount);
|
||||
|
||||
static abstract bool IsSupported { get; }
|
||||
|
||||
IHardwareDeviceDriver GetRealDeviceDriver()
|
||||
{
|
||||
return this;
|
||||
|
@ -23,7 +23,7 @@ namespace Ryujinx.Audio.Renderer.Common
|
||||
|
||||
if (size != 0)
|
||||
{
|
||||
ulong alignedOffset = BitUtils.AlignUp(Offset, align);
|
||||
ulong alignedOffset = BitUtils.AlignUp<ulong>(Offset, (ulong)align);
|
||||
|
||||
if (alignedOffset + size <= (ulong)BackingMemory.Length)
|
||||
{
|
||||
@ -55,7 +55,7 @@ namespace Ryujinx.Audio.Renderer.Common
|
||||
|
||||
public static ulong GetTargetSize<T>(ulong currentSize, ulong count, int align) where T : unmanaged
|
||||
{
|
||||
return BitUtils.AlignUp(currentSize, align) + (ulong)Unsafe.SizeOf<T>() * count;
|
||||
return BitUtils.AlignUp<ulong>(currentSize, (ulong)align) + (ulong)Unsafe.SizeOf<T>() * count;
|
||||
}
|
||||
}
|
||||
}
|
@ -40,6 +40,12 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
info.InputBufferIndices[i] = (ushort)(bufferOffset + inputBufferOffset[i]);
|
||||
}
|
||||
|
||||
if (info.BufferStates?.Length != (int)inputCount)
|
||||
{
|
||||
// Keep state if possible.
|
||||
info.BufferStates = new UpsamplerBufferState[(int)inputCount];
|
||||
}
|
||||
|
||||
UpsamplerInfo = info;
|
||||
}
|
||||
|
||||
@ -50,8 +56,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
|
||||
public void Process(CommandList context)
|
||||
{
|
||||
float ratio = (float)InputSampleRate / Constants.TargetSampleRate;
|
||||
|
||||
uint bufferCount = Math.Min(BufferCount, UpsamplerInfo.SourceSampleCount);
|
||||
|
||||
for (int i = 0; i < bufferCount; i++)
|
||||
@ -59,9 +63,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
||||
Span<float> inputBuffer = context.GetBuffer(UpsamplerInfo.InputBufferIndices[i]);
|
||||
Span<float> outputBuffer = GetBuffer(UpsamplerInfo.InputBufferIndices[i], (int)UpsamplerInfo.SampleCount);
|
||||
|
||||
float fraction = 0.0f;
|
||||
|
||||
ResamplerHelper.ResampleForUpsampler(outputBuffer, inputBuffer, ratio, ref fraction, (int)(InputSampleCount / ratio));
|
||||
UpsamplerHelper.Upsample(outputBuffer, inputBuffer, (int)UpsamplerInfo.SampleCount, (int)InputSampleCount, ref UpsamplerInfo.BufferStates[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp
|
||||
@ -23,6 +24,44 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
return GetCountToDecode(startSampleOffset, endSampleOffset, offset, count) * Unsafe.SizeOf<T>();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float ConvertSampleToPcmFloat(short sample)
|
||||
{
|
||||
return (float)sample / short.MaxValue;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static short ConvertSampleToPcmInt16(float sample)
|
||||
{
|
||||
return Saturate(sample * short.MaxValue);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static TOutput ConvertSample<TInput, TOutput>(TInput value) where TInput: INumber<TInput>, IMinMaxValue<TInput> where TOutput : INumber<TOutput>, IMinMaxValue<TOutput>
|
||||
{
|
||||
TInput conversionRate = TInput.CreateSaturating(TOutput.MaxValue / TOutput.CreateSaturating(TInput.MaxValue));
|
||||
|
||||
return TOutput.CreateSaturating(value * conversionRate);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Convert<TInput, TOutput>(Span<TOutput> output, ReadOnlySpan<TInput> input) where TInput : INumber<TInput>, IMinMaxValue<TInput> where TOutput : INumber<TOutput>, IMinMaxValue<TOutput>
|
||||
{
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
{
|
||||
output[i] = ConvertSample<TInput, TOutput>(input[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void ConvertSampleToPcmFloat(Span<float> output, ReadOnlySpan<short> input)
|
||||
{
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
{
|
||||
output[i] = ConvertSampleToPcmFloat(input[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int Decode(Span<short> output, ReadOnlySpan<short> input, int startSampleOffset, int endSampleOffset, int channelIndex, int channelCount)
|
||||
{
|
||||
@ -53,7 +92,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
|
||||
for (int i = 0; i < decodedCount; i++)
|
||||
{
|
||||
output[i] = (short)(input[i * channelCount + channelIndex] * short.MaxValue);
|
||||
output[i] = ConvertSampleToPcmInt16(input[i * channelCount + channelIndex]);
|
||||
}
|
||||
|
||||
return decodedCount;
|
||||
|
@ -579,52 +579,5 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
||||
fraction -= (int)fraction;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void ResampleForUpsampler(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, float ratio, ref float fraction, int sampleCount)
|
||||
{
|
||||
// Currently a simple cubic interpolation, assuming duplicated values at edges.
|
||||
// TODO: Discover and use algorithm that the switch uses.
|
||||
|
||||
int inputBufferIndex = 0;
|
||||
int maxIndex = inputBuffer.Length - 1;
|
||||
int cubicEnd = inputBuffer.Length - 3;
|
||||
|
||||
for (int i = 0; i < sampleCount; i++)
|
||||
{
|
||||
float s0, s1, s2, s3;
|
||||
|
||||
s1 = inputBuffer[inputBufferIndex];
|
||||
|
||||
if (inputBufferIndex == 0 || inputBufferIndex > cubicEnd)
|
||||
{
|
||||
// Clamp interplation values at the ends of the input buffer.
|
||||
s0 = inputBuffer[Math.Max(0, inputBufferIndex - 1)];
|
||||
s2 = inputBuffer[Math.Min(maxIndex, inputBufferIndex + 1)];
|
||||
s3 = inputBuffer[Math.Min(maxIndex, inputBufferIndex + 2)];
|
||||
}
|
||||
else
|
||||
{
|
||||
s0 = inputBuffer[inputBufferIndex - 1];
|
||||
s2 = inputBuffer[inputBufferIndex + 1];
|
||||
s3 = inputBuffer[inputBufferIndex + 2];
|
||||
}
|
||||
|
||||
float a = s3 - s2 - s0 + s1;
|
||||
float b = s0 - s1 - a;
|
||||
float c = s2 - s0;
|
||||
float d = s1;
|
||||
|
||||
float f2 = fraction * fraction;
|
||||
float f3 = f2 * fraction;
|
||||
|
||||
outputBuffer[i] = a * f3 + b * f2 + c * fraction + d;
|
||||
|
||||
fraction += ratio;
|
||||
inputBufferIndex += (int)MathF.Truncate(fraction);
|
||||
|
||||
fraction -= (int)fraction;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
175
Ryujinx.Audio/Renderer/Dsp/UpsamplerHelper.cs
Normal file
175
Ryujinx.Audio/Renderer/Dsp/UpsamplerHelper.cs
Normal file
@ -0,0 +1,175 @@
|
||||
using Ryujinx.Audio.Renderer.Server.Upsampler;
|
||||
using Ryujinx.Common.Memory;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Dsp
|
||||
{
|
||||
public class UpsamplerHelper
|
||||
{
|
||||
private const int HistoryLength = UpsamplerBufferState.HistoryLength;
|
||||
private const int FilterBankLength = 20;
|
||||
// Bank0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
private const int Bank0CenterIndex = 9;
|
||||
private static readonly Array20<float> Bank1 = PrecomputeFilterBank(1.0f / 6.0f);
|
||||
private static readonly Array20<float> Bank2 = PrecomputeFilterBank(2.0f / 6.0f);
|
||||
private static readonly Array20<float> Bank3 = PrecomputeFilterBank(3.0f / 6.0f);
|
||||
private static readonly Array20<float> Bank4 = PrecomputeFilterBank(4.0f / 6.0f);
|
||||
private static readonly Array20<float> Bank5 = PrecomputeFilterBank(5.0f / 6.0f);
|
||||
|
||||
private static Array20<float> PrecomputeFilterBank(float offset)
|
||||
{
|
||||
float Sinc(float x)
|
||||
{
|
||||
if (x == 0)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
return (MathF.Sin(MathF.PI * x) / (MathF.PI * x));
|
||||
}
|
||||
|
||||
float BlackmanWindow(float x)
|
||||
{
|
||||
const float a = 0.18f;
|
||||
const float a0 = 0.5f - 0.5f * a;
|
||||
const float a1 = -0.5f;
|
||||
const float a2 = 0.5f * a;
|
||||
return a0 + a1 * MathF.Cos(2 * MathF.PI * x) + a2 * MathF.Cos(4 * MathF.PI * x);
|
||||
}
|
||||
|
||||
Array20<float> result = new Array20<float>();
|
||||
|
||||
for (int i = 0; i < FilterBankLength; i++)
|
||||
{
|
||||
float x = (Bank0CenterIndex - i) + offset;
|
||||
result[i] = Sinc(x) * BlackmanWindow(x / FilterBankLength + 0.5f);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Polyphase upsampling algorithm
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Upsample(Span<float> outputBuffer, ReadOnlySpan<float> inputBuffer, int outputSampleCount, int inputSampleCount, ref UpsamplerBufferState state)
|
||||
{
|
||||
if (!state.Initialized)
|
||||
{
|
||||
state.Scale = inputSampleCount switch
|
||||
{
|
||||
40 => 6.0f,
|
||||
80 => 3.0f,
|
||||
160 => 1.5f,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
state.Initialized = true;
|
||||
}
|
||||
|
||||
if (outputSampleCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
float DoFilterBank(ref UpsamplerBufferState state, in Array20<float> bank)
|
||||
{
|
||||
float result = 0.0f;
|
||||
|
||||
Debug.Assert(state.History.Length == HistoryLength);
|
||||
Debug.Assert(bank.Length == FilterBankLength);
|
||||
for (int j = 0; j < FilterBankLength; j++)
|
||||
{
|
||||
result += bank[j] * state.History[j];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void NextInput(ref UpsamplerBufferState state, float input)
|
||||
{
|
||||
state.History.AsSpan().Slice(1).CopyTo(state.History.AsSpan());
|
||||
state.History[HistoryLength - 1] = input;
|
||||
}
|
||||
|
||||
int inputBufferIndex = 0;
|
||||
|
||||
switch (state.Scale)
|
||||
{
|
||||
case 6.0f:
|
||||
for (int i = 0; i < outputSampleCount; i++)
|
||||
{
|
||||
switch (state.Phase)
|
||||
{
|
||||
case 0:
|
||||
NextInput(ref state, inputBuffer[inputBufferIndex++]);
|
||||
outputBuffer[i] = state.History[Bank0CenterIndex];
|
||||
break;
|
||||
case 1:
|
||||
outputBuffer[i] = DoFilterBank(ref state, Bank1);
|
||||
break;
|
||||
case 2:
|
||||
outputBuffer[i] = DoFilterBank(ref state, Bank2);
|
||||
break;
|
||||
case 3:
|
||||
outputBuffer[i] = DoFilterBank(ref state, Bank3);
|
||||
break;
|
||||
case 4:
|
||||
outputBuffer[i] = DoFilterBank(ref state, Bank4);
|
||||
break;
|
||||
case 5:
|
||||
outputBuffer[i] = DoFilterBank(ref state, Bank5);
|
||||
break;
|
||||
}
|
||||
|
||||
state.Phase = (state.Phase + 1) % 6;
|
||||
}
|
||||
break;
|
||||
case 3.0f:
|
||||
for (int i = 0; i < outputSampleCount; i++)
|
||||
{
|
||||
switch (state.Phase)
|
||||
{
|
||||
case 0:
|
||||
NextInput(ref state, inputBuffer[inputBufferIndex++]);
|
||||
outputBuffer[i] = state.History[Bank0CenterIndex];
|
||||
break;
|
||||
case 1:
|
||||
outputBuffer[i] = DoFilterBank(ref state, Bank2);
|
||||
break;
|
||||
case 2:
|
||||
outputBuffer[i] = DoFilterBank(ref state, Bank4);
|
||||
break;
|
||||
}
|
||||
|
||||
state.Phase = (state.Phase + 1) % 3;
|
||||
}
|
||||
break;
|
||||
case 1.5f:
|
||||
// Upsample by 3 then decimate by 2.
|
||||
for (int i = 0; i < outputSampleCount; i++)
|
||||
{
|
||||
switch (state.Phase)
|
||||
{
|
||||
case 0:
|
||||
NextInput(ref state, inputBuffer[inputBufferIndex++]);
|
||||
outputBuffer[i] = state.History[Bank0CenterIndex];
|
||||
break;
|
||||
case 1:
|
||||
outputBuffer[i] = DoFilterBank(ref state, Bank4);
|
||||
break;
|
||||
case 2:
|
||||
NextInput(ref state, inputBuffer[inputBufferIndex++]);
|
||||
outputBuffer[i] = DoFilterBank(ref state, Bank2);
|
||||
break;
|
||||
}
|
||||
|
||||
state.Phase = (state.Phase + 1) % 3;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -167,7 +167,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
return ResultCode.WorkBufferTooSmall;
|
||||
}
|
||||
|
||||
_depopBuffer = workBufferAllocator.Allocate<float>((ulong)BitUtils.AlignUp(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment);
|
||||
_depopBuffer = workBufferAllocator.Allocate<float>(BitUtils.AlignUp<ulong>(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment);
|
||||
|
||||
if (_depopBuffer.IsEmpty)
|
||||
{
|
||||
@ -772,7 +772,7 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
size = WorkBufferAllocator.GetTargetSize<float>(size, Constants.TargetSampleCount * (Constants.VoiceChannelCountMax + parameter.MixBufferCount) * (parameter.SinkCount + parameter.SubMixBufferCount), 0x10);
|
||||
|
||||
// Depop buffer
|
||||
size = WorkBufferAllocator.GetTargetSize<float>(size, (ulong)BitUtils.AlignUp(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment);
|
||||
size = WorkBufferAllocator.GetTargetSize<float>(size, BitUtils.AlignUp<ulong>(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment);
|
||||
|
||||
// Voice
|
||||
size = WorkBufferAllocator.GetTargetSize<VoiceState>(size, parameter.VoiceCount, VoiceState.Alignment);
|
||||
@ -804,10 +804,10 @@ namespace Ryujinx.Audio.Renderer.Server
|
||||
{
|
||||
ulong performanceMetricsPerFramesSize = PerformanceManager.GetRequiredBufferSizeForPerformanceMetricsPerFrame(ref parameter, ref behaviourContext) * (parameter.PerformanceMetricFramesCount + 1) + 0xC;
|
||||
|
||||
size += BitUtils.AlignUp(performanceMetricsPerFramesSize, Constants.PerformanceMetricsPerFramesSizeAlignment);
|
||||
size += BitUtils.AlignUp<ulong>(performanceMetricsPerFramesSize, Constants.PerformanceMetricsPerFramesSizeAlignment);
|
||||
}
|
||||
|
||||
return BitUtils.AlignUp(size, Constants.WorkBufferAlignment);
|
||||
return BitUtils.AlignUp<ulong>(size, Constants.WorkBufferAlignment);
|
||||
}
|
||||
|
||||
public ResultCode QuerySystemEvent(out IWritableEvent systemEvent)
|
||||
|
@ -0,0 +1,14 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
|
||||
namespace Ryujinx.Audio.Renderer.Server.Upsampler
|
||||
{
|
||||
public struct UpsamplerBufferState
|
||||
{
|
||||
public const int HistoryLength = 20;
|
||||
|
||||
public float Scale;
|
||||
public Array20<float> History;
|
||||
public bool Initialized;
|
||||
public int Phase;
|
||||
}
|
||||
}
|
@ -37,6 +37,11 @@ namespace Ryujinx.Audio.Renderer.Server.Upsampler
|
||||
/// </summary>
|
||||
public ushort[] InputBufferIndices;
|
||||
|
||||
/// <summary>
|
||||
/// State of each input buffer index kept across invocations of the upsampler.
|
||||
/// </summary>
|
||||
public UpsamplerBufferState[] BufferStates;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="UpsamplerState"/>.
|
||||
/// </summary>
|
||||
|
@ -4,6 +4,6 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:sty="using:FluentAvalonia.Styling">
|
||||
<Application.Styles>
|
||||
<sty:FluentAvaloniaTheme UseSystemThemeOnWindows="False" />
|
||||
<sty:FluentAvaloniaTheme PreferSystemTheme="False" />
|
||||
</Application.Styles>
|
||||
</Application>
|
@ -5,8 +5,9 @@ using Avalonia.Styling;
|
||||
using Avalonia.Threading;
|
||||
using FluentAvalonia.Styling;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Ui.Controls;
|
||||
using Ryujinx.Ava.Ui.Windows;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Ui.Common.Configuration;
|
||||
@ -58,11 +59,11 @@ namespace Ryujinx.Ava
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
var result = await ContentDialogHelper.CreateConfirmationDialog(
|
||||
LocaleManager.Instance["DialogThemeRestartMessage"],
|
||||
LocaleManager.Instance["DialogThemeRestartSubMessage"],
|
||||
LocaleManager.Instance["InputDialogYes"],
|
||||
LocaleManager.Instance["InputDialogNo"],
|
||||
LocaleManager.Instance["DialogRestartRequiredMessage"]);
|
||||
LocaleManager.Instance[LocaleKeys.DialogThemeRestartMessage],
|
||||
LocaleManager.Instance[LocaleKeys.DialogThemeRestartSubMessage],
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogYes],
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogNo],
|
||||
LocaleManager.Instance[LocaleKeys.DialogRestartRequiredMessage]);
|
||||
|
||||
if (result == UserResult.Yes)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,5 @@
|
||||
{
|
||||
"Language": "Deutsch",
|
||||
"MenuBarFileOpenApplet": "Applet öffnen",
|
||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Öffnet das Mii Editor Applet im Standalone Modus",
|
||||
"SettingsTabInputDirectMouseAccess": "Direkter Mauszugriff",
|
||||
@ -41,10 +42,10 @@
|
||||
"GameListHeaderPath": "Pfad",
|
||||
"GameListContextMenuOpenUserSaveDirectory": "Spielstand-Verzeichnis öffnen",
|
||||
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Öffnet das Verzeichnis, welches den Benutzer-Spielstand beinhaltet",
|
||||
"GameListContextMenuOpenUserDeviceDirectory": "Benutzer-Geräte-Verzeichnis öffnen",
|
||||
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Öffnet das Verzeichnis, welches den Geräte-Spielstände beinhaltet",
|
||||
"GameListContextMenuOpenUserBcatDirectory": "Benutzer-BCAT-Vezeichnis öffnen",
|
||||
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Öffnet das Verzeichnis, welches den BCAT Cache des Spiels beinhaltet",
|
||||
"GameListContextMenuOpenDeviceSaveDirectory": "Benutzer-Geräte-Verzeichnis öffnen",
|
||||
"GameListContextMenuOpenDeviceSaveDirectoryToolTip": "Öffnet das Verzeichnis, welches den Geräte-Spielstände beinhaltet",
|
||||
"GameListContextMenuOpenBcatSaveDirectory": "Benutzer-BCAT-Vezeichnis öffnen",
|
||||
"GameListContextMenuOpenBcatSaveDirectoryToolTip": "Öffnet das Verzeichnis, welches den BCAT Cache des Spiels beinhaltet",
|
||||
"GameListContextMenuManageTitleUpdates": "Verwalten von Spiel Updates",
|
||||
"GameListContextMenuManageTitleUpdatesToolTip": "Öffnet den Spiel-Update-Manager",
|
||||
"GameListContextMenuManageDlc": "Verwalten von DLC",
|
||||
@ -81,7 +82,7 @@
|
||||
"SettingsTabGeneralRemove": "Entfernen",
|
||||
"SettingsTabSystem": "System",
|
||||
"SettingsTabSystemCore": "Kern",
|
||||
"SettingsTabSystemSystemRegion": "System Region:",
|
||||
"SettingsTabSystemSystemRegion": "Systemregion:",
|
||||
"SettingsTabSystemSystemRegionJapan": "Japan",
|
||||
"SettingsTabSystemSystemRegionUSA": "USA",
|
||||
"SettingsTabSystemSystemRegionEurope": "Europa",
|
||||
@ -113,7 +114,7 @@
|
||||
"SettingsTabSystemEnablePptc": "PPTC Cache (Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "FS Integritätsprüfung",
|
||||
"SettingsTabSystemAudioBackend": "Audio-Backend:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Dummy",
|
||||
"SettingsTabSystemAudioBackendDummy": "Ohne Funktion",
|
||||
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
|
||||
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
|
||||
"SettingsTabSystemAudioBackendSDL2": "SDL2",
|
||||
@ -157,6 +158,7 @@
|
||||
"SettingsTabLoggingEnableFsAccessLogs": "Aktiviere Fs Zugriff-Logs",
|
||||
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs Globaler Zugriff-Log-Modus:",
|
||||
"SettingsTabLoggingDeveloperOptions": "Entwickleroptionen (WARNUNG: Beeinträchtigt die Leistung)",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevel": "Graphics Backend Log Level:",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Keine",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelError": "Fehler",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Verlangsamungen",
|
||||
@ -190,7 +192,7 @@
|
||||
"ControllerSettingsControllerTypeJoyConLeft": "Joy-Con Links",
|
||||
"ControllerSettingsControllerTypeJoyConRight": "Joy-Con Rechts",
|
||||
"ControllerSettingsProfile": "Profil",
|
||||
"ControllerSettingsProfileDefault": "Default",
|
||||
"ControllerSettingsProfileDefault": "Standard",
|
||||
"ControllerSettingsLoad": "Laden",
|
||||
"ControllerSettingsAdd": "Hinzufügen",
|
||||
"ControllerSettingsRemove": "Entfernen",
|
||||
@ -230,7 +232,7 @@
|
||||
"ControllerSettingsTriggersRight": "Rechter Trigger",
|
||||
"ControllerSettingsTriggersButtonsLeft": "Linke Schultertaste",
|
||||
"ControllerSettingsTriggersButtonsRight": "Rechte Schultertaste",
|
||||
"ControllerSettingsTriggers": "Triggers",
|
||||
"ControllerSettingsTriggers": "Trigger",
|
||||
"ControllerSettingsTriggerL": "L",
|
||||
"ControllerSettingsTriggerR": "R",
|
||||
"ControllerSettingsTriggerZL": "ZL",
|
||||
@ -245,7 +247,7 @@
|
||||
"ControllerSettingsTriggerThreshold": "Empfindlichkeit:",
|
||||
"ControllerSettingsMotion": "Bewegung",
|
||||
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "CemuHook kompatible Bewegungssteuerung",
|
||||
"ControllerSettingsMotionControllerSlot": "Controller Slot:",
|
||||
"ControllerSettingsMotionControllerSlot": "Kontroller Slot:",
|
||||
"ControllerSettingsMotionMirrorInput": "Spiegele Eingabe",
|
||||
"ControllerSettingsMotionRightJoyConSlot": "Rechter Joy-Con Slot:",
|
||||
"ControllerSettingsMotionServerHost": "Server Host:",
|
||||
@ -258,7 +260,7 @@
|
||||
"UserProfilesChangeProfileImage": "Profilbild ändern",
|
||||
"UserProfilesAvailableUserProfiles": "Verfügbare Profile:",
|
||||
"UserProfilesAddNewProfile": "Neues Profil",
|
||||
"UserProfilesDeleteSelectedProfile": "Profil löschen",
|
||||
"UserProfilesDelete": "Löschen",
|
||||
"UserProfilesClose": "Schließen",
|
||||
"ProfileImageSelectionTitle": "Auswahl des Profilbildes",
|
||||
"ProfileImageSelectionHeader": "Wähle ein Profilbild aus",
|
||||
@ -279,7 +281,7 @@
|
||||
"ControllerSettingsRemoveProfileToolTip": "Entfernt ein Profil",
|
||||
"ControllerSettingsSaveProfileToolTip": "Speichert ein Profil",
|
||||
"MenuBarFileToolsTakeScreenshot": "Screenshot aufnehmen",
|
||||
"MenuBarFileToolsHideUi": "Verstecke UI",
|
||||
"MenuBarFileToolsHideUi": "Hide UI",
|
||||
"GameListContextMenuToggleFavorite": "Als Favoriten hinzufügen/entfernen",
|
||||
"GameListContextMenuToggleFavoriteToolTip": "Aktiviert den Favoriten-Status des Spiels",
|
||||
"SettingsTabGeneralTheme": "Design",
|
||||
@ -314,8 +316,8 @@
|
||||
"DialogUpdaterConvertFailedMessage": "Die Konvertierung der aktuellen Ryujinx Version ist fehlgeschlagen.",
|
||||
"DialogUpdaterCancelUpdateMessage": "Download wird abgebrochen!",
|
||||
"DialogUpdaterAlreadyOnLatestVersionMessage": "Es wird bereits die aktuellste Version von Ryujinx benutzt",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "Bei dem Versuch Versionsinformationen von AppVeyor zu erhalten, ist ein Fehler aufgetreten ",
|
||||
"DialogUpdaterConvertFailedAppveyorMessage": "Die von AppVeyor erhaltene Ryujinx Version konnte nicht konvertiert werden.",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "An error has occurred when trying to get release information from GitHub Release. This can be caused if a new release is being compiled by GitHub Actions. Try again in a few minutes.",
|
||||
"DialogUpdaterConvertFailedGithubMessage": "Failed to convert the received Ryujinx version from Github Release.",
|
||||
"DialogUpdaterDownloadingMessage": "Update wird Heruntergeladen...",
|
||||
"DialogUpdaterExtractionMessage": "Update wird entpackt...",
|
||||
"DialogUpdaterRenamingMessage": "Update wird umbenannt...",
|
||||
@ -411,6 +413,8 @@
|
||||
"DlcManagerTableHeadingContainerPathLabel": "Container-Pfad",
|
||||
"DlcManagerTableHeadingFullPathLabel": "Vollständiger-Pfad",
|
||||
"DlcManagerRemoveAllButton": "Entferne alle",
|
||||
"DlcManagerEnableAllButton": "Alle aktivieren",
|
||||
"DlcManagerDisableAllButton": "Alle deaktivieren",
|
||||
"MenuBarOptionsChangeLanguage": "Sprache ändern",
|
||||
"CommonSort": "Sortieren",
|
||||
"CommonShowNames": "Spiel-Namen anzeigen",
|
||||
@ -455,8 +459,8 @@
|
||||
"StubLogTooltip": "Ausgabe von Stub-Logs in der Konsole. Hat keinen Einfluss auf die Leistung.",
|
||||
"InfoLogTooltip": "Ausgabe von Info-Logs in der Konsole. Hat keinen Einfluss auf die Leistung.",
|
||||
"WarnLogTooltip": "Ausgabe von Warn-Logs in der Konsole. Hat keinen Einfluss auf die Leistung.",
|
||||
"TraceLogTooltip": "Ausgabe von Trace-Log in der Konsole. Hat keinen Einfluss auf die Leistung.",
|
||||
"ErrorLogTooltip": "Ausgabe von Fehler-Logs in der Konsole. Hat keinen Einfluss auf die Leistung.",
|
||||
"TraceLogTooltip": "Ausgabe von Trace-Log in der Konsole. Hat keinen Einfluss auf die Leistung.",
|
||||
"GuestLogTooltip": "Ausgabe von Gast-Logs in der Konsole. Hat keinen Einfluss auf die Leistung.",
|
||||
"FileAccessLogTooltip": "Ausgabe von FS-Zugriff-Logs in der Konsole.",
|
||||
"FSAccessLogModeTooltip": "Aktiviert die Ausgabe des FS-Zugriff-Logs in der Konsole. Mögliche Modi sind 0-3",
|
||||
@ -477,7 +481,7 @@
|
||||
"GridSizeTooltip": "Ändert die Größe der Rasterelemente",
|
||||
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "Brasilianisches Portugiesisch",
|
||||
"AboutRyujinxContributorsButtonHeader": "Alle Mitwirkenden anzeigen",
|
||||
"SettingsTabSystemAudioVolume" : "Lautstärke: ",
|
||||
"SettingsTabSystemAudioVolume": "Lautstärke: ",
|
||||
"AudioVolumeTooltip": "Ändert die Lautstärke",
|
||||
"SettingsTabSystemEnableInternetAccess": "Gast-Internet-Zugang/LAN Modus",
|
||||
"EnableInternetAccessTooltip": "Erlaubt es der emulierten Anwendung sich mit dem Internet zu verbinden.\n\nSpiele die den LAN-Modus unterstützen, ermöglichen es Ryujinx sich sowohl mit anderen Ryujinx-Systemen, als auch mit offiziellen Nintendo Switch Konsolen zu verbinden. Allerdings nur, wenn diese Option aktiviert ist und die Systeme mit demselben lokalen Netzwerk verbunden sind.\n\nDies erlaubt KEINE Verbindung zu Nintendo-Servern. Kann bei bestimmten Spielen die versuchen sich mit dem Internet zu verbinden zum Absturz führen.\n\nIm Zweifelsfall AUS lassen",
|
||||
@ -554,8 +558,8 @@
|
||||
"SettingsTabHotkeysToggleMuteHotkey": "Stummschalten:",
|
||||
"ControllerMotionTitle": "Bewegungssteuerung - Einstellungen",
|
||||
"ControllerRumbleTitle": "Vibration - Einstellungen",
|
||||
"SettingsSelectThemeFileDialogTitle" : "Wähle ein Design für die Emulator-Benutzeroberfläche",
|
||||
"SettingsXamlThemeFile" : "Xaml Design-Datei",
|
||||
"SettingsSelectThemeFileDialogTitle": "Wähle ein Design für die Emulator-Benutzeroberfläche",
|
||||
"SettingsXamlThemeFile": "Xaml Design-Datei",
|
||||
"AvatarWindowTitle": "Profile verwalten - Avatar",
|
||||
"Amiibo": "Amiibo",
|
||||
"Unknown": "Unbekannt",
|
||||
@ -575,12 +579,12 @@
|
||||
"Discard": "Verwerfen",
|
||||
"UserProfilesSetProfileImage": "Profilbild einrichten",
|
||||
"UserProfileEmptyNameError": "Name ist erforderlich",
|
||||
"UserProfileNoImageError": "Bitte ein Profilbild auswählen",
|
||||
"UserProfileNoImageError": "Bitte ein Profilbild auswählen",
|
||||
"GameUpdateWindowHeading": "Update verfügbar für {0} [{1}]",
|
||||
"SettingsTabHotkeysResScaleUpHotkey": "Auflösung erhöhen:",
|
||||
"SettingsTabHotkeysResScaleDownHotkey": "Auflösung verringern:",
|
||||
"UserProfilesName": "Name:",
|
||||
"UserProfilesUserId" : "Benutzer Id:",
|
||||
"UserProfilesUserId": "Benutzer Id:",
|
||||
"SettingsTabGraphicsBackend": "Grafik-Backend:",
|
||||
"SettingsTabGraphicsBackendTooltip": "Verwendendetes Grafik-Backend",
|
||||
"SettingsEnableTextureRecompression": "Textur-Rekompression",
|
||||
@ -589,5 +593,22 @@
|
||||
"SettingsTabGraphicsPreferredGpuTooltip": "Wähle die Grafikkarte aus, die mit dem Vulkan Grafik-Backend verwendet werden soll.\n\nDies hat keinen Einfluss auf die GPU die OpenGL verwendet.\n\nIm Zweifelsfall die als \"dGPU\" gekennzeichnete GPU auswählen. Diese Einstellung unberührt lassen, wenn keine zur Auswahl steht.",
|
||||
"SettingsAppRequiredRestartMessage": "Ein Neustart von Ryujinx ist erforderlich",
|
||||
"SettingsGpuBackendRestartMessage": "Das Grafik-Backend oder die Grafikkarteneinstellungen wurden geändert. Ein Neustart ist erforderlich um diese Einstellungen anzuwenden.",
|
||||
"SettingsGpuBackendRestartSubMessage": "Ryujinx jetzt neu starten?"
|
||||
"SettingsGpuBackendRestartSubMessage": "Ryujinx jetzt neu starten?",
|
||||
"RyujinxUpdaterMessage": "Möchtest du Ryujinx auf die neueste Version aktualisieren?",
|
||||
"SettingsTabHotkeysVolumeUpHotkey": "Lautstärke erhöhen:",
|
||||
"SettingsTabHotkeysVolumeDownHotkey": "Lautstärke verringern:",
|
||||
"SettingsEnableMacroHLE": "HLE Makros aktivieren",
|
||||
"SettingsEnableMacroHLETooltip": "High-level emulation of GPU Macro code.\n\nImproves performance, but may cause graphical glitches in some games.\n\nLeave ON if unsure.",
|
||||
"VolumeShort": "Vol",
|
||||
"UserProfilesManageSaves": "Speicherstände verwalten",
|
||||
"DeleteUserSave": "Möchtest du den Spielerstand für dieses Spiel löschen?",
|
||||
"IrreversibleActionNote": "Diese Option kann nicht rückgängig gemacht werden.",
|
||||
"SaveManagerHeading": "Spielstände für {0} verwalten",
|
||||
"SaveManagerTitle": "Speicherdaten Manager",
|
||||
"Name": "Name",
|
||||
"Size": "Größe",
|
||||
"Search": "Suche",
|
||||
"UserProfilesRecoverLostAccounts": "Konto wiederherstellen",
|
||||
"Recover": "Wiederherstellen",
|
||||
"UserProfilesRecoverHeading": "Speicherstände wurden für die folgenden Konten gefunden"
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
{
|
||||
"Language": "Ελληνικά",
|
||||
"MenuBarFileOpenApplet": "Άνοιγμα Applet",
|
||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Άνοιγμα του Mii Editor Applet σε Αυτόνομη λειτουργία",
|
||||
"SettingsTabInputDirectMouseAccess": "Άμεση Πρόσβαση Ποντικιού",
|
||||
@ -41,10 +42,10 @@
|
||||
"GameListHeaderPath": "Τοποθεσία",
|
||||
"GameListContextMenuOpenUserSaveDirectory": "Άνοιγμα Τοποθεσίας Αποθήκευσης Χρήστη",
|
||||
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Ανοίγει την τοποθεσία που περιέχει την Αποθήκευση Χρήστη της εφαρμογής",
|
||||
"GameListContextMenuOpenUserDeviceDirectory": "Άνοιγμα Τοποθεσίας Συσκευής Χρήστη",
|
||||
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Ανοίγει την τοποθεσία που περιέχει την Αποθήκευση Συσκευής της εφαρμογής",
|
||||
"GameListContextMenuOpenUserBcatDirectory": "Άνοιγμα Τοποθεσίας BCAT",
|
||||
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Ανοίγει την τοποθεσία που περιέχει την Αποθήκευση BCAT της εφαρμογής",
|
||||
"GameListContextMenuOpenDeviceSaveDirectory": "Άνοιγμα Τοποθεσίας Συσκευής Χρήστη",
|
||||
"GameListContextMenuOpenDeviceSaveDirectoryToolTip": "Ανοίγει την τοποθεσία που περιέχει την Αποθήκευση Συσκευής της εφαρμογής",
|
||||
"GameListContextMenuOpenBcatSaveDirectory": "Άνοιγμα Τοποθεσίας BCAT",
|
||||
"GameListContextMenuOpenBcatSaveDirectoryToolTip": "Ανοίγει την τοποθεσία που περιέχει την Αποθήκευση BCAT της εφαρμογής",
|
||||
"GameListContextMenuManageTitleUpdates": "Διαχείριση Ενημερώσεων Παιχνιδιού",
|
||||
"GameListContextMenuManageTitleUpdatesToolTip": "Ανοίγει το παράθυρο διαχείρισης Ενημερώσεων Παιχνιδιού",
|
||||
"GameListContextMenuManageDlc": "Διαχείριση DLC",
|
||||
@ -65,7 +66,7 @@
|
||||
"GameListContextMenuExtractDataExeFSToolTip": "Εξαγωγή της ενότητας ExeFS από την τρέχουσα διαμόρφωση της εφαρμογής (συμπεριλαμβανομένου ενημερώσεων)",
|
||||
"GameListContextMenuExtractDataRomFS": "RomFS",
|
||||
"GameListContextMenuExtractDataRomFSToolTip": "Εξαγωγή της ενότητας RomFS από την τρέχουσα διαμόρφωση της εφαρμογής (συμπεριλαμβανομένου ενημερώσεων)",
|
||||
"GameListContextMenuExtractDataLogo": "Logo",
|
||||
"GameListContextMenuExtractDataLogo": "Λογότυπο",
|
||||
"GameListContextMenuExtractDataLogoToolTip": "Εξαγωγή της ενότητας Logo από την τρέχουσα διαμόρφωση της εφαρμογής (συμπεριλαμβανομένου ενημερώσεων)",
|
||||
"StatusBarGamesLoaded": "{0}/{1} Φορτωμένα Παιχνίδια",
|
||||
"StatusBarSystemVersion": "Έκδοση Συστήματος: {0}",
|
||||
@ -157,6 +158,7 @@
|
||||
"SettingsTabLoggingEnableFsAccessLogs": "Ενεργοποίηση Καταγραφής Πρόσβασης FS",
|
||||
"SettingsTabLoggingFsGlobalAccessLogMode": "Λειτουργία Καταγραφής Καθολικής Πρόσβασης FS:",
|
||||
"SettingsTabLoggingDeveloperOptions": "Επιλογές Προγραμματιστή (ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Η απόδοση Θα μειωθεί)",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevel": "Επίπεδο Καταγραφής Διεπαφής Γραφικών:",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Κανένα",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelError": "Σφάλμα",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Επιβραδύνσεις",
|
||||
@ -167,7 +169,7 @@
|
||||
"SettingsTabInputDirectKeyboardAccess": "Άμεση Πρόσβαση στο Πληκτρολόγιο",
|
||||
"SettingsButtonSave": "Αποθήκευση",
|
||||
"SettingsButtonClose": "Κλείσιμο",
|
||||
"SettingsButtonOk": "OK",
|
||||
"SettingsButtonOk": "ΟΚ",
|
||||
"SettingsButtonCancel": "Ακύρωση",
|
||||
"SettingsButtonApply": "Εφαρμογή",
|
||||
"ControllerSettingsPlayer": "Παίχτης",
|
||||
@ -184,7 +186,7 @@
|
||||
"ControllerSettingsRefresh": "Ανανέωση",
|
||||
"ControllerSettingsDeviceDisabled": "Απενεργοποιημένο",
|
||||
"ControllerSettingsControllerType": "Τύπος Χειριστηρίου",
|
||||
"ControllerSettingsControllerTypeHandheld": "Handheld",
|
||||
"ControllerSettingsControllerTypeHandheld": "Φορητό",
|
||||
"ControllerSettingsControllerTypeProController": "Pro Controller",
|
||||
"ControllerSettingsControllerTypeJoyConPair": "Ζεύγος JoyCon",
|
||||
"ControllerSettingsControllerTypeJoyConLeft": "Αριστερό JoyCon",
|
||||
@ -195,7 +197,7 @@
|
||||
"ControllerSettingsAdd": "Προσθήκη",
|
||||
"ControllerSettingsRemove": "Αφαίρεση",
|
||||
"ControllerSettingsButtons": "Κουμπιά",
|
||||
"ControllerSettingsButtonA": "A",
|
||||
"ControllerSettingsButtonA": "Α",
|
||||
"ControllerSettingsButtonB": "B",
|
||||
"ControllerSettingsButtonX": "X",
|
||||
"ControllerSettingsButtonY": "Y",
|
||||
@ -212,7 +214,7 @@
|
||||
"ControllerSettingsLStickDown": "Κάτω",
|
||||
"ControllerSettingsLStickLeft": "Αριστερά",
|
||||
"ControllerSettingsLStickRight": "Δεξιά",
|
||||
"ControllerSettingsLStickStick": "Stick",
|
||||
"ControllerSettingsLStickStick": "Μοχλός",
|
||||
"ControllerSettingsLStickInvertXAxis": "Αντιστροφή Μοχλού X",
|
||||
"ControllerSettingsLStickInvertYAxis": "Αντιστροφή Μοχλού Y",
|
||||
"ControllerSettingsLStickDeadzone": "Νεκρή Ζώνη:",
|
||||
@ -222,7 +224,7 @@
|
||||
"ControllerSettingsRStickDown": "Κάτω",
|
||||
"ControllerSettingsRStickLeft": "Αριστερά",
|
||||
"ControllerSettingsRStickRight": "Δεξιά",
|
||||
"ControllerSettingsRStickStick": "Stick",
|
||||
"ControllerSettingsRStickStick": "Μοχλός",
|
||||
"ControllerSettingsRStickInvertXAxis": "Αντιστροφή Μοχλού X",
|
||||
"ControllerSettingsRStickInvertYAxis": "Αντιστροφή Μοχλού Y",
|
||||
"ControllerSettingsRStickDeadzone": "Νεκρή Ζώνη:",
|
||||
@ -258,7 +260,7 @@
|
||||
"UserProfilesChangeProfileImage": "Αλλαγή Εικόνας Προφίλ",
|
||||
"UserProfilesAvailableUserProfiles": "Διαθέσιμα Προφίλ Χρηστών:",
|
||||
"UserProfilesAddNewProfile": "Προσθήκη Νέου Προφίλ",
|
||||
"UserProfilesDeleteSelectedProfile": "Διαγραφή Επιλεγμένου Προφίλ",
|
||||
"UserProfilesDelete": "Διαγράφω",
|
||||
"UserProfilesClose": "Κλείσιμο",
|
||||
"ProfileImageSelectionTitle": "Επιλογή Εικόνας Προφίλ",
|
||||
"ProfileImageSelectionHeader": "Επιλέξτε μία Εικόνα Προφίλ",
|
||||
@ -266,7 +268,7 @@
|
||||
"ProfileImageSelectionImportImage": "Εισαγωγή Αρχείου Εικόνας",
|
||||
"ProfileImageSelectionSelectAvatar": "Επιλέξτε Avatar από Firmware",
|
||||
"InputDialogTitle": "Διάλογος Εισαγωγής",
|
||||
"InputDialogOk": "OK",
|
||||
"InputDialogOk": "ΟΚ",
|
||||
"InputDialogCancel": "Ακύρωση",
|
||||
"InputDialogAddNewProfileTitle": "Επιλογή Ονόματος Προφίλ",
|
||||
"InputDialogAddNewProfileHeader": "Εισαγωγή Ονόματος Προφίλ",
|
||||
@ -314,7 +316,7 @@
|
||||
"DialogUpdaterConvertFailedMessage": "Αποτυχία μετατροπής της τρέχουσας έκδοσης Ryujinx.",
|
||||
"DialogUpdaterCancelUpdateMessage": "Ακύρωση Ενημέρωσης!",
|
||||
"DialogUpdaterAlreadyOnLatestVersionMessage": "Χρησιμοποιείτε ήδη την πιο ενημερωμένη έκδοση του Ryujinx!",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "Σφάλμα κατά την προσπάθεια λήψης έκδοσης από το GitHub Release. Αυτό μπορεί να προκληθεί εάν μία νέα έκδοση συντάσσεται από το GitHub Actions. Δοκιμάστε ξανά σε λίγα λεπτά.",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "Προέκυψε ένα σφάλμα στη λήψη πληροφοριών έκδοσης από τα GitHub Releases. Αυτό δύναται να συμβεί αν μία έκδοση χτίζεται αυτή τη στιγμή στα GitHub Actions. Παρακαλούμε προσπαθήστε αργότερα.",
|
||||
"DialogUpdaterConvertFailedGithubMessage": "Αποτυχία μετατροπής της ληφθείσας έκδοσης Ryujinx από την έκδοση GitHub.",
|
||||
"DialogUpdaterDownloadingMessage": "Λήψη Ενημέρωσης...",
|
||||
"DialogUpdaterExtractionMessage": "Εξαγωγή Ενημέρωσης...",
|
||||
@ -411,6 +413,8 @@
|
||||
"DlcManagerTableHeadingContainerPathLabel": "Τοποθεσία DLC",
|
||||
"DlcManagerTableHeadingFullPathLabel": "Πλήρης τοποθεσία",
|
||||
"DlcManagerRemoveAllButton": "Αφαίρεση όλων",
|
||||
"DlcManagerEnableAllButton": "Ενεργοποίηση Όλων",
|
||||
"DlcManagerDisableAllButton": "Απενεργοποίηση Όλων",
|
||||
"MenuBarOptionsChangeLanguage": "Αλλαξε γλώσσα",
|
||||
"CommonSort": "Κατάταξη",
|
||||
"CommonShowNames": "Εμφάνιση ονομάτων",
|
||||
@ -492,6 +496,119 @@
|
||||
"SettingsTabNetworkConnection": "Σύνδεση δικτύου",
|
||||
"SettingsTabCpuCache": "Προσωρινή Μνήμη CPU",
|
||||
"SettingsTabCpuMemory": "Μνήμη CPU",
|
||||
"DialogUpdaterFlatpakNotSupportedMessage": "Παρακαλούμε ενημερώστε το Ryujinx μέσω FlatHub.",
|
||||
"UpdaterDisabledWarningTitle": "Ο Διαχειριστής Ενημερώσεων Είναι Απενεργοποιημένος!",
|
||||
"GameListContextMenuOpenSdModsDirectory": "Άνοιγμα Της Τοποθεσίας Των Atmosphere Mods",
|
||||
"GameListContextMenuOpenSdModsDirectoryToolTip": "Opens the alternative SD card Atmosphere directory which contains Application's Mods. Useful for mods that are packaged for real hardware.",
|
||||
"ControllerSettingsRotate90": "Rotate 90° Clockwise",
|
||||
"IconSize": "Icon Size",
|
||||
"IconSizeTooltip": "Change the size of game icons",
|
||||
"MenuBarOptionsShowConsole": "Show Console",
|
||||
"ShaderCachePurgeError": "Error purging shader cache at {0}: {1}",
|
||||
"UserErrorNoKeys": "Keys not found",
|
||||
"UserErrorNoFirmware": "Firmware not found",
|
||||
"UserErrorFirmwareParsingFailed": "Firmware parsing error",
|
||||
"UserErrorApplicationNotFound": "Application not found",
|
||||
"UserErrorUnknown": "Unknown error",
|
||||
"UserErrorUndefined": "Undefined error",
|
||||
"UserErrorNoKeysDescription": "Ryujinx was unable to find your 'prod.keys' file",
|
||||
"UserErrorNoFirmwareDescription": "Ryujinx was unable to find any firmwares installed",
|
||||
"UserErrorFirmwareParsingFailedDescription": "Ryujinx was unable to parse the provided firmware. This is usually caused by outdated keys.",
|
||||
"UserErrorApplicationNotFoundDescription": "Ryujinx couldn't find a valid application at the given path.",
|
||||
"UserErrorUnknownDescription": "An unknown error occured!",
|
||||
"UserErrorUndefinedDescription": "An undefined error occured! This shouldn't happen, please contact a dev!",
|
||||
"OpenSetupGuideMessage": "Open the Setup Guide",
|
||||
"NoUpdate": "No Update",
|
||||
"TitleUpdateVersionLabel": "Version {0} - {1}",
|
||||
"RyujinxInfo": "Ryujinx - Info",
|
||||
"RyujinxConfirm": "Ryujinx - Confirmation",
|
||||
"FileDialogAllTypes": "All types",
|
||||
"Never": "Never",
|
||||
"SwkbdMinCharacters": "Must be at least {0} characters long",
|
||||
"SwkbdMinRangeCharacters": "Must be {0}-{1} characters long",
|
||||
"SoftwareKeyboard": "Software Keyboard",
|
||||
"DialogControllerAppletMessagePlayerRange": "Application requests {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
|
||||
"DialogControllerAppletMessage": "Application requests exactly {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
|
||||
"DialogControllerAppletDockModeSet": "Docked mode set. Handheld is also invalid.\n\n",
|
||||
"UpdaterRenaming": "Renaming Old Files...",
|
||||
"UpdaterRenameFailed": "Updater was unable to rename file: {0}",
|
||||
"UpdaterAddingFiles": "Adding New Files...",
|
||||
"UpdaterExtracting": "Extracting Update...",
|
||||
"UpdaterDownloading": "Downloading Update...",
|
||||
"Game": "Game",
|
||||
"Docked": "Docked",
|
||||
"Handheld": "Handheld",
|
||||
"ConnectionError": "Connection Error.",
|
||||
"AboutPageDeveloperListMore": "{0} and more...",
|
||||
"ApiError": "API Error.",
|
||||
"LoadingHeading": "Loading {0}",
|
||||
"CompilingPPTC": "Compiling PTC",
|
||||
"CompilingShaders": "Compiling Shaders",
|
||||
"AllKeyboards": "All keyboards",
|
||||
"OpenFileDialogTitle": "Select a supported file to open",
|
||||
"OpenFolderDialogTitle": "Select a folder with an unpacked game",
|
||||
"AllSupportedFormats": "All Supported Formats",
|
||||
"RyujinxUpdater": "Ryujinx Updater",
|
||||
"SettingsTabHotkeys": "Keyboard Hotkeys",
|
||||
"SettingsTabHotkeysHotkeys": "Keyboard Hotkeys",
|
||||
"SettingsTabHotkeysToggleVsyncHotkey": "Toggle VSync:",
|
||||
"SettingsTabHotkeysScreenshotHotkey": "Screenshot:",
|
||||
"SettingsTabHotkeysShowUiHotkey": "Show UI:",
|
||||
"SettingsTabHotkeysPauseHotkey": "Pause:",
|
||||
"SettingsTabHotkeysToggleMuteHotkey": "Mute:",
|
||||
"ControllerMotionTitle": "Motion Control Settings",
|
||||
"ControllerRumbleTitle": "Rumble Settings"
|
||||
"ControllerRumbleTitle": "Rumble Settings",
|
||||
"SettingsSelectThemeFileDialogTitle": "Select Theme File",
|
||||
"SettingsXamlThemeFile": "Xaml Theme File",
|
||||
"AvatarWindowTitle": "Manage Accounts - Avatar",
|
||||
"Amiibo": "Amiibo",
|
||||
"Unknown": "Unknown",
|
||||
"Usage": "Usage",
|
||||
"Writable": "Writable",
|
||||
"SelectDlcDialogTitle": "Select DLC files",
|
||||
"SelectUpdateDialogTitle": "Select update files",
|
||||
"UserProfileWindowTitle": "User Profiles Manager",
|
||||
"CheatWindowTitle": "Cheats Manager",
|
||||
"DlcWindowTitle": "Downloadable Content Manager",
|
||||
"UpdateWindowTitle": "Title Update Manager",
|
||||
"CheatWindowHeading": "Cheats Available for {0} [{1}]",
|
||||
"DlcWindowHeading": "{0} Downloadable Content(s) available for {1} ({2})",
|
||||
"UserProfilesEditProfile": "Edit Selected",
|
||||
"Cancel": "Cancel",
|
||||
"Save": "Save",
|
||||
"Discard": "Discard",
|
||||
"UserProfilesSetProfileImage": "Set Profile Image",
|
||||
"UserProfileEmptyNameError": "Name is required",
|
||||
"UserProfileNoImageError": "Profile image must be set",
|
||||
"GameUpdateWindowHeading": "{0} Update(s) available for {1} ({2})",
|
||||
"SettingsTabHotkeysResScaleUpHotkey": "Increase resolution:",
|
||||
"SettingsTabHotkeysResScaleDownHotkey": "Decrease resolution:",
|
||||
"UserProfilesName": "Name:",
|
||||
"UserProfilesUserId": "User Id:",
|
||||
"SettingsTabGraphicsBackend": "Graphics Backend",
|
||||
"SettingsTabGraphicsBackendTooltip": "Graphics Backend to use",
|
||||
"SettingsEnableTextureRecompression": "Enable Texture Recompression",
|
||||
"SettingsEnableTextureRecompressionTooltip": "Compresses certain textures in order to reduce VRAM usage.\n\nRecommended for use with GPUs that have less than 4GiB VRAM.\n\nLeave OFF if unsure.",
|
||||
"SettingsTabGraphicsPreferredGpu": "Preferred GPU",
|
||||
"SettingsTabGraphicsPreferredGpuTooltip": "Select the graphics card that will be used with the Vulkan graphics backend.\n\nDoes not affect the GPU that OpenGL will use.\n\nSet to the GPU flagged as \"dGPU\" if unsure. If there isn't one, leave untouched.",
|
||||
"SettingsAppRequiredRestartMessage": "Ryujinx Restart Required",
|
||||
"SettingsGpuBackendRestartMessage": "Graphics Backend or GPU settings have been modified. This will require a restart to be applied",
|
||||
"SettingsGpuBackendRestartSubMessage": "Do you want to restart now?",
|
||||
"RyujinxUpdaterMessage": "Do you want to update Ryujinx to the latest version?",
|
||||
"SettingsTabHotkeysVolumeUpHotkey": "Increase Volume:",
|
||||
"SettingsTabHotkeysVolumeDownHotkey": "Decrease Volume:",
|
||||
"SettingsEnableMacroHLE": "Enable Macro HLE",
|
||||
"SettingsEnableMacroHLETooltip": "High-level emulation of GPU Macro code.\n\nImproves performance, but may cause graphical glitches in some games.\n\nLeave ON if unsure.",
|
||||
"VolumeShort": "Vol",
|
||||
"UserProfilesManageSaves": "Manage Saves",
|
||||
"DeleteUserSave": "Do you want to delete user save for this game?",
|
||||
"IrreversibleActionNote": "This action is not reversible.",
|
||||
"SaveManagerHeading": "Manage Saves for {0}",
|
||||
"SaveManagerTitle": "Save Manager",
|
||||
"Name": "Name",
|
||||
"Size": "Size",
|
||||
"Search": "Search",
|
||||
"UserProfilesRecoverLostAccounts": "Recover Lost Accounts",
|
||||
"Recover": "Recover",
|
||||
"UserProfilesRecoverHeading": "Saves were found for the following accounts"
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"Language": "English (US)",
|
||||
"MenuBarFileOpenApplet": "Open Applet",
|
||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Open Mii Editor Applet in Standalone mode",
|
||||
"SettingsTabInputDirectMouseAccess": "Direct Mouse Access",
|
||||
@ -41,10 +42,10 @@
|
||||
"GameListHeaderPath": "Path",
|
||||
"GameListContextMenuOpenUserSaveDirectory": "Open User Save Directory",
|
||||
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Opens the directory which contains Application's User Save",
|
||||
"GameListContextMenuOpenUserDeviceDirectory": "Open User Device Directory",
|
||||
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Opens the directory which contains Application's Device Save",
|
||||
"GameListContextMenuOpenUserBcatDirectory": "Open User BCAT Directory",
|
||||
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Opens the directory which contains Application's BCAT Save",
|
||||
"GameListContextMenuOpenDeviceSaveDirectory": "Open Device Save Directory",
|
||||
"GameListContextMenuOpenDeviceSaveDirectoryToolTip": "Opens the directory which contains Application's Device Save",
|
||||
"GameListContextMenuOpenBcatSaveDirectory": "Open BCAT Save Directory",
|
||||
"GameListContextMenuOpenBcatSaveDirectoryToolTip": "Opens the directory which contains Application's BCAT Save",
|
||||
"GameListContextMenuManageTitleUpdates": "Manage Title Updates",
|
||||
"GameListContextMenuManageTitleUpdatesToolTip": "Opens the Title Update management window",
|
||||
"GameListContextMenuManageDlc": "Manage DLC",
|
||||
@ -118,7 +119,7 @@
|
||||
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
|
||||
"SettingsTabSystemAudioBackendSDL2": "SDL2",
|
||||
"SettingsTabSystemHacks": "Hacks",
|
||||
"SettingsTabSystemHacksNote": " (may cause instability)",
|
||||
"SettingsTabSystemHacksNote": "May cause instability",
|
||||
"SettingsTabSystemExpandDramSize": "Use alternative memory layout (Developers)",
|
||||
"SettingsTabSystemIgnoreMissingServices": "Ignore Missing Services",
|
||||
"SettingsTabGraphics": "Graphics",
|
||||
@ -156,7 +157,8 @@
|
||||
"SettingsTabLoggingEnableGuestLogs": "Enable Guest Logs",
|
||||
"SettingsTabLoggingEnableFsAccessLogs": "Enable Fs Access Logs",
|
||||
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs Global Access Log Mode:",
|
||||
"SettingsTabLoggingDeveloperOptions": "Developer Options (WARNING: Will reduce performance)",
|
||||
"SettingsTabLoggingDeveloperOptions": "Developer Options",
|
||||
"SettingsTabLoggingDeveloperOptionsNote": "WARNING: Will reduce performance",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevel": "Graphics Backend Log Level:",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelNone": "None",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelError": "Error",
|
||||
@ -259,8 +261,9 @@
|
||||
"UserProfilesChangeProfileImage": "Change Profile Image",
|
||||
"UserProfilesAvailableUserProfiles": "Available User Profiles:",
|
||||
"UserProfilesAddNewProfile": "Create Profile",
|
||||
"UserProfilesDeleteSelectedProfile": "Delete Selected",
|
||||
"UserProfilesDelete": "Delete",
|
||||
"UserProfilesClose": "Close",
|
||||
"ProfileNameSelectionWatermark": "Choose a nickname",
|
||||
"ProfileImageSelectionTitle": "Profile Image Selection",
|
||||
"ProfileImageSelectionHeader": "Choose a profile Image",
|
||||
"ProfileImageSelectionNote": "You may import a custom profile image, or select an avatar from system firmware",
|
||||
@ -272,7 +275,7 @@
|
||||
"InputDialogAddNewProfileTitle": "Choose the Profile Name",
|
||||
"InputDialogAddNewProfileHeader": "Please Enter a Profile Name",
|
||||
"InputDialogAddNewProfileSubtext": "(Max Length: {0})",
|
||||
"AvatarChoose": "Choose",
|
||||
"AvatarChoose": "Choose Avatar",
|
||||
"AvatarSetBackgroundColor": "Set Background Color",
|
||||
"AvatarClose": "Close",
|
||||
"ControllerSettingsLoadProfileToolTip": "Load Profile",
|
||||
@ -280,7 +283,7 @@
|
||||
"ControllerSettingsRemoveProfileToolTip": "Remove Profile",
|
||||
"ControllerSettingsSaveProfileToolTip": "Save Profile",
|
||||
"MenuBarFileToolsTakeScreenshot": "Take Screenshot",
|
||||
"MenuBarFileToolsHideUi": "Hide Ui",
|
||||
"MenuBarFileToolsHideUi": "Hide UI",
|
||||
"GameListContextMenuToggleFavorite": "Toggle Favorite",
|
||||
"GameListContextMenuToggleFavoriteToolTip": "Toggle Favorite status of Game",
|
||||
"SettingsTabGeneralTheme": "Theme",
|
||||
@ -367,6 +370,9 @@
|
||||
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "System version {0} successfully installed.",
|
||||
"DialogUserProfileDeletionWarningMessage": "There would be no other profiles to be opened if selected profile is deleted",
|
||||
"DialogUserProfileDeletionConfirmMessage": "Do you want to delete the selected profile",
|
||||
"DialogUserProfileUnsavedChangesTitle": "Warning - Unsaved Changes",
|
||||
"DialogUserProfileUnsavedChangesMessage": "You have made changes to this user profile that have not been saved.",
|
||||
"DialogUserProfileUnsavedChangesSubMessage": "Do you want to discard your changes?",
|
||||
"DialogControllerSettingsModifiedConfirmMessage": "The current controller settings has been updated.",
|
||||
"DialogControllerSettingsModifiedConfirmSubMessage": "Do you want to save?",
|
||||
"DialogDlcLoadNcaErrorMessage": "{0}. Errored File: {1}",
|
||||
@ -583,7 +589,7 @@
|
||||
"SettingsTabHotkeysResScaleUpHotkey": "Increase resolution:",
|
||||
"SettingsTabHotkeysResScaleDownHotkey": "Decrease resolution:",
|
||||
"UserProfilesName": "Name:",
|
||||
"UserProfilesUserId": "User Id:",
|
||||
"UserProfilesUserId": "User ID:",
|
||||
"SettingsTabGraphicsBackend": "Graphics Backend",
|
||||
"SettingsTabGraphicsBackendTooltip": "Graphics Backend to use",
|
||||
"SettingsEnableTextureRecompression": "Enable Texture Recompression",
|
||||
@ -602,12 +608,15 @@
|
||||
"UserProfilesManageSaves": "Manage Saves",
|
||||
"DeleteUserSave": "Do you want to delete user save for this game?",
|
||||
"IrreversibleActionNote": "This action is not reversible.",
|
||||
"SaveManagerHeading": "Manage Saves for {0}",
|
||||
"SaveManagerHeading": "Manage Saves for {0} ({1})",
|
||||
"SaveManagerTitle": "Save Manager",
|
||||
"Name": "Name",
|
||||
"Size": "Size",
|
||||
"Search": "Search",
|
||||
"UserProfilesRecoverLostAccounts": "Recover Lost Accounts",
|
||||
"Recover": "Recover",
|
||||
"UserProfilesRecoverHeading" : "Saves were found for the following accounts"
|
||||
}
|
||||
"UserProfilesRecoverHeading" : "Saves were found for the following accounts",
|
||||
"UserProfilesRecoverEmptyList": "No profiles to recover",
|
||||
"UserEditorTitle" : "Edit User",
|
||||
"UserEditorTitleCreate" : "Create User"
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"Language": "Español (ES)",
|
||||
"MenuBarFileOpenApplet": "Abrir applet",
|
||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Abre el editor de Mii en modo autónomo",
|
||||
"SettingsTabInputDirectMouseAccess": "Acceso directo al ratón",
|
||||
@ -13,66 +14,66 @@
|
||||
"MenuBarFileOpenLogsFolder": "Abrir carpeta de registros",
|
||||
"MenuBarFileExit": "_Salir",
|
||||
"MenuBarOptions": "_Opciones",
|
||||
"MenuBarOptionsToggleFullscreen": "Alternar pantalla completa",
|
||||
"MenuBarOptionsToggleFullscreen": "Cambiar a pantalla completa.",
|
||||
"MenuBarOptionsStartGamesInFullscreen": "Iniciar juegos en pantalla completa",
|
||||
"MenuBarOptionsStopEmulation": "Detener emulación",
|
||||
"MenuBarOptionsSettings": "_Configuración",
|
||||
"MenuBarOptionsManageUserProfiles": "_Gestionar perfiles de usuario",
|
||||
"MenuBarActions": "Accio_nes",
|
||||
"MenuBarOptionsSimulateWakeUpMessage": "Simular mensaje de _reactivación",
|
||||
"MenuBarActionsScanAmiibo": "_Escanear Amiibo",
|
||||
"MenuBarActions": "_Acciones",
|
||||
"MenuBarOptionsSimulateWakeUpMessage": "Simular mensaje de reactivación",
|
||||
"MenuBarActionsScanAmiibo": "Escanear Amiibo",
|
||||
"MenuBarTools": "_Herramientas",
|
||||
"MenuBarToolsInstallFirmware": "Instalar firmware",
|
||||
"MenuBarFileToolsInstallFirmwareFromFile": "Instalar firmware desde un archivo XCI o ZIP",
|
||||
"MenuBarFileToolsInstallFirmwareFromDirectory": "Instalar firmware desde una carpeta",
|
||||
"MenuBarHelp": "A_yuda",
|
||||
"MenuBarHelp": "Ayuda",
|
||||
"MenuBarHelpCheckForUpdates": "Buscar actualizaciones",
|
||||
"MenuBarHelpAbout": "Acerca de",
|
||||
"MenuSearch": "Buscar...",
|
||||
"GameListHeaderFavorite": "Fav",
|
||||
"GameListHeaderFavorite": "Favoritos",
|
||||
"GameListHeaderIcon": "Icono",
|
||||
"GameListHeaderApplication": "Aplicación",
|
||||
"GameListHeaderApplication": "Nombre",
|
||||
"GameListHeaderDeveloper": "Desarrollador",
|
||||
"GameListHeaderVersion": "Versión",
|
||||
"GameListHeaderTimePlayed": "Tiempo jugado",
|
||||
"GameListHeaderLastPlayed": "Última vez",
|
||||
"GameListHeaderLastPlayed": "Jugado por última vez",
|
||||
"GameListHeaderFileExtension": "Extensión",
|
||||
"GameListHeaderFileSize": "Tamaño",
|
||||
"GameListHeaderFileSize": "Tamaño del archivo",
|
||||
"GameListHeaderPath": "Directorio",
|
||||
"GameListContextMenuOpenUserSaveDirectory": "Abrir carpeta de guardado de este usuario",
|
||||
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Abre la carpeta que contiene la partida guardada del usuario para esta aplicación",
|
||||
"GameListContextMenuOpenUserDeviceDirectory": "Abrir carpeta de guardado del sistema para el usuario actual",
|
||||
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Abre la carpeta que contiene la partida guardada del sistema para esta aplicación",
|
||||
"GameListContextMenuOpenUserBcatDirectory": "Abrir carpeta de guardado BCAT del usuario",
|
||||
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Abre la carpeta que contiene el guardado BCAT de esta aplicación",
|
||||
"GameListContextMenuOpenDeviceSaveDirectory": "Abrir carpeta de guardado del sistema para el usuario actual",
|
||||
"GameListContextMenuOpenDeviceSaveDirectoryToolTip": "Abre la carpeta que contiene la partida guardada del sistema para esta aplicación",
|
||||
"GameListContextMenuOpenBcatSaveDirectory": "Abrir carpeta de guardado BCAT del usuario",
|
||||
"GameListContextMenuOpenBcatSaveDirectoryToolTip": "Abrir la carpeta que contiene el guardado BCAT de esta aplicación",
|
||||
"GameListContextMenuManageTitleUpdates": "Gestionar actualizaciones del juego",
|
||||
"GameListContextMenuManageTitleUpdatesToolTip": "Abre la ventana de gestión de actualizaciones de esta aplicación",
|
||||
"GameListContextMenuManageTitleUpdatesToolTip": "Abrir la ventana de gestión de actualizaciones de esta aplicación",
|
||||
"GameListContextMenuManageDlc": "Gestionar DLC",
|
||||
"GameListContextMenuManageDlcToolTip": "Abre la ventana de gestión del contenido descargable",
|
||||
"GameListContextMenuManageDlcToolTip": "Abrir la ventana de gestión del DLC",
|
||||
"GameListContextMenuOpenModsDirectory": "Abrir carpeta de mods",
|
||||
"GameListContextMenuOpenModsDirectoryToolTip": "Abre la carpeta que contiene los mods (archivos modificantes) de esta aplicación",
|
||||
"GameListContextMenuCacheManagement": "Gestión de cachés",
|
||||
"GameListContextMenuCacheManagementPurgePptc": "Purgar caché de PPTC",
|
||||
"GameListContextMenuOpenModsDirectoryToolTip": "Abrir la carpeta que contiene los mods (archivos modificantes) de esta aplicación",
|
||||
"GameListContextMenuCacheManagement": "Gestión de caché ",
|
||||
"GameListContextMenuCacheManagementPurgePptc": "Reconstruir PPTC en cola",
|
||||
"GameListContextMenuCacheManagementPurgePptcToolTip": "Elimina la caché de PPTC de esta aplicación",
|
||||
"GameListContextMenuCacheManagementPurgeShaderCache": "Purgar caché de sombreadores",
|
||||
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Elimina la caché de sombreadores de esta aplicación",
|
||||
"GameListContextMenuCacheManagementPurgeShaderCache": "Limpiar caché de sombras",
|
||||
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Eliminar la caché de sombras de esta aplicación",
|
||||
"GameListContextMenuCacheManagementOpenPptcDirectory": "Abrir carpeta de PPTC",
|
||||
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "Abre la carpeta que contiene la caché de PPTC de esta aplicación",
|
||||
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "Abrir carpeta de caché de sombreadores",
|
||||
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "Abre la carpeta que contiene la caché de sombreadores de esta aplicación",
|
||||
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "Abrir la carpeta que contiene la caché de PPTC de esta aplicación",
|
||||
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "Abrir carpeta de caché de sombras",
|
||||
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "Abrir la carpeta que contiene la caché de sombras de esta aplicación",
|
||||
"GameListContextMenuExtractData": "Extraer datos",
|
||||
"GameListContextMenuExtractDataExeFS": "ExeFS",
|
||||
"GameListContextMenuExtractDataExeFSToolTip": "Extrae la sección ExeFS de la configuración actual de la aplicación (incluyendo actualizaciones)",
|
||||
"GameListContextMenuExtractDataExeFSToolTip": "Extraer la sección ExeFS de la configuración actual de la aplicación (incluyendo actualizaciones)",
|
||||
"GameListContextMenuExtractDataRomFS": "RomFS",
|
||||
"GameListContextMenuExtractDataRomFSToolTip": "Extrae la sección RomFS de la configuración actual de la aplicación (incluyendo actualizaciones)",
|
||||
"GameListContextMenuExtractDataLogo": "Logo",
|
||||
"GameListContextMenuExtractDataLogoToolTip": "Extrae la sección Logo de la configuración actual de la aplicación (incluyendo actualizaciones)",
|
||||
"GameListContextMenuExtractDataRomFSToolTip": "Extraer la sección RomFS de la configuración actual de la aplicación (incluyendo actualizaciones)",
|
||||
"GameListContextMenuExtractDataLogo": "Logotipo",
|
||||
"GameListContextMenuExtractDataLogoToolTip": "Extraer la sección Logo de la configuración actual de la aplicación (incluyendo actualizaciones)",
|
||||
"StatusBarGamesLoaded": "{0}/{1} juegos cargados",
|
||||
"StatusBarSystemVersion": "Versión del sistema: {0}",
|
||||
"Settings": "Configuración",
|
||||
"SettingsTabGeneral": "General",
|
||||
"SettingsTabGeneral": "Interfaz de usuario",
|
||||
"SettingsTabGeneralGeneral": "General",
|
||||
"SettingsTabGeneralEnableDiscordRichPresence": "Habilitar presencia enriquecida de Discord",
|
||||
"SettingsTabGeneralEnableDiscordRichPresence": "Habilitar estado en Discord",
|
||||
"SettingsTabGeneralCheckUpdatesOnLaunch": "Buscar actualizaciones al iniciar",
|
||||
"SettingsTabGeneralShowConfirmExitDialog": "Mostrar diálogo de confirmación al cerrar",
|
||||
"SettingsTabGeneralHideCursorOnIdle": "Ocultar cursor cuando esté inactivo",
|
||||
@ -80,7 +81,7 @@
|
||||
"SettingsTabGeneralAdd": "Agregar",
|
||||
"SettingsTabGeneralRemove": "Quitar",
|
||||
"SettingsTabSystem": "Sistema",
|
||||
"SettingsTabSystemCore": "Principal",
|
||||
"SettingsTabSystemCore": "Núcleo",
|
||||
"SettingsTabSystemSystemRegion": "Región del sistema:",
|
||||
"SettingsTabSystemSystemRegionJapan": "Japón",
|
||||
"SettingsTabSystemSystemRegionUSA": "EEUU",
|
||||
@ -110,22 +111,22 @@
|
||||
"SettingsTabSystemSystemTimeZone": "Zona horaria del sistema:",
|
||||
"SettingsTabSystemSystemTime": "Hora del sistema:",
|
||||
"SettingsTabSystemEnableVsync": "Sincronización vertical",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (Cache de Traducción de Perfil Persistente)",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "Comprobar integridad de los archivos",
|
||||
"SettingsTabSystemAudioBackend": "Motor de audio:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Dummy",
|
||||
"SettingsTabSystemAudioBackendDummy": "Vacio",
|
||||
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
|
||||
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
|
||||
"SettingsTabSystemAudioBackendSDL2": "SDL2",
|
||||
"SettingsTabSystemHacks": "Hacks",
|
||||
"SettingsTabSystemHacksNote": " (Pueden causar inestabilidad)",
|
||||
"SettingsTabSystemExpandDramSize": "Expandir DRAM a 6GiB",
|
||||
"SettingsTabSystemExpandDramSize": "Usar diseño alternativo de memoria (Desarrolladores)",
|
||||
"SettingsTabSystemIgnoreMissingServices": "Ignorar servicios no implementados",
|
||||
"SettingsTabGraphics": "Gráficos",
|
||||
"SettingsTabGraphicsAPI": "API de gráficos",
|
||||
"SettingsTabGraphicsEnableShaderCache": "Habilitar caché de sombreadores",
|
||||
"SettingsTabGraphicsEnableShaderCache": "Habilitar caché de sombras",
|
||||
"SettingsTabGraphicsAnisotropicFiltering": "Filtro anisotrópico:",
|
||||
"SettingsTabGraphicsAnisotropicFilteringAuto": "Auto",
|
||||
"SettingsTabGraphicsAnisotropicFilteringAuto": "Automático",
|
||||
"SettingsTabGraphicsAnisotropicFiltering2x": "x2",
|
||||
"SettingsTabGraphicsAnisotropicFiltering4x": "x4",
|
||||
"SettingsTabGraphicsAnisotropicFiltering8x": "x8",
|
||||
@ -144,10 +145,10 @@
|
||||
"SettingsTabGraphicsAspectRatio32x9": "32:9",
|
||||
"SettingsTabGraphicsAspectRatioStretch": "Estirar a la ventana",
|
||||
"SettingsTabGraphicsDeveloperOptions": "Opciones de desarrollador",
|
||||
"SettingsTabGraphicsShaderDumpPath": "Directorio de volcado de sombreadores:",
|
||||
"SettingsTabGraphicsShaderDumpPath": "Directorio de volcado de sombras:",
|
||||
"SettingsTabLogging": "Registros",
|
||||
"SettingsTabLoggingLogging": "Registros",
|
||||
"SettingsTabLoggingEnableLoggingToFile": "Escribir registros en archivo",
|
||||
"SettingsTabLoggingEnableLoggingToFile": "Habilitar registro a archivo",
|
||||
"SettingsTabLoggingEnableStubLogs": "Habilitar registros de Stub",
|
||||
"SettingsTabLoggingEnableInfoLogs": "Habilitar registros de Info",
|
||||
"SettingsTabLoggingEnableWarningLogs": "Habilitar registros de Advertencia",
|
||||
@ -157,6 +158,7 @@
|
||||
"SettingsTabLoggingEnableFsAccessLogs": "Habilitar registros de Fs Access",
|
||||
"SettingsTabLoggingFsGlobalAccessLogMode": "Modo de registros Fs Global Access:",
|
||||
"SettingsTabLoggingDeveloperOptions": "Opciones de desarrollador (ADVERTENCIA: empeorarán el rendimiento)",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevel": "Nivel de registro de backend gráficos:",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Nada",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelError": "Errores",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Ralentizaciones",
|
||||
@ -167,7 +169,7 @@
|
||||
"SettingsTabInputDirectKeyboardAccess": "Acceso directo al teclado",
|
||||
"SettingsButtonSave": "Guardar",
|
||||
"SettingsButtonClose": "Cerrar",
|
||||
"SettingsButtonOk": "OK",
|
||||
"SettingsButtonOk": "Aceptar",
|
||||
"SettingsButtonCancel": "Cancelar",
|
||||
"SettingsButtonApply": "Aplicar",
|
||||
"ControllerSettingsPlayer": "Jugador",
|
||||
@ -258,7 +260,7 @@
|
||||
"UserProfilesChangeProfileImage": "Cambiar imagen de perfil",
|
||||
"UserProfilesAvailableUserProfiles": "Perfiles de usuario disponibles:",
|
||||
"UserProfilesAddNewProfile": "Añadir nuevo perfil",
|
||||
"UserProfilesDeleteSelectedProfile": "Eliminar perfil seleccionado",
|
||||
"UserProfilesDelete": "Eliminar",
|
||||
"UserProfilesClose": "Cerrar",
|
||||
"ProfileImageSelectionTitle": "Selección de imagen de perfil",
|
||||
"ProfileImageSelectionHeader": "Elige una imagen de perfil",
|
||||
@ -314,7 +316,7 @@
|
||||
"DialogUpdaterConvertFailedMessage": "No se pudo convertir la versión actual de Ryujinx.",
|
||||
"DialogUpdaterCancelUpdateMessage": "¡Cancelando actualización!",
|
||||
"DialogUpdaterAlreadyOnLatestVersionMessage": "¡Ya tienes la versión más reciente de Ryujinx!",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "Ha ocurrido un error al intentar obtener información de versión desde GitHub Release. Esto puede ocurrir cuando una nueva versión está siendo compilada por GitHub Actions. Inténtalo de nuevo en unos minutos.",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "Se ha producido un error al intentar obtener información de liberación de GitHub Release. Esto puede ser causado si una nueva versión está siendo compilada por GitHub Actions. Inténtalo de nuevo en unos minutos.",
|
||||
"DialogUpdaterConvertFailedGithubMessage": "No se pudo convertir la versión de Ryujinx recibida de GitHub Release.",
|
||||
"DialogUpdaterDownloadingMessage": "Descargando actualización...",
|
||||
"DialogUpdaterExtractionMessage": "Extrayendo actualización...",
|
||||
@ -372,8 +374,8 @@
|
||||
"DialogDlcNoDlcErrorMessage": "¡Ese archivo no contiene contenido descargable para el título seleccionado!",
|
||||
"DialogPerformanceCheckLoggingEnabledMessage": "Has habilitado los registros debug, diseñados solo para uso de los desarrolladores.",
|
||||
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "Para un rendimiento óptimo, se recomienda deshabilitar los registros debug. ¿Quieres deshabilitarlos ahora?",
|
||||
"DialogPerformanceCheckShaderDumpEnabledMessage": "Has habilitado el volcado de sombreadores, diseñado solo para uso de los desarrolladores.",
|
||||
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "Para un rendimiento óptimo, se recomienda deshabilitar el volcado de sombreadores. ¿Quieres deshabilitarlo ahora?",
|
||||
"DialogPerformanceCheckShaderDumpEnabledMessage": "Has habilitado el volcado de sombras, diseñado solo para uso de los desarrolladores.",
|
||||
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "Para un rendimiento óptimo, se recomienda deshabilitar el volcado de sombraa. ¿Quieres deshabilitarlo ahora?",
|
||||
"DialogLoadAppGameAlreadyLoadedMessage": "Ya has cargado un juego",
|
||||
"DialogLoadAppGameAlreadyLoadedSubMessage": "Por favor, detén la emulación o cierra el emulador antes de iniciar otro juego.",
|
||||
"DialogUpdateAddUpdateErrorMessage": "¡Ese archivo no contiene una actualización para el título seleccionado!",
|
||||
@ -381,7 +383,7 @@
|
||||
"DialogSettingsBackendThreadingWarningMessage": "Ryujinx debe reiniciarse para aplicar este cambio. Dependiendo de tu plataforma, puede que tengas que desactivar manualmente la optimización enlazada de tus controladores gráficos para usar el multihilo de Ryujinx.",
|
||||
"SettingsTabGraphicsFeaturesOptions": "Funcionalidades",
|
||||
"SettingsTabGraphicsBackendMultithreading": "Multihilado del motor gráfico:",
|
||||
"CommonAuto": "Auto",
|
||||
"CommonAuto": "Automático",
|
||||
"CommonOff": "Desactivado",
|
||||
"CommonOn": "Activado",
|
||||
"InputDialogYes": "Sí",
|
||||
@ -400,7 +402,7 @@
|
||||
"AboutRyujinxAboutContent": "Ryujinx es un emulador para Nintendo Switch™.\nPor favor, apóyanos en Patreon.\nEncuentra las noticias más recientes en nuestro Twitter o Discord.\nDesarrolladores interesados en contribuir pueden encontrar más información en GitHub o Discord.",
|
||||
"AboutRyujinxMaintainersTitle": "Mantenido por:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "Haz clic para abrir la página de contribuidores en tu navegador predeterminado.",
|
||||
"AboutRyujinxSupprtersTitle": "Mecenas en Patreon:",
|
||||
"AboutRyujinxSupprtersTitle": "Apoyado en Patreon Por:",
|
||||
"AmiiboSeriesLabel": "Serie de Amiibo",
|
||||
"AmiiboCharacterLabel": "Personaje",
|
||||
"AmiiboScanButtonLabel": "Escanear",
|
||||
@ -411,13 +413,15 @@
|
||||
"DlcManagerTableHeadingContainerPathLabel": "Directorio del contenedor",
|
||||
"DlcManagerTableHeadingFullPathLabel": "Directorio completo",
|
||||
"DlcManagerRemoveAllButton": "Quitar todo",
|
||||
"DlcManagerEnableAllButton": "Activar todas",
|
||||
"DlcManagerDisableAllButton": "Desactivar todos",
|
||||
"MenuBarOptionsChangeLanguage": "Cambiar idioma",
|
||||
"CommonSort": "Orden",
|
||||
"CommonShowNames": "Mostrar nombres",
|
||||
"CommonFavorite": "Favorito",
|
||||
"OrderAscending": "Ascendente",
|
||||
"OrderDescending": "Descendente",
|
||||
"SettingsTabGraphicsFeatures": "Funcionalidades & Mejoras",
|
||||
"SettingsTabGraphicsFeatures": "Funcionalidades Y Mejoras",
|
||||
"ErrorWindowTitle": "Ventana de error",
|
||||
"ToggleDiscordTooltip": "Elige si muestras Ryujinx o no en tu actividad de Discord cuando lo estés usando",
|
||||
"AddGameDirBoxTooltip": "Elige un directorio de juegos para mostrar en la ventana principal",
|
||||
@ -476,7 +480,7 @@
|
||||
"GridSize": "Tamaño de cuadrícula",
|
||||
"GridSizeTooltip": "Cambia el tamaño de los objetos en la cuadrícula",
|
||||
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "Portugués brasileño",
|
||||
"AboutRyujinxContributorsButtonHeader": "Ver todos los contribuidores",
|
||||
"AboutRyujinxContributorsButtonHeader": "Ver todos los contribuidores",
|
||||
"SettingsTabSystemAudioVolume": "Volumen: ",
|
||||
"AudioVolumeTooltip": "Ajusta el nivel de volumen",
|
||||
"SettingsTabSystemEnableInternetAccess": "Conectar guest a Internet/Modo LAN",
|
||||
@ -487,7 +491,7 @@
|
||||
"DialogStopEmulationTitle": "Ryujinx - Detener emulación",
|
||||
"DialogStopEmulationMessage": "¿Seguro que quieres detener la emulación actual?",
|
||||
"SettingsTabCpu": "CPU",
|
||||
"SettingsTabAudio": "Audio",
|
||||
"SettingsTabAudio": "Sonido",
|
||||
"SettingsTabNetwork": "Red",
|
||||
"SettingsTabNetworkConnection": "Conexión de red",
|
||||
"SettingsTabCpuCache": "Caché de CPU",
|
||||
@ -559,7 +563,7 @@
|
||||
"AvatarWindowTitle": "Administrar cuentas - Avatar",
|
||||
"Amiibo": "Amiibo",
|
||||
"Unknown": "Desconocido",
|
||||
"Usage": "Usage",
|
||||
"Usage": "Uso",
|
||||
"Writable": "Escribible",
|
||||
"SelectDlcDialogTitle": "Selecciona archivo(s) de DLC",
|
||||
"SelectUpdateDialogTitle": "Selecciona archivo(s) de actualización",
|
||||
@ -569,7 +573,42 @@
|
||||
"UpdateWindowTitle": "Administrar actualizaciones",
|
||||
"CheatWindowHeading": "Cheats disponibles para {0} [{1}]",
|
||||
"DlcWindowHeading": "Contenido descargable disponible para {0} [{1}]",
|
||||
"UserProfilesEditProfile": "Editar selección",
|
||||
"Cancel": "Cancelar",
|
||||
"Save": "Guardar",
|
||||
"Discard": "Descartar",
|
||||
"UserProfilesSetProfileImage": "Elegir Imagen de Perfil ",
|
||||
"UserProfileEmptyNameError": "El nombre es obligatorio",
|
||||
"UserProfileNoImageError": "Debe establecerse la imagen de perfil",
|
||||
"GameUpdateWindowHeading": "Actualizaciones disponibles para {0} [{1}]",
|
||||
"SettingsTabHotkeysResScaleUpHotkey": "Aumentar la resolución:",
|
||||
"SettingsTabHotkeysResScaleDownHotkey": "Disminuir la resolución:"
|
||||
"SettingsTabHotkeysResScaleDownHotkey": "Disminuir la resolución:",
|
||||
"UserProfilesName": "Nombre:",
|
||||
"UserProfilesUserId": "Id de Usuario:",
|
||||
"SettingsTabGraphicsBackend": "Fondo de gráficos",
|
||||
"SettingsTabGraphicsBackendTooltip": "Graphics Backend to use",
|
||||
"SettingsEnableTextureRecompression": "Enable Texture Recompression",
|
||||
"SettingsEnableTextureRecompressionTooltip": "Compresses certain textures in order to reduce VRAM usage.\n\nRecommended for use with GPUs that have less than 4GiB VRAM.\n\nLeave OFF if unsure.",
|
||||
"SettingsTabGraphicsPreferredGpu": "Preferred GPU",
|
||||
"SettingsTabGraphicsPreferredGpuTooltip": "Select the graphics card that will be used with the Vulkan graphics backend.\n\nDoes not affect the GPU that OpenGL will use.\n\nSet to the GPU flagged as \"dGPU\" if unsure. If there isn't one, leave untouched.",
|
||||
"SettingsAppRequiredRestartMessage": "Ryujinx Restart Required",
|
||||
"SettingsGpuBackendRestartMessage": "Graphics Backend or GPU settings have been modified. This will require a restart to be applied",
|
||||
"SettingsGpuBackendRestartSubMessage": "Do you want to restart now?",
|
||||
"RyujinxUpdaterMessage": "Do you want to update Ryujinx to the latest version?",
|
||||
"SettingsTabHotkeysVolumeUpHotkey": "Increase Volume:",
|
||||
"SettingsTabHotkeysVolumeDownHotkey": "Decrease Volume:",
|
||||
"SettingsEnableMacroHLE": "Enable Macro HLE",
|
||||
"SettingsEnableMacroHLETooltip": "High-level emulation of GPU Macro code.\n\nImproves performance, but may cause graphical glitches in some games.\n\nLeave ON if unsure.",
|
||||
"VolumeShort": "Vol",
|
||||
"UserProfilesManageSaves": "Manage Saves",
|
||||
"DeleteUserSave": "Do you want to delete user save for this game?",
|
||||
"IrreversibleActionNote": "This action is not reversible.",
|
||||
"SaveManagerHeading": "Manage Saves for {0}",
|
||||
"SaveManagerTitle": "Save Manager",
|
||||
"Name": "Name",
|
||||
"Size": "Size",
|
||||
"Search": "Search",
|
||||
"UserProfilesRecoverLostAccounts": "Recover Lost Accounts",
|
||||
"Recover": "Recover",
|
||||
"UserProfilesRecoverHeading": "Saves were found for the following accounts"
|
||||
}
|
||||
|
@ -1,9 +1,17 @@
|
||||
{
|
||||
"Language": "Français",
|
||||
"MenuBarFileOpenApplet": "Ouvrir Applet",
|
||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Ouvrir l'Applet Mii Editor en mode Standalone",
|
||||
"SettingsTabInputDirectMouseAccess": "Accès direct à la souris",
|
||||
"SettingsTabSystemMemoryManagerMode": "Mode de gestion mémoire :",
|
||||
"SettingsTabSystemMemoryManagerModeSoftware": "Logiciel",
|
||||
"SettingsTabSystemMemoryManagerModeHost": "Hôte (rapide)",
|
||||
"SettingsTabSystemMemoryManagerModeHostUnchecked": "Hôte non vérifié (plus rapide, non sécurisé)",
|
||||
"MenuBarFile": "_Fichier",
|
||||
"MenuBarFileOpenFromFile": "_Charger un jeu depuis un fichier",
|
||||
"MenuBarFileOpenUnpacked": "Charger un jeu _extrait",
|
||||
"MenuBarFileOpenEmuFolder": "Ouvrir le dossier Ryujinx",
|
||||
"MenuBarFileOpenLogsFolder": "Ouvrir le dossier de Logs",
|
||||
"MenuBarFileOpenLogsFolder": "Ouvrir le dossier des journaux",
|
||||
"MenuBarFileExit": "_Quitter",
|
||||
"MenuBarOptions": "Options",
|
||||
"MenuBarOptionsToggleFullscreen": "Basculer en plein écran",
|
||||
@ -34,10 +42,10 @@
|
||||
"GameListHeaderPath": "Chemin",
|
||||
"GameListContextMenuOpenUserSaveDirectory": "Ouvrir le dossier de sauvegarde utilisateur",
|
||||
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Ouvre le dossier contenant la sauvegarde utilisateur du jeu",
|
||||
"GameListContextMenuOpenUserDeviceDirectory": "Ouvrir le dossier de sauvegarde console",
|
||||
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Ouvre le dossier contenant la sauvegarde console du jeu",
|
||||
"GameListContextMenuOpenUserBcatDirectory": "Ouvrir le dossier de sauvegarde BCAT",
|
||||
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Ouvre le dossier contenant la sauvegarde BCAT du jeu",
|
||||
"GameListContextMenuOpenDeviceSaveDirectory": "Ouvrir le dossier de sauvegarde console",
|
||||
"GameListContextMenuOpenDeviceSaveDirectoryToolTip": "Ouvre le dossier contenant la sauvegarde console du jeu",
|
||||
"GameListContextMenuOpenBcatSaveDirectory": "Ouvrir le dossier de sauvegarde BCAT",
|
||||
"GameListContextMenuOpenBcatSaveDirectoryToolTip": "Ouvre le dossier contenant la sauvegarde BCAT du jeu",
|
||||
"GameListContextMenuManageTitleUpdates": "Gérer les mises à jour",
|
||||
"GameListContextMenuManageTitleUpdatesToolTip": "Ouvre la fenêtre de gestion des mises à jour",
|
||||
"GameListContextMenuManageDlc": "Gérer les DLC",
|
||||
@ -73,7 +81,7 @@
|
||||
"SettingsTabGeneralAdd": "Ajouter",
|
||||
"SettingsTabGeneralRemove": "Supprimer",
|
||||
"SettingsTabSystem": "Système",
|
||||
"SettingsTabSystemCore": "Core",
|
||||
"SettingsTabSystemCore": "Cœur",
|
||||
"SettingsTabSystemSystemRegion": "Région du système:",
|
||||
"SettingsTabSystemSystemRegionJapan": "Japon",
|
||||
"SettingsTabSystemSystemRegionUSA": "USA",
|
||||
@ -105,13 +113,13 @@
|
||||
"SettingsTabSystemEnableVsync": "Activer la VSync",
|
||||
"SettingsTabSystemEnablePptc": "Activer le PPTC (Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "Activer la vérification de l'intégrité du système de fichiers",
|
||||
"SettingsTabSystemAudioBackend": "Bibliothèque Audio:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Dummy",
|
||||
"SettingsTabSystemAudioBackend": "Bibliothèque Audio :",
|
||||
"SettingsTabSystemAudioBackendDummy": "Factice",
|
||||
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
|
||||
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
|
||||
"SettingsTabSystemAudioBackendSDL2": "SDL2",
|
||||
"SettingsTabSystemHacks": "Hacks",
|
||||
"SettingsTabSystemHacksNote": " (Cela peut causer des instabilitées)",
|
||||
"SettingsTabSystemHacksNote": " (Cela peut causer des instabilités)",
|
||||
"SettingsTabSystemExpandDramSize": "Augmenter la taille de la DRAM à 6GiB",
|
||||
"SettingsTabSystemIgnoreMissingServices": "Ignorer les services manquant",
|
||||
"SettingsTabGraphics": "Graphique",
|
||||
@ -119,16 +127,16 @@
|
||||
"SettingsTabGraphicsEnableShaderCache": "Activer le cache des shaders",
|
||||
"SettingsTabGraphicsAnisotropicFiltering": "Filtrage anisotrope:",
|
||||
"SettingsTabGraphicsAnisotropicFilteringAuto": "Auto",
|
||||
"SettingsTabGraphicsAnisotropicFiltering2x": "2x",
|
||||
"SettingsTabGraphicsAnisotropicFiltering4x": "4x",
|
||||
"SettingsTabGraphicsAnisotropicFiltering8x": "8x",
|
||||
"SettingsTabGraphicsAnisotropicFiltering16x": "16x",
|
||||
"SettingsTabGraphicsAnisotropicFiltering2x": "x2",
|
||||
"SettingsTabGraphicsAnisotropicFiltering4x": "x4",
|
||||
"SettingsTabGraphicsAnisotropicFiltering8x": "x8",
|
||||
"SettingsTabGraphicsAnisotropicFiltering16x": "x16",
|
||||
"SettingsTabGraphicsResolutionScale": "Échelle de résolution:",
|
||||
"SettingsTabGraphicsResolutionScaleCustom": "Customisée (Non recommandée)",
|
||||
"SettingsTabGraphicsResolutionScaleNative": "Native (720p/1080p)",
|
||||
"SettingsTabGraphicsResolutionScale2x": "2x (1440p/2160p)",
|
||||
"SettingsTabGraphicsResolutionScale3x": "3x (2160p/3240p)",
|
||||
"SettingsTabGraphicsResolutionScale4x": "4x (2880p/4320p)",
|
||||
"SettingsTabGraphicsResolutionScaleNative": "Natif (720p/1080p)",
|
||||
"SettingsTabGraphicsResolutionScale2x": "x2 (1440p/2160p)",
|
||||
"SettingsTabGraphicsResolutionScale3x": "x3 (2160p/3240p)",
|
||||
"SettingsTabGraphicsResolutionScale4x": "x4 (2880p/4320p)",
|
||||
"SettingsTabGraphicsAspectRatio": "Format:",
|
||||
"SettingsTabGraphicsAspectRatio4x3": "4:3",
|
||||
"SettingsTabGraphicsAspectRatio16x9": "16:9",
|
||||
@ -138,7 +146,6 @@
|
||||
"SettingsTabGraphicsAspectRatioStretch": "Écran étiré",
|
||||
"SettingsTabGraphicsDeveloperOptions": "Options développeur",
|
||||
"SettingsTabGraphicsShaderDumpPath": "Chemin du dossier de dump des shaders:",
|
||||
"SettingsTabGraphicsFeatures": "Fonctionnalités & Améliorations",
|
||||
"SettingsTabLogging": "Journaux",
|
||||
"SettingsTabLoggingLogging": "Journaux",
|
||||
"SettingsTabLoggingEnableLoggingToFile": "Activer la sauvegarde des journaux vers un fichier",
|
||||
@ -146,10 +153,12 @@
|
||||
"SettingsTabLoggingEnableInfoLogs": "Activer les journaux d'informations",
|
||||
"SettingsTabLoggingEnableWarningLogs": "Activer les journaux d'avertissements",
|
||||
"SettingsTabLoggingEnableErrorLogs": "Activer les journaux d'erreurs",
|
||||
"SettingsTabLoggingEnableTraceLogs": "Activer journaux d'erreurs Trace",
|
||||
"SettingsTabLoggingEnableGuestLogs": "Activer les journaux du programme simulé",
|
||||
"SettingsTabLoggingEnableFsAccessLogs": "Activer les journaux des accès au système de fichiers",
|
||||
"SettingsTabLoggingFsGlobalAccessLogMode": "Niveau des journaux des accès au système de fichiers:",
|
||||
"SettingsTabLoggingDeveloperOptions": "Options développeur (ATTENTION: Cela peut réduire les performances)",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevel": "Niveau du journal du backend graphique :",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Aucun",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelError": "Erreur",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Ralentissements",
|
||||
@ -219,11 +228,11 @@
|
||||
"ControllerSettingsRStickInvertXAxis": "Inverser l'axe X",
|
||||
"ControllerSettingsRStickInvertYAxis": "Inverser l'axe Y",
|
||||
"ControllerSettingsRStickDeadzone": "Zone morte:",
|
||||
"ControllerSettingsTriggers": "Gachettes",
|
||||
"ControllerSettingsTriggersLeft": "Gachettes Gauche",
|
||||
"ControllerSettingsTriggersRight": "Gachettes Droite",
|
||||
"ControllerSettingsTriggersButtonsLeft": "Boutons Gachettes Gauche",
|
||||
"ControllerSettingsTriggersButtonsRight": "Boutons Gachettes Droite",
|
||||
"ControllerSettingsTriggers": "Gachettes",
|
||||
"ControllerSettingsTriggerL": "L",
|
||||
"ControllerSettingsTriggerR": "R",
|
||||
"ControllerSettingsTriggerZL": "ZL",
|
||||
@ -237,7 +246,6 @@
|
||||
"ControllerSettingsMisc": "Divers",
|
||||
"ControllerSettingsTriggerThreshold": "Seuil de gachettes:",
|
||||
"ControllerSettingsMotion": "Mouvements",
|
||||
"ControllerSettingsConfigureGeneral": "Configurer",
|
||||
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "Utiliser un capteur de mouvements CemuHook",
|
||||
"ControllerSettingsMotionControllerSlot": "Contrôleur ID:",
|
||||
"ControllerSettingsMotionMirrorInput": "Inverser les contrôles",
|
||||
@ -252,7 +260,7 @@
|
||||
"UserProfilesChangeProfileImage": "Changer l'image du profil",
|
||||
"UserProfilesAvailableUserProfiles": "Profils utilisateurs disponible:",
|
||||
"UserProfilesAddNewProfile": "Ajouter un nouveau profil",
|
||||
"UserProfilesDeleteSelectedProfile": "Supprimer le profil sélectionné",
|
||||
"UserProfilesDelete": "Supprimer",
|
||||
"UserProfilesClose": "Fermer",
|
||||
"ProfileImageSelectionTitle": "Sélection de l'image du profil",
|
||||
"ProfileImageSelectionHeader": "Choisir l'image du profil",
|
||||
@ -268,6 +276,339 @@
|
||||
"AvatarChoose": "Choisir",
|
||||
"AvatarSetBackgroundColor": "Choisir une couleur de fond",
|
||||
"AvatarClose": "Fermer",
|
||||
"ControllerMotionTitle": "Motion Control Settings",
|
||||
"ControllerRumbleTitle": "Rumble Settings"
|
||||
"ControllerSettingsLoadProfileToolTip": "Charger un profil",
|
||||
"ControllerSettingsAddProfileToolTip": "Ajouter un profil",
|
||||
"ControllerSettingsRemoveProfileToolTip": "Supprimer un profil",
|
||||
"ControllerSettingsSaveProfileToolTip": "Enregistrer un profil",
|
||||
"MenuBarFileToolsTakeScreenshot": "Prendre une Capture d'Écran",
|
||||
"MenuBarFileToolsHideUi": "Masquer l'interface utilisateur",
|
||||
"GameListContextMenuToggleFavorite": "Ajouter/Retirer des favoris",
|
||||
"GameListContextMenuToggleFavoriteToolTip": "Activer/désactiver le statut favori du jeu",
|
||||
"SettingsTabGeneralTheme": "Thème",
|
||||
"SettingsTabGeneralThemeCustomTheme": "Chemin du thème personnalisé",
|
||||
"SettingsTabGeneralThemeBaseStyle": "Style par défaut",
|
||||
"SettingsTabGeneralThemeBaseStyleDark": "Sombre",
|
||||
"SettingsTabGeneralThemeBaseStyleLight": "Lumière",
|
||||
"SettingsTabGeneralThemeEnableCustomTheme": "Activer un Thème Personnalisé",
|
||||
"ButtonBrowse": "Parcourir",
|
||||
"ControllerSettingsConfigureGeneral": "Configurer",
|
||||
"ControllerSettingsRumble": "Vibreur",
|
||||
"ControllerSettingsRumbleStrongMultiplier": "Multiplicateur de vibrations fortes",
|
||||
"ControllerSettingsRumbleWeakMultiplier": "Multiplicateur de vibrations faibles",
|
||||
"DialogMessageSaveNotAvailableMessage": "Il n'y a aucune sauvegarde pour {0} [{1:x16}]",
|
||||
"DialogMessageSaveNotAvailableCreateSaveMessage": "Voulez-vous créer une sauvegarde pour ce jeu ?",
|
||||
"DialogConfirmationTitle": "Ryujinx - Confirmation",
|
||||
"DialogUpdaterTitle": "Ryujinx - Mise à Jour",
|
||||
"DialogErrorTitle": "Ryujinx - Erreur",
|
||||
"DialogWarningTitle": "Ryujinx - Avertissement",
|
||||
"DialogExitTitle": "Ryujinx - Quitter",
|
||||
"DialogErrorMessage": "Ryujinx a rencontré une erreur",
|
||||
"DialogExitMessage": "Êtes-vous sûr de vouloir fermer Ryujinx ?",
|
||||
"DialogExitSubMessage": "Toute progression non sauvegardée sera perdue.",
|
||||
"DialogMessageCreateSaveErrorMessage": "Une erreur s'est produite lors de la création de la sauvegarde spécifiée : {0}",
|
||||
"DialogMessageFindSaveErrorMessage": "Une erreur s'est produite lors de la recherche de la sauvegarde spécifiée : {0}",
|
||||
"FolderDialogExtractTitle": "Choisissez le dossier dans lequel extraire",
|
||||
"DialogNcaExtractionMessage": "Extraction de la section {0} depuis {1}...",
|
||||
"DialogNcaExtractionTitle": "Ryujinx - Extracteur de la section NCA",
|
||||
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "Échec de l'extraction. Le NCA principal n'était pas présent dans le fichier sélectionné.",
|
||||
"DialogNcaExtractionCheckLogErrorMessage": "Échec de l'extraction. Lisez le fichier journal pour plus d'informations.",
|
||||
"DialogNcaExtractionSuccessMessage": "Extraction terminée avec succès.",
|
||||
"DialogUpdaterConvertFailedMessage": "Échec de la conversion de la version actuelle de Ryujinx.",
|
||||
"DialogUpdaterCancelUpdateMessage": "Annuler la mise à jour!",
|
||||
"DialogUpdaterAlreadyOnLatestVersionMessage": "Vous utilisez déjà la version la plus mise à jour de Ryujinx!",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "Une erreur s'est produite lors de la tentative d'obtention des informations de publication de la version GitHub. Cela peut survenir lorsqu'une nouvelle version est en cours de compilation par GitHub Actions. Réessayez dans quelques minutes.",
|
||||
"DialogUpdaterConvertFailedGithubMessage": "Impossible de convertir la version reçue de Ryujinx depuis Github Release.",
|
||||
"DialogUpdaterDownloadingMessage": "Téléchargement de la mise à jour...",
|
||||
"DialogUpdaterExtractionMessage": "Extraction de la mise à jour…",
|
||||
"DialogUpdaterRenamingMessage": "Renommage de la mise à jour...",
|
||||
"DialogUpdaterAddingFilesMessage": "Ajout d'une nouvelle mise à jour...",
|
||||
"DialogUpdaterCompleteMessage": "Mise à jour terminée !",
|
||||
"DialogUpdaterRestartMessage": "Voulez-vous redémarrer Ryujinx maintenant ?",
|
||||
"DialogUpdaterArchNotSupportedMessage": "Vous n'utilisez pas d'architecture système prise en charge !",
|
||||
"DialogUpdaterArchNotSupportedSubMessage": "(Seuls les systèmes x64 sont pris en charge !)",
|
||||
"DialogUpdaterNoInternetMessage": "Vous n'êtes pas connecté à Internet !",
|
||||
"DialogUpdaterNoInternetSubMessage": "Veuillez vérifier que vous avez une connexion Internet fonctionnelle!",
|
||||
"DialogUpdaterDirtyBuildMessage": "Vous ne pouvez pas mettre à jour une version Dirty de Ryujinx!",
|
||||
"DialogUpdaterDirtyBuildSubMessage": "Veuillez télécharger Ryujinx sur https://ryujinx.org/ si vous recherchez une version prise en charge.",
|
||||
"DialogRestartRequiredMessage": "Redémarrage Requis",
|
||||
"DialogThemeRestartMessage": "Le thème a été enregistré. Un redémarrage est requis pour appliquer le thème.",
|
||||
"DialogThemeRestartSubMessage": "Voulez-vous redémarrer",
|
||||
"DialogFirmwareInstallEmbeddedMessage": "Voulez-vous installer le firmware intégré dans ce jeu ? (Firmware {0})",
|
||||
"DialogFirmwareInstallEmbeddedSuccessMessage": "Aucun firmware installé n'a été trouvé mais Ryujinx a pu installer le firmware {0} à partir du jeu fourni.\\nL'émulateur va maintenant démarrer.",
|
||||
"DialogFirmwareNoFirmwareInstalledMessage": "Aucun Firmware installé",
|
||||
"DialogFirmwareInstalledMessage": "Le firmware {0} a été installé",
|
||||
"DialogOpenSettingsWindowLabel": "Ouvrir la fenêtre de configuration",
|
||||
"DialogControllerAppletTitle": "Controller Applet",
|
||||
"DialogMessageDialogErrorExceptionMessage": "Erreur lors de l'affichage de la boîte de dialogue : {0}",
|
||||
"DialogSoftwareKeyboardErrorExceptionMessage": "Erreur lors de l'affichage du clavier logiciel: {0}",
|
||||
"DialogErrorAppletErrorExceptionMessage": "Erreur lors de l'affichage de la boîte de dialogue ErrorApplet: {0}",
|
||||
"DialogUserErrorDialogMessage": "{0}: {1}",
|
||||
"DialogUserErrorDialogInfoMessage": "\nPour plus d'informations sur la manière de corriger cette erreur, suivez notre Guide d'Installation.",
|
||||
"DialogUserErrorDialogTitle": "Erreur Ryujinx ({0})",
|
||||
"DialogAmiiboApiTitle": "Amiibo API",
|
||||
"DialogAmiiboApiFailFetchMessage": "Une erreur est survenue lors de la récupération des informations de l'API.",
|
||||
"DialogAmiiboApiConnectErrorMessage": "Impossible de se connecter au serveur API Amiibo. Le service est peut-être hors service ou vous devriez peut-être vérifier que votre connexion internet est connectée.",
|
||||
"DialogProfileInvalidProfileErrorMessage": "Le profil {0} est incompatible avec le système de configuration de manette actuel.",
|
||||
"DialogProfileDefaultProfileOverwriteErrorMessage": "Le profil par défaut ne peut pas être écrasé",
|
||||
"DialogProfileDeleteProfileTitle": "Supprimer le profil",
|
||||
"DialogProfileDeleteProfileMessage": "Cette action est irréversible, êtes-vous sûr de vouloir continuer ?",
|
||||
"DialogWarning": "Avertissement",
|
||||
"DialogPPTCDeletionMessage": "Vous êtes sur le point de mettre en file d'attente une reconstruction PPTC au prochain démarrage de :\n\n{0}\n\nÊtes-vous sûr de vouloir continuer ?",
|
||||
"DialogPPTCDeletionErrorMessage": "Erreur lors de la purge du cache PPTC à {0}: {1}",
|
||||
"DialogShaderDeletionMessage": "Vous êtes sur le point de supprimer le cache du Shader pour :\n\n{0}\n\nÊtes-vous sûr de vouloir continuer ?",
|
||||
"DialogShaderDeletionErrorMessage": "Erreur lors de la purge du cache du Shader à {0}: {1}",
|
||||
"DialogRyujinxErrorMessage": "Ryujinx a rencontré une erreur",
|
||||
"DialogInvalidTitleIdErrorMessage": "Erreur d'UI : le jeu sélectionné n'a pas d'ID de titre valide",
|
||||
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "Un firmware valide n'a pas été trouvé dans {0}.",
|
||||
"DialogFirmwareInstallerFirmwareInstallTitle": "Installer le Firmware {0}",
|
||||
"DialogFirmwareInstallerFirmwareInstallMessage": "La version {0} du système sera installée.",
|
||||
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\nCela remplacera la version actuelle du système {0}.",
|
||||
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nVoulez-vous continuer ?",
|
||||
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Installation du firmware...",
|
||||
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Version du système {0} installée avec succès.",
|
||||
"DialogUserProfileDeletionWarningMessage": "Il n'y aurait aucun autre profil à ouvrir si le profil sélectionné est supprimé",
|
||||
"DialogUserProfileDeletionConfirmMessage": "Voulez-vous supprimer le profil sélectionné ?",
|
||||
"DialogControllerSettingsModifiedConfirmMessage": "Les paramètres actuels du contrôleur ont été mis à jour.",
|
||||
"DialogControllerSettingsModifiedConfirmSubMessage": "Voulez-vous sauvegarder?",
|
||||
"DialogDlcLoadNcaErrorMessage": "{0}. Fichier erroné : {1}",
|
||||
"DialogDlcNoDlcErrorMessage": "Le fichier spécifié ne contient pas de DLC pour le titre sélectionné !",
|
||||
"DialogPerformanceCheckLoggingEnabledMessage": "Vous avez activé la journalisation des traces, conçue pour être utilisée uniquement par les développeurs.",
|
||||
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "Pour des performances optimales, il est recommandé de désactiver la journalisation des traces. Souhaitez-vous désactiver la journalisation des traces maintenant ?",
|
||||
"DialogPerformanceCheckShaderDumpEnabledMessage": "Vous avez activé l'extraction des shaders, qui est conçu pour être utilisé par les développeurs uniquement.",
|
||||
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "Pour des performances optimales, il est recommandé de désactiver l'extraction des shaders. Souhaitez-vous désactiver l'extraction des shaders maintenant ?",
|
||||
"DialogLoadAppGameAlreadyLoadedMessage": "Un jeu a déjà été chargé",
|
||||
"DialogLoadAppGameAlreadyLoadedSubMessage": "Veuillez arrêter l'émulation ou fermer l'émulateur avant de lancer un autre jeu.",
|
||||
"DialogUpdateAddUpdateErrorMessage": "Le fichier spécifié ne contient pas de mise à jour pour le titre sélectionné !",
|
||||
"DialogSettingsBackendThreadingWarningTitle": "Avertissement - Backend Threading ",
|
||||
"DialogSettingsBackendThreadingWarningMessage": "Ryujinx doit être redémarré après avoir changé cette option pour qu'elle s'applique complètement. Selon votre plate-forme, vous devrez peut-être désactiver manuellement le multithreading de votre pilote lorsque vous utilisez Ryujinx.",
|
||||
"SettingsTabGraphicsFeaturesOptions": "Fonctionnalités",
|
||||
"SettingsTabGraphicsBackendMultithreading": "Interface graphique multithread",
|
||||
"CommonAuto": "Auto",
|
||||
"CommonOff": "Désactivé",
|
||||
"CommonOn": "Activé",
|
||||
"InputDialogYes": "Oui",
|
||||
"InputDialogNo": "Non",
|
||||
"DialogProfileInvalidProfileNameErrorMessage": "Le nom du fichier contient des caractères invalides. Veuillez réessayer.",
|
||||
"MenuBarOptionsPauseEmulation": "Suspendre",
|
||||
"MenuBarOptionsResumeEmulation": "Reprendre",
|
||||
"AboutUrlTooltipMessage": "Cliquez pour ouvrir le site de Ryujinx dans votre navigateur par défaut.",
|
||||
"AboutDisclaimerMessage": "Ryujinx n'est pas affilié à Nintendo™,\nou à aucun de ses partenaires, de quelque manière que ce soit.",
|
||||
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) est utilisé\ndans notre émulation Amiibo.",
|
||||
"AboutPatreonUrlTooltipMessage": "Cliquez pour ouvrir la page Patreon de Ryujinx dans votre navigateur par défaut.",
|
||||
"AboutGithubUrlTooltipMessage": "Cliquez pour ouvrir la page GitHub de Ryujinx dans votre navigateur par défaut.",
|
||||
"AboutDiscordUrlTooltipMessage": "Cliquez pour ouvrir une invitation au serveur Discord de Ryujinx dans votre navigateur par défaut.",
|
||||
"AboutTwitterUrlTooltipMessage": "Cliquez pour ouvrir la page Twitter de Ryujinx dans votre navigateur par défaut.",
|
||||
"AboutRyujinxAboutTitle": "Á propos:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx est un émulateur pour la Nintendo Switch™.\nMerci de nous soutenir sur Patreon.\nObtenez toutes les dernières actualités sur notre Twitter ou notre Discord.\nLes développeurs intéressés à contribuer peuvent en savoir plus sur notre GitHub ou notre Discord.",
|
||||
"AboutRyujinxMaintainersTitle": "Maintenu par :",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "Cliquez pour ouvrir la page Contributeurs dans votre navigateur par défaut.",
|
||||
"AboutRyujinxSupprtersTitle": "Supporté sur Patreon par :",
|
||||
"AmiiboSeriesLabel": "Séries Amiibo",
|
||||
"AmiiboCharacterLabel": "Personnage",
|
||||
"AmiiboScanButtonLabel": "Scanner",
|
||||
"AmiiboOptionsShowAllLabel": "Afficher tous les Amiibo",
|
||||
"AmiiboOptionsUsRandomTagLabel": "Hack : Utiliser un tag Uuid aléatoire",
|
||||
"DlcManagerTableHeadingEnabledLabel": "Activé",
|
||||
"DlcManagerTableHeadingTitleIdLabel": "ID du titre",
|
||||
"DlcManagerTableHeadingContainerPathLabel": "Chemin du conteneur",
|
||||
"DlcManagerTableHeadingFullPathLabel": "Chemin complet",
|
||||
"DlcManagerRemoveAllButton": "Tout supprimer",
|
||||
"DlcManagerEnableAllButton": "Activer Tout",
|
||||
"DlcManagerDisableAllButton": "Désactiver Tout",
|
||||
"MenuBarOptionsChangeLanguage": "Changer la Langue",
|
||||
"CommonSort": "Trier",
|
||||
"CommonShowNames": "Afficher les noms",
|
||||
"CommonFavorite": "Favoris",
|
||||
"OrderAscending": "Croissant",
|
||||
"OrderDescending": "Décroissant",
|
||||
"SettingsTabGraphicsFeatures": "Fonctionnalités & Améliorations",
|
||||
"ErrorWindowTitle": "Fenêtre d'erreur",
|
||||
"ToggleDiscordTooltip": "Choisissez d'afficher ou non Ryujinx sur votre activité « en cours de jeu » Discord",
|
||||
"AddGameDirBoxTooltip": "Entrez un répertoire de jeux à ajouter à la liste",
|
||||
"AddGameDirTooltip": "Ajouter un répertoire de jeux à la liste",
|
||||
"RemoveGameDirTooltip": "Supprimer le dossier sélectionné",
|
||||
"CustomThemeCheckTooltip": "Use a custom Avalonia theme for the GUI to change the appearance of the emulator menus",
|
||||
"CustomThemePathTooltip": "Chemin vers le thème personnalisé de l'interface utilisateur",
|
||||
"CustomThemeBrowseTooltip": "Parcourir vers un thème personnalisé pour l'interface utilisateur",
|
||||
"DockModeToggleTooltip": "Le mode station d'accueil permet à la console émulée de se comporter comme une Nintendo Switch en mode station d'accueil, ce qui améliore la fidélité graphique dans la plupart des jeux. Inversement, la désactivation de cette option rendra la console émulée comme une console Nintendo Switch portable, réduisant la qualité graphique.\n\nConfigurer les controles du joueur 1 si vous prévoyez d'utiliser le mode station d'accueil; configurez les commandes portable si vous prévoyez d'utiliser le mode portable.\n\nLaissez ACTIVER si vous n'êtes pas sûr.",
|
||||
"DirectKeyboardTooltip": "Direct keyboard access (HID) support. Provides games access to your keyboard as a text entry device.",
|
||||
"DirectMouseTooltip": "Direct mouse access (HID) support. Provides games access to your mouse as a pointing device.",
|
||||
"RegionTooltip": "Changer la région du système",
|
||||
"LanguageTooltip": "Changer la langue du système",
|
||||
"TimezoneTooltip": "Changer le fuseau horaire du système",
|
||||
"TimeTooltip": "Changer l'heure du système",
|
||||
"VSyncToggleTooltip": "Emulated console's Vertical Sync. Essentially a frame-limiter for the majority of games; disabling it may cause games to run at higher speed or make loading screens take longer or get stuck.\n\nCan be toggled in-game with a hotkey of your preference. We recommend doing this if you plan on disabling it.\n\nLeave ON if unsure.",
|
||||
"PptcToggleTooltip": "Saves translated JIT functions so that they do not need to be translated every time the game loads.\n\nReduces stuttering and significantly speeds up boot times after the first boot of a game.\n\nLeave ON if unsure.",
|
||||
"FsIntegrityToggleTooltip": "Checks for corrupt files when booting a game, and if corrupt files are detected, displays a hash error in the log.\n\nHas no impact on performance and is meant to help troubleshooting.\n\nLeave ON if unsure.",
|
||||
"AudioBackendTooltip": "Changes the backend used to render audio.\n\nSDL2 is the preferred one, while OpenAL and SoundIO are used as fallbacks. Dummy will have no sound.\n\nSet to SDL2 if unsure.",
|
||||
"MemoryManagerTooltip": "Change how guest memory is mapped and accessed. Greatly affects emulated CPU performance.\n\nSet to HOST UNCHECKED if unsure.",
|
||||
"MemoryManagerSoftwareTooltip": "Use a software page table for address translation. Highest accuracy but slowest performance.",
|
||||
"MemoryManagerHostTooltip": "Directly map memory in the host address space. Much faster JIT compilation and execution.",
|
||||
"MemoryManagerUnsafeTooltip": "Directly map memory, but do not mask the address within the guest address space before access. Faster, but at the cost of safety. The guest application can access memory from anywhere in Ryujinx, so only run programs you trust with this mode.",
|
||||
"DRamTooltip": "Utilizes an alternative MemoryMode layout to mimic a Switch development model.\n\nThis is only useful for higher-resolution texture packs or 4k resolution mods. Does NOT improve performance.\n\nLeave OFF if unsure.",
|
||||
"IgnoreMissingServicesTooltip": "Ignores unimplemented Horizon OS services. This may help in bypassing crashes when booting certain games.\n\nLeave OFF if unsure.",
|
||||
"GraphicsBackendThreadingTooltip": "Executes graphics backend commands on a second thread.\n\nSpeeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.\n\nSet to AUTO if unsure.",
|
||||
"GalThreadingTooltip": "Executes graphics backend commands on a second thread.\n\nSpeeds up shader compilation, reduces stuttering, and improves performance on GPU drivers without multithreading support of their own. Slightly better performance on drivers with multithreading.\n\nSet to AUTO if unsure.",
|
||||
"ShaderCacheToggleTooltip": "Saves a disk shader cache which reduces stuttering in subsequent runs.\n\nLeave ON if unsure.",
|
||||
"ResolutionScaleTooltip": "Resolution Scale applied to applicable render targets",
|
||||
"ResolutionScaleEntryTooltip": "Floating point resolution scale, such as 1.5. Non-integral scales are more likely to cause issues or crash.",
|
||||
"AnisotropyTooltip": "Level of Anisotropic Filtering (set to Auto to use the value requested by the game)",
|
||||
"AspectRatioTooltip": "Ratio d'aspect appliqué à la fenêtre de rendu",
|
||||
"ShaderDumpPathTooltip": "Chemin de copie des Shaders Graphiques",
|
||||
"FileLogTooltip": "Sauver le journal de la console dans un fichier journal sur le disque. Cela n'affecte pas les performances.",
|
||||
"StubLogTooltip": "Prints stub log messages in the console. Does not affect performance.",
|
||||
"InfoLogTooltip": "Prints info log messages in the console. Does not affect performance.",
|
||||
"WarnLogTooltip": "Prints warning log messages in the console. Does not affect performance.",
|
||||
"ErrorLogTooltip": "Prints error log messages in the console. Does not affect performance.",
|
||||
"TraceLogTooltip": "Prints trace log messages in the console. Does not affect performance.",
|
||||
"GuestLogTooltip": "Prints guest log messages in the console. Does not affect performance.",
|
||||
"FileAccessLogTooltip": "Prints file access log messages in the console.",
|
||||
"FSAccessLogModeTooltip": "Enables FS access log output to the console. Possible modes are 0-3",
|
||||
"DeveloperOptionTooltip": "Utiliser avec précaution",
|
||||
"OpenGlLogLevel": "Nécessite l'activation des niveaux de journalisation appropriés",
|
||||
"DebugLogTooltip": "Prints debug log messages in the console.\n\nOnly use this if specifically instructed by a staff member, as it will make logs difficult to read and worsen emulator performance.",
|
||||
"LoadApplicationFileTooltip": "Ouvrir un explorateur de fichiers pour choisir un fichier compatible Switch à charger",
|
||||
"LoadApplicationFolderTooltip": "Ouvrir un explorateur de fichiers pour choisir une application Switch compatible et décompressée à charger",
|
||||
"OpenRyujinxFolderTooltip": "Ouvrir le dossier du système de fichiers Ryujinx",
|
||||
"OpenRyujinxLogsTooltip": "Ouvre le dossier dans lequel les journaux sont écrits",
|
||||
"ExitTooltip": "Quitter Ryujinx",
|
||||
"OpenSettingsTooltip": "Ouvrir la fenêtre de configuration",
|
||||
"OpenProfileManagerTooltip": "Ouvrir la fenêtre du gestionnaire de profils d'utilisateurs",
|
||||
"StopEmulationTooltip": "Arrêter l'émulation du jeu en cours et revenir à la sélection des jeux",
|
||||
"CheckUpdatesTooltip": "Vérifier les mises à jour de Ryujinx",
|
||||
"OpenAboutTooltip": "Ouvrir la fenêtre À Propos",
|
||||
"GridSize": "Taille de la grille",
|
||||
"GridSizeTooltip": "Modifier la taille des éléments de la grille",
|
||||
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "Portugais brésilien",
|
||||
"AboutRyujinxContributorsButtonHeader": "Voir tous les contributeurs",
|
||||
"SettingsTabSystemAudioVolume": "Volume :",
|
||||
"AudioVolumeTooltip": "Modifier le volume audio",
|
||||
"SettingsTabSystemEnableInternetAccess": "Accès Internet Invité/Mode LAN",
|
||||
"EnableInternetAccessTooltip": "Permet à l'application émulée de se connecter à Internet.\n\nLes jeux avec un mode LAN peuvent se connecter les uns aux autres lorsque cette option est cochée et que les systèmes sont connectés au même point d'accès. Cela inclut également les vrais consoles.\n\nCette option n'autorise PAS la connexion aux serveurs Nintendo. Elle peut faire planter certains jeux qui essaient de se connecter à l'Internet.\n\nLaissez DÉSACTIVÉ si vous n'êtes pas sûr.",
|
||||
"GameListContextMenuManageCheatToolTip": "Gérer la triche",
|
||||
"GameListContextMenuManageCheat": "Gérer la triche",
|
||||
"ControllerSettingsStickRange": "Intervalle:",
|
||||
"DialogStopEmulationTitle": "Ryujinx - Arrêt de l'émulation",
|
||||
"DialogStopEmulationMessage": "Êtes-vous sûr de vouloir arrêter l'émulation ?",
|
||||
"SettingsTabCpu": "CPU",
|
||||
"SettingsTabAudio": "Audio",
|
||||
"SettingsTabNetwork": "Réseau",
|
||||
"SettingsTabNetworkConnection": "Connexion réseau",
|
||||
"SettingsTabCpuCache": "Cache CPU",
|
||||
"SettingsTabCpuMemory": "Mémoire CPU",
|
||||
"DialogUpdaterFlatpakNotSupportedMessage": "Merci de mettre à jour Ryujinx via FlatHub.",
|
||||
"UpdaterDisabledWarningTitle": "Mise à jour désactivée !",
|
||||
"GameListContextMenuOpenSdModsDirectory": "Ouvrir le dossier Mods d'Atmosphère",
|
||||
"GameListContextMenuOpenSdModsDirectoryToolTip": "Ouvre le répertoire alternatif de carte SD Atmosphère qui contient les Mods d'Application. Utile pour les mods qui sont conçu pour le vrai matériel.",
|
||||
"ControllerSettingsRotate90": "Rotation 90° horaire",
|
||||
"IconSize": "Taille d'icône",
|
||||
"IconSizeTooltip": "Changer la taille des icônes de jeu",
|
||||
"MenuBarOptionsShowConsole": "Afficher la console",
|
||||
"ShaderCachePurgeError": "Erreur lors de la purge du cache du Shader à {0}: {1}",
|
||||
"UserErrorNoKeys": "Clés introuvables",
|
||||
"UserErrorNoFirmware": "Firmware introuvable",
|
||||
"UserErrorFirmwareParsingFailed": "Erreur d'analyse du firmware",
|
||||
"UserErrorApplicationNotFound": " Application introuvable",
|
||||
"UserErrorUnknown": "Erreur inconnue",
|
||||
"UserErrorUndefined": "Erreur non définie",
|
||||
"UserErrorNoKeysDescription": "Ryujinx n'a pas trouvé votre fichier 'prod.keys'",
|
||||
"UserErrorNoFirmwareDescription": "Ryujinx n'a pas trouvé de firmwares installés",
|
||||
"UserErrorFirmwareParsingFailedDescription": "Ryujinx n'a pas pu analyser le firmware fourni. Cela est généralement dû à des clés obsolètes.",
|
||||
"UserErrorApplicationNotFoundDescription": "Ryujinx n'a pas pu trouver une application valide dans le chemin indiqué.",
|
||||
"UserErrorUnknownDescription": "Une erreur inconnue est survenue!",
|
||||
"UserErrorUndefinedDescription": "Une erreur inconnue est survenue ! Cela ne devrait pas se produire, merci de contacter un développeur !",
|
||||
"OpenSetupGuideMessage": "Ouvrir le guide d'installation",
|
||||
"NoUpdate": "Aucune mise à jour",
|
||||
"TitleUpdateVersionLabel": "Version {0} - {1}",
|
||||
"RyujinxInfo": "Ryujinx - Info",
|
||||
"RyujinxConfirm": "Ryujinx - Confirmation",
|
||||
"FileDialogAllTypes": "Tous les types",
|
||||
"Never": "Jamais",
|
||||
"SwkbdMinCharacters": "Doit comporter au moins {0} caractères",
|
||||
"SwkbdMinRangeCharacters": "Doit contenir {0}-{1} caractères en longueur",
|
||||
"SoftwareKeyboard": "Clavier logiciel",
|
||||
"DialogControllerAppletMessagePlayerRange": "L'application demande {0} joueur(s) avec :\n\nTYPES : {1}\n\nJOUEURS : {2}\n\n{3}Merci d'ouvrir les Paramètres et de reconfigurer les Périphériques maintenant ou appuyez sur Fermer.",
|
||||
"DialogControllerAppletMessage": "L'application demande exactement {0} joueur(s) avec :\n\nTYPES : {1}\n\nJOUEURS : {2}\n\n{3}Merci d'ouvrir les Paramètres et de reconfigurer les Périphériques maintenant ou appuyez sur Fermer.",
|
||||
"DialogControllerAppletDockModeSet": "Mode station d'accueil défini. Le portable est également invalide.\n\n",
|
||||
"UpdaterRenaming": "Renommage des anciens fichiers...",
|
||||
"UpdaterRenameFailed": "Impossible de renommer le fichier : {0}",
|
||||
"UpdaterAddingFiles": "Ajout des nouveaux fichiers...",
|
||||
"UpdaterExtracting": "Extraction de la mise à jour…",
|
||||
"UpdaterDownloading": "Téléchargement de la mise à jour...",
|
||||
"Game": "Jeu",
|
||||
"Docked": "Attaché",
|
||||
"Handheld": "Portable",
|
||||
"ConnectionError": "Erreur de connexion.",
|
||||
"AboutPageDeveloperListMore": "{0} et plus...",
|
||||
"ApiError": "Erreur API.",
|
||||
"LoadingHeading": "Chargement {0}",
|
||||
"CompilingPPTC": "Compilation PTC",
|
||||
"CompilingShaders": "Compilation des Shaders",
|
||||
"AllKeyboards": "Tous les claviers",
|
||||
"OpenFileDialogTitle": "Sélectionnez un fichier supporté à ouvrir",
|
||||
"OpenFolderDialogTitle": "Sélectionnez un dossier avec un jeu décompressé",
|
||||
"AllSupportedFormats": "Tous les formats supportés",
|
||||
"RyujinxUpdater": "Mise à jour de Ryujinx",
|
||||
"SettingsTabHotkeys": "Raccourcis clavier",
|
||||
"SettingsTabHotkeysHotkeys": "Raccourcis clavier",
|
||||
"SettingsTabHotkeysToggleVsyncHotkey": "Activer/désactiver la VSync :",
|
||||
"SettingsTabHotkeysScreenshotHotkey": "Captures d'écran :",
|
||||
"SettingsTabHotkeysShowUiHotkey": "Afficher UI :",
|
||||
"SettingsTabHotkeysPauseHotkey": "Suspendre :",
|
||||
"SettingsTabHotkeysToggleMuteHotkey": "Muet : ",
|
||||
"ControllerMotionTitle": "Réglages du contrôle par mouvement",
|
||||
"ControllerRumbleTitle": "Paramètres de Vibration",
|
||||
"SettingsSelectThemeFileDialogTitle": "Sélectionnez un Fichier de Thème",
|
||||
"SettingsXamlThemeFile": "Fichier thème Xaml",
|
||||
"AvatarWindowTitle": "Gérer les Comptes - Avatar",
|
||||
"Amiibo": "Amiibo",
|
||||
"Unknown": "Inconnu",
|
||||
"Usage": "Utilisation",
|
||||
"Writable": "Ecriture possible",
|
||||
"SelectDlcDialogTitle": "Sélectionner les fichiers DLC",
|
||||
"SelectUpdateDialogTitle": "Sélectionner les fichiers de mise à jour",
|
||||
"UserProfileWindowTitle": "Gestionnaire de profils utilisateur",
|
||||
"CheatWindowTitle": "Gestionnaire de triches",
|
||||
"DlcWindowTitle": "Gestionnaire de contenus téléchargeables",
|
||||
"UpdateWindowTitle": "Gestionnaire de mises à jour",
|
||||
"CheatWindowHeading": "Cheats disponibles pour {0} [{1}]",
|
||||
"DlcWindowHeading": "{0} Contenu(s) téléchargeable(s) disponible pour {1} ({2})",
|
||||
"UserProfilesEditProfile": "Éditer la sélection",
|
||||
"Cancel": "Annuler",
|
||||
"Save": "Enregistrer",
|
||||
"Discard": "Abandonner",
|
||||
"UserProfilesSetProfileImage": "Modifier l'image du profil",
|
||||
"UserProfileEmptyNameError": "Le nom est requis",
|
||||
"UserProfileNoImageError": "L'image du profil doit être définie",
|
||||
"GameUpdateWindowHeading": "{0} mise(s) à jour disponible pour {1} ({2})",
|
||||
"SettingsTabHotkeysResScaleUpHotkey": "Augmenter la résolution:",
|
||||
"SettingsTabHotkeysResScaleDownHotkey": "Diminuer la résolution :",
|
||||
"UserProfilesName": "Nom :",
|
||||
"UserProfilesUserId": "Identifiant de l'utilisateur :",
|
||||
"SettingsTabGraphicsBackend": "API de Rendu",
|
||||
"SettingsTabGraphicsBackendTooltip": "Interface Graphique à utiliser",
|
||||
"SettingsEnableTextureRecompression": "Activer la recompression des textures",
|
||||
"SettingsEnableTextureRecompressionTooltip": "Compresse certaines textures afin de réduire l'utilisation de la VRAM.\n\nRecommandé pour une utilisation avec des GPU qui ont moins de 4 Go de VRAM.\n\nLaissez DÉSACTIVÉ si vous n'êtes pas sûr.",
|
||||
"SettingsTabGraphicsPreferredGpu": "GPU préféré",
|
||||
"SettingsTabGraphicsPreferredGpuTooltip": "Sélectionnez la carte graphique qui sera utilisée avec l'interface graphique Vulkan.\n\nCela ne change pas le GPU qu'OpenGL utilisera.\n\nChoisissez le GPU noté \"dGPU\" si vous n'êtes pas sûr. S'il n'y en a pas, ne pas modifier.",
|
||||
"SettingsAppRequiredRestartMessage": "Redémarrage de Ryujinx requis",
|
||||
"SettingsGpuBackendRestartMessage": "Les paramètres de l'interface graphique ou du GPU ont été modifiés. Cela nécessitera un redémarrage pour être appliqué",
|
||||
"SettingsGpuBackendRestartSubMessage": "\n\nVoulez-vous redémarrer maintenant?",
|
||||
"RyujinxUpdaterMessage": "Voulez-vous mettre à jour Ryujinx vers la dernière version ?",
|
||||
"SettingsTabHotkeysVolumeUpHotkey": "Augmenter le volume :",
|
||||
"SettingsTabHotkeysVolumeDownHotkey": "Diminuer le volume :",
|
||||
"SettingsEnableMacroHLE": "Activer les macros HLE",
|
||||
"SettingsEnableMacroHLETooltip": "Émulation de haut niveau du code de Macro GPU.\n\nAméliore les performances, mais peut causer des bugs graphiques dans certains jeux.\n\nLaissez ACTIVER si vous n'êtes pas sûr.",
|
||||
"VolumeShort": "Vol",
|
||||
"UserProfilesManageSaves": "Gérer les sauvegardes",
|
||||
"DeleteUserSave": "Voulez-vous supprimer la sauvegarde de l'utilisateur pour ce jeu?",
|
||||
"IrreversibleActionNote": "Cette action n'est pas réversible.",
|
||||
"SaveManagerHeading": "Gérer les sauvegardes pour {0}",
|
||||
"SaveManagerTitle": "Gestionnaire de sauvegarde",
|
||||
"Name": "Nom ",
|
||||
"Size": "Taille",
|
||||
"Search": "Rechercher",
|
||||
"UserProfilesRecoverLostAccounts": "Récupérer les comptes perdus",
|
||||
"Recover": "Récupérer",
|
||||
"UserProfilesRecoverHeading": "Des sauvegardes ont été trouvées pour les comptes suivants"
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,5 @@
|
||||
{
|
||||
"Language": "日本語",
|
||||
"MenuBarFileOpenApplet": "アプレットを開く",
|
||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "スタンドアロンモードで Mii エディタアプレットを開きます",
|
||||
"SettingsTabInputDirectMouseAccess": "マウス直接アクセス",
|
||||
@ -41,10 +42,10 @@
|
||||
"GameListHeaderPath": "パス",
|
||||
"GameListContextMenuOpenUserSaveDirectory": "セーブディレクトリを開く",
|
||||
"GameListContextMenuOpenUserSaveDirectoryToolTip": "アプリケーションのユーザセーブデータを格納するディレクトリを開きます",
|
||||
"GameListContextMenuOpenUserDeviceDirectory": "デバイスディレクトリを開く",
|
||||
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "アプリケーションのデバイスセーブデータを格納するディレクトリを開きます",
|
||||
"GameListContextMenuOpenUserBcatDirectory": "BCATディレクトリを開く",
|
||||
"GameListContextMenuOpenUserBcatDirectoryToolTip": "アプリケーションの BCAT セーブデータを格納するディレクトリを開きます",
|
||||
"GameListContextMenuOpenDeviceSaveDirectory": "デバイスディレクトリを開く",
|
||||
"GameListContextMenuOpenDeviceSaveDirectoryToolTip": "アプリケーションのデバイスセーブデータを格納するディレクトリを開きます",
|
||||
"GameListContextMenuOpenBcatSaveDirectory": "BCATディレクトリを開く",
|
||||
"GameListContextMenuOpenBcatSaveDirectoryToolTip": "アプリケーションの BCAT セーブデータを格納するディレクトリを開きます",
|
||||
"GameListContextMenuManageTitleUpdates": "アップデートを管理",
|
||||
"GameListContextMenuManageTitleUpdatesToolTip": "タイトルのアップデート管理ウインドウを開きます",
|
||||
"GameListContextMenuManageDlc": "DLCを管理",
|
||||
@ -157,6 +158,7 @@
|
||||
"SettingsTabLoggingEnableFsAccessLogs": "Fs アクセスログを有効",
|
||||
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs グローバルアクセスログモード:",
|
||||
"SettingsTabLoggingDeveloperOptions": "開発者オプション (警告: パフォーマンスが低下します)",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevel": "グラフィックスバックエンド ログレベル:",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelNone": "なし",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelError": "エラー",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "パフォーマンス低下",
|
||||
@ -167,7 +169,7 @@
|
||||
"SettingsTabInputDirectKeyboardAccess": "キーボード直接アクセス",
|
||||
"SettingsButtonSave": "セーブ",
|
||||
"SettingsButtonClose": "閉じる",
|
||||
"SettingsButtonOk": "オーケー",
|
||||
"SettingsButtonOk": "OK",
|
||||
"SettingsButtonCancel": "キャンセル",
|
||||
"SettingsButtonApply": "適用",
|
||||
"ControllerSettingsPlayer": "プレイヤー",
|
||||
@ -258,7 +260,7 @@
|
||||
"UserProfilesChangeProfileImage": "プロファイル画像を変更",
|
||||
"UserProfilesAvailableUserProfiles": "利用可能なユーザプロファイル:",
|
||||
"UserProfilesAddNewProfile": "プロファイルを作成",
|
||||
"UserProfilesDeleteSelectedProfile": "削除",
|
||||
"UserProfilesDelete": "削除",
|
||||
"UserProfilesClose": "閉じる",
|
||||
"ProfileImageSelectionTitle": "プロファイル画像選択",
|
||||
"ProfileImageSelectionHeader": "プロファイル画像を選択",
|
||||
@ -279,7 +281,7 @@
|
||||
"ControllerSettingsRemoveProfileToolTip": "プロファイルを削除",
|
||||
"ControllerSettingsSaveProfileToolTip": "プロファイルをセーブ",
|
||||
"MenuBarFileToolsTakeScreenshot": "スクリーンショットを撮影",
|
||||
"MenuBarFileToolsHideUi": "UIを隠す",
|
||||
"MenuBarFileToolsHideUi": "Hide UI",
|
||||
"GameListContextMenuToggleFavorite": "お気に入りを切り替え",
|
||||
"GameListContextMenuToggleFavoriteToolTip": "ゲームをお気に入りに含めるかどうかを切り替えます",
|
||||
"SettingsTabGeneralTheme": "テーマ",
|
||||
@ -302,7 +304,7 @@
|
||||
"DialogExitTitle": "Ryujinx - 終了",
|
||||
"DialogErrorMessage": "エラーが発生しました",
|
||||
"DialogExitMessage": "Ryujinx を閉じてよろしいですか?",
|
||||
"DialogExitSubMessage": "セーブされていないのデータはすべて失われます!",
|
||||
"DialogExitSubMessage": "セーブされていないデータはすべて失われます!",
|
||||
"DialogMessageCreateSaveErrorMessage": "セーブデータ: {0} の作成中にエラーが発生しました",
|
||||
"DialogMessageFindSaveErrorMessage": "セーブデータ: {0} の検索中にエラーが発生しました",
|
||||
"FolderDialogExtractTitle": "展開フォルダを選択",
|
||||
@ -314,7 +316,7 @@
|
||||
"DialogUpdaterConvertFailedMessage": "現在の Ryujinx バージョンの変換に失敗しました.",
|
||||
"DialogUpdaterCancelUpdateMessage": "アップデータをキャンセル中!",
|
||||
"DialogUpdaterAlreadyOnLatestVersionMessage": "最新バージョンの Ryujinx を使用中です!",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "Github からのリリース情報取得時にエラーが発生しました. Github Actions でリリースファイルを作成中かもしれません. 後ほどもう一度試してみてください.",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "An error has occurred when trying to get release information from GitHub Release. This can be caused if a new release is being compiled by GitHub Actions. Try again in a few minutes.",
|
||||
"DialogUpdaterConvertFailedGithubMessage": "Github から取得した Ryujinx バージョンの変換に失敗しました.",
|
||||
"DialogUpdaterDownloadingMessage": "アップデートをダウンロード中...",
|
||||
"DialogUpdaterExtractionMessage": "アップデートを展開中...",
|
||||
@ -411,6 +413,8 @@
|
||||
"DlcManagerTableHeadingContainerPathLabel": "コンテナパス",
|
||||
"DlcManagerTableHeadingFullPathLabel": "フルパス",
|
||||
"DlcManagerRemoveAllButton": "すべて削除",
|
||||
"DlcManagerEnableAllButton": "すべて有効",
|
||||
"DlcManagerDisableAllButton": "すべて無効",
|
||||
"MenuBarOptionsChangeLanguage": "言語を変更",
|
||||
"CommonSort": "並べ替え",
|
||||
"CommonShowNames": "名称を表示",
|
||||
@ -575,12 +579,12 @@
|
||||
"Discard": "破棄",
|
||||
"UserProfilesSetProfileImage": "プロファイル画像を設定",
|
||||
"UserProfileEmptyNameError": "名称が必要です",
|
||||
"UserProfileNoImageError": "プロファイル画像が必要です",
|
||||
"UserProfileNoImageError": "プロファイル画像が必要です",
|
||||
"GameUpdateWindowHeading": "利用可能なアップデート {0} [{1}]",
|
||||
"SettingsTabHotkeysResScaleUpHotkey": "解像度を上げる:",
|
||||
"SettingsTabHotkeysResScaleDownHotkey": "解像度を下げる:",
|
||||
"UserProfilesName": "名称:",
|
||||
"UserProfilesUserId" : "ユーザID:",
|
||||
"UserProfilesUserId": "ユーザID:",
|
||||
"SettingsTabGraphicsBackend": "グラフィックスバックエンド",
|
||||
"SettingsTabGraphicsBackendTooltip": "使用するグラフィックスバックエンドです",
|
||||
"SettingsEnableTextureRecompression": "テクスチャの再圧縮を有効",
|
||||
@ -589,5 +593,22 @@
|
||||
"SettingsTabGraphicsPreferredGpuTooltip": "Vulkanグラフィックスバックエンドで使用されるグラフィックスカードを選択します.\n\nOpenGLが使用するGPUには影響しません.\n\n不明な場合は, \"dGPU\" としてフラグが立っているGPUに設定します. ない場合はそのままにします.",
|
||||
"SettingsAppRequiredRestartMessage": "Ryujinx の再起動が必要です",
|
||||
"SettingsGpuBackendRestartMessage": "グラフィックスバックエンドまたはGPUの設定が変更されました. 変更を適用するには再起動する必要があります",
|
||||
"SettingsGpuBackendRestartSubMessage": "今すぐ再起動しますか?"
|
||||
"SettingsGpuBackendRestartSubMessage": "今すぐ再起動しますか?",
|
||||
"RyujinxUpdaterMessage": "Ryujinx を最新版にアップデートしますか?",
|
||||
"SettingsTabHotkeysVolumeUpHotkey": "音量を上げる:",
|
||||
"SettingsTabHotkeysVolumeDownHotkey": "音量を下げる:",
|
||||
"SettingsEnableMacroHLE": "マクロの高レベルエミュレーション (HLE) を有効",
|
||||
"SettingsEnableMacroHLETooltip": "GPU マクロコードの高レベルエミュレーションです.\n\nパフォーマンスを向上させますが, 一部のゲームでグラフィックに不具合が発生する可能性があります.\n\nよくわからない場合はオンのままにしてください.",
|
||||
"VolumeShort": "音量",
|
||||
"UserProfilesManageSaves": "セーブデータの管理",
|
||||
"DeleteUserSave": "このゲームのユーザセーブデータを削除しますか?",
|
||||
"IrreversibleActionNote": "この操作は元に戻せません.",
|
||||
"SaveManagerHeading": "{0} のセーブデータを管理",
|
||||
"SaveManagerTitle": "セーブデータマネージャ",
|
||||
"Name": "名称",
|
||||
"Size": "サイズ",
|
||||
"Search": "検索",
|
||||
"UserProfilesRecoverLostAccounts": "アカウントの復旧",
|
||||
"Recover": "復旧",
|
||||
"UserProfilesRecoverHeading": "以下のアカウントのセーブデータが見つかりました"
|
||||
}
|
||||
|
@ -1,87 +1,88 @@
|
||||
{
|
||||
"Language": "한국어",
|
||||
"MenuBarFileOpenApplet": "애플릿 열기",
|
||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "독립 실행형 모드에서 Mii 편집기 애플릿 열기",
|
||||
"SettingsTabInputDirectMouseAccess": "직접 마우스 액세스",
|
||||
"SettingsTabInputDirectMouseAccess": "직접 마우스 접속",
|
||||
"SettingsTabSystemMemoryManagerMode": "메모리 관리자 모드 :",
|
||||
"SettingsTabSystemMemoryManagerModeSoftware": "소프트웨어",
|
||||
"SettingsTabSystemMemoryManagerModeHost": "호스트 (빠른)",
|
||||
"SettingsTabSystemMemoryManagerModeHostUnchecked": "호스트가 확인되지 않음 (가장 빠르고 안전하지 않은)",
|
||||
"SettingsTabSystemMemoryManagerModeHost": "호스트 (빠름)",
|
||||
"SettingsTabSystemMemoryManagerModeHostUnchecked": "호스트가 확인되지 않음 (가장 빠르나 안전하지 않음)",
|
||||
"MenuBarFile": "_파일",
|
||||
"MenuBarFileOpenFromFile": "_서류철음에서 애플리케이션 로드",
|
||||
"MenuBarFileOpenUnpacked": "_압축을 푼 게임 로드",
|
||||
"MenuBarFileOpenFromFile": "_파일에서 응용 프로그램 불러오기",
|
||||
"MenuBarFileOpenUnpacked": "_압축을 푼 게임 불러오기",
|
||||
"MenuBarFileOpenEmuFolder": "Ryujinx 폴더 열기",
|
||||
"MenuBarFileOpenLogsFolder": "로그 폴더 열기",
|
||||
"MenuBarFileExit": "_그만두",
|
||||
"MenuBarFileExit": "_종료",
|
||||
"MenuBarOptions": "옵션",
|
||||
"MenuBarOptionsToggleFullscreen": "전체 화면 전환",
|
||||
"MenuBarOptionsStartGamesInFullscreen": "전체 화면 모드에서 게임 열기",
|
||||
"MenuBarOptionsToggleFullscreen": "전체화면 전환",
|
||||
"MenuBarOptionsStartGamesInFullscreen": "전체 화면 모드에서 게임 시작",
|
||||
"MenuBarOptionsStopEmulation": "에뮬레이션 중지",
|
||||
"MenuBarOptionsSettings": "_조절",
|
||||
"MenuBarOptionsManageUserProfiles": "사용자 프로필 _관리",
|
||||
"MenuBarActions": "_행위",
|
||||
"MenuBarOptionsSimulateWakeUpMessage": "깨우기 명령어 시뮬레이션",
|
||||
"MenuBarOptionsSettings": "_설정",
|
||||
"MenuBarOptionsManageUserProfiles": "_사용자 프로파일 관리\n",
|
||||
"MenuBarActions": "_동작",
|
||||
"MenuBarOptionsSimulateWakeUpMessage": "모닝콜 메세지 시뮬레이션\n",
|
||||
"MenuBarActionsScanAmiibo": "Amiibo 스캔",
|
||||
"MenuBarTools": "_도구",
|
||||
"MenuBarToolsInstallFirmware": "펌웨어 설치",
|
||||
"MenuBarFileToolsInstallFirmwareFromFile": "XCI 또는 ZIP에서 펌웨어 설치",
|
||||
"MenuBarFileToolsInstallFirmwareFromDirectory": "디렉토리에서 펌웨어 설치",
|
||||
"MenuBarHelp": "돕다",
|
||||
"MenuBarHelp": "도움",
|
||||
"MenuBarHelpCheckForUpdates": "업데이트 확인",
|
||||
"MenuBarHelpAbout": "통지",
|
||||
"MenuSearch": "찾다···",
|
||||
"MenuBarHelpAbout": "정보",
|
||||
"MenuSearch": "검색...",
|
||||
"GameListHeaderFavorite": "즐겨찾기",
|
||||
"GameListHeaderIcon": "상",
|
||||
"GameListHeaderIcon": "아이콘",
|
||||
"GameListHeaderApplication": "이름",
|
||||
"GameListHeaderDeveloper": "개발자",
|
||||
"GameListHeaderVersion": "버전",
|
||||
"GameListHeaderTimePlayed": "플레이 시간",
|
||||
"GameListHeaderLastPlayed": "해본 마지막",
|
||||
"GameListHeaderLastPlayed": "마지막 플레이",
|
||||
"GameListHeaderFileExtension": "파일 확장자",
|
||||
"GameListHeaderFileSize": "파일 크기",
|
||||
"GameListHeaderPath": "파일 경로",
|
||||
"GameListContextMenuOpenUserSaveDirectory": "사용자 저장 폴더 열기",
|
||||
"GameListContextMenuOpenUserSaveDirectoryToolTip": "응용 프로그램의 사용자 저장이 포함된 폴더를 엽니다",
|
||||
"GameListContextMenuOpenUserDeviceDirectory": "사용자 장치 폴더 열기",
|
||||
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "응용 프로그램의 장치 저장이 포함된 폴더를 엽니다",
|
||||
"GameListContextMenuOpenUserBcatDirectory": "사용자의 BCAT 폴더 열기",
|
||||
"GameListContextMenuOpenUserBcatDirectoryToolTip": "응용 프로그램의 BCAT 저장이 포함된 폴더를 엽니다",
|
||||
"GameListContextMenuManageTitleUpdates": "타이틀 업데이트 관리s",
|
||||
"GameListHeaderPath": "경로",
|
||||
"GameListContextMenuOpenUserSaveDirectory": "사용자 저장 디렉토리 열기\n",
|
||||
"GameListContextMenuOpenUserSaveDirectoryToolTip": "응용 프로그램의 사용자 저장이 포함된 디렉토리 열기\n",
|
||||
"GameListContextMenuOpenDeviceSaveDirectory": "사용자 장치 디렉토리 열기",
|
||||
"GameListContextMenuOpenDeviceSaveDirectoryToolTip": "응용 프로그램의 장치 저장이 포함된 디렉토리 열기\n",
|
||||
"GameListContextMenuOpenBcatSaveDirectory": "사용자의 BCAT 디렉토리 열기\n",
|
||||
"GameListContextMenuOpenBcatSaveDirectoryToolTip": "응용 프로그램의 BCAT 저장이 포함된 디렉토리 열기\n",
|
||||
"GameListContextMenuManageTitleUpdates": "타이틀 업데이트 관리\n",
|
||||
"GameListContextMenuManageTitleUpdatesToolTip": "타이틀 업데이트 관리 창 열기",
|
||||
"GameListContextMenuManageDlc": "DLC 관리",
|
||||
"GameListContextMenuManageDlcToolTip": "DLC 관리 창 열기",
|
||||
"GameListContextMenuOpenModsDirectory": "모드 디렉토리 열기",
|
||||
"GameListContextMenuOpenModsDirectoryToolTip": "응용 프로그램의 모드가들 포함된 디렉터리를 엽니다",
|
||||
"GameListContextMenuOpenModsDirectory": "Mod 디렉토리 열기",
|
||||
"GameListContextMenuOpenModsDirectoryToolTip": "응용 프로그램의 Mod들이 포함된 디렉터리 열기",
|
||||
"GameListContextMenuCacheManagement": "캐시 관리",
|
||||
"GameListContextMenuCacheManagementPurgePptc": "PPTC 캐시 제거",
|
||||
"GameListContextMenuCacheManagementPurgePptcToolTip": "응용 프로그램 PPTC 캐시 삭제",
|
||||
"GameListContextMenuCacheManagementPurgePptc": "대기열 PPTC 재구성",
|
||||
"GameListContextMenuCacheManagementPurgePptcToolTip": "다음 게임 시작 시 부팅 시 PPTC가 다시 빌드되도록 트리거\n",
|
||||
"GameListContextMenuCacheManagementPurgeShaderCache": "셰이더 캐시 제거",
|
||||
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "애플리케이션 셰이더 캐시를 삭제합니다.",
|
||||
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "응용 프로그램 셰이더 캐시 삭제\n",
|
||||
"GameListContextMenuCacheManagementOpenPptcDirectory": "PPTC 디렉토리 열기",
|
||||
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "응용 프로그램 PPTC 캐시가 포함된 디렉터리를 엽니다",
|
||||
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "응용 프로그램 PPTC 캐시가 포함된 디렉터리 열기\n",
|
||||
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "셰이더 캐시 디렉토리 열기",
|
||||
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "응용 프로그램 셰이더 캐시가 포함된 디렉터리를 엽니다",
|
||||
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "응용 프로그램 셰이더 캐시가 포함된 디렉터리 열기\n",
|
||||
"GameListContextMenuExtractData": "데이터 추출",
|
||||
"GameListContextMenuExtractDataExeFS": "ExeFS",
|
||||
"GameListContextMenuExtractDataExeFSToolTip": "애플리케이션의 현재 구성에서 ExeFS 추출 (업데이트 포함)",
|
||||
"GameListContextMenuExtractDataRomFS": "RomFS",
|
||||
"GameListContextMenuExtractDataRomFSToolTip": "애플리케이션의 현재 구성에서 RomFS 추출 (업데이트 포함)",
|
||||
"GameListContextMenuExtractDataLogo": "Logo",
|
||||
"GameListContextMenuExtractDataLogoToolTip": "애플리케이션의 현재 구성에서 로고 섹션 추출 (업데이트 포함)",
|
||||
"StatusBarGamesLoaded": "로드된 {0}/{1}개의 게임",
|
||||
"GameListContextMenuExtractDataRomFSToolTip": "응용 프로그램의 현재 구성에서 RomFS 추출 (업데이트 포함)\n",
|
||||
"GameListContextMenuExtractDataLogo": "로고",
|
||||
"GameListContextMenuExtractDataLogoToolTip": "응용 프로그램의 현재 구성에서 로고 섹션 추출 (업데이트 포함)\n",
|
||||
"StatusBarGamesLoaded": "불러온 {0}/{1} 개의 게임",
|
||||
"StatusBarSystemVersion": "시스템 버전 : {0}",
|
||||
"Settings": "조절",
|
||||
"Settings": "설정",
|
||||
"SettingsTabGeneral": "사용자 인터페이스",
|
||||
"SettingsTabGeneralGeneral": "일반",
|
||||
"SettingsTabGeneralEnableDiscordRichPresence": "Discord Rich Presence 활성화",
|
||||
"SettingsTabGeneralCheckUpdatesOnLaunch": "열 때 업데이트 확인",
|
||||
"SettingsTabGeneralEnableDiscordRichPresence": "디스코드 활동 상태 활성화\n",
|
||||
"SettingsTabGeneralCheckUpdatesOnLaunch": "실행 시 업데이트 확인\n",
|
||||
"SettingsTabGeneralShowConfirmExitDialog": "\"종료 확인\" 대화 상자 표시",
|
||||
"SettingsTabGeneralHideCursorOnIdle": "유휴 상태에서 커서 숨기기",
|
||||
"SettingsTabGeneralGameDirectories": "게임 디렉토리들",
|
||||
"SettingsTabGeneralAdd": "추가하다",
|
||||
"SettingsTabGeneralRemove": "제거하다",
|
||||
"SettingsTabSystem": "체계",
|
||||
"SettingsTabSystemCore": "핵심",
|
||||
"SettingsTabSystemSystemRegion": "시스템 영역 :",
|
||||
"SettingsTabGeneralGameDirectories": "게임 디렉토리",
|
||||
"SettingsTabGeneralAdd": "추가",
|
||||
"SettingsTabGeneralRemove": "제거",
|
||||
"SettingsTabSystem": "시스템",
|
||||
"SettingsTabSystemCore": "코어",
|
||||
"SettingsTabSystemSystemRegion": "시스템 지역 :",
|
||||
"SettingsTabSystemSystemRegionJapan": "일본",
|
||||
"SettingsTabSystemSystemRegionUSA": "미국",
|
||||
"SettingsTabSystemSystemRegionEurope": "유럽",
|
||||
@ -98,45 +99,45 @@
|
||||
"SettingsTabSystemSystemLanguageSpanish": "스페인어",
|
||||
"SettingsTabSystemSystemLanguageChinese": "중국어",
|
||||
"SettingsTabSystemSystemLanguageKorean": "한국어",
|
||||
"SettingsTabSystemSystemLanguageDutch": "네덜란드 어",
|
||||
"SettingsTabSystemSystemLanguageDutch": "네덜란드어",
|
||||
"SettingsTabSystemSystemLanguagePortuguese": "포르투갈어",
|
||||
"SettingsTabSystemSystemLanguageRussian": "러시아어",
|
||||
"SettingsTabSystemSystemLanguageTaiwanese": "대만어",
|
||||
"SettingsTabSystemSystemLanguageBritishEnglish": "영어(영국)",
|
||||
"SettingsTabSystemSystemLanguageCanadianFrench": "프랑스어(캐나다)",
|
||||
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "스페인어(라틴 아메리카)",
|
||||
"SettingsTabSystemSystemLanguageBritishEnglish": "영어 (영국)",
|
||||
"SettingsTabSystemSystemLanguageCanadianFrench": "프랑스어 (캐나다)",
|
||||
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "스페인어 (라틴 아메리카)",
|
||||
"SettingsTabSystemSystemLanguageSimplifiedChinese": "중국어 간체",
|
||||
"SettingsTabSystemSystemLanguageTraditionalChinese": "중국어 번체",
|
||||
"SettingsTabSystemSystemTimeZone": "시스템 시간대 :",
|
||||
"SettingsTabSystemSystemTime": "시스템 시간 :",
|
||||
"SettingsTabSystemEnableVsync": "수직 동기화 사용",
|
||||
"SettingsTabSystemEnablePptc": "PPTC(Profiled Persistent Translation Cache) 활성화",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "FS 무결성 검사 활성화",
|
||||
"SettingsTabSystemAudioBackend": "오디오 백엔드 :",
|
||||
"SettingsTabSystemAudioBackendDummy": "Dummy",
|
||||
"SettingsTabSystemEnableVsync": "수직 동기화",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (프로파일된 영구 번역 캐시) 활성화",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "FS 무결성 검사",
|
||||
"SettingsTabSystemAudioBackend": "오디오 백엔드:",
|
||||
"SettingsTabSystemAudioBackendDummy": "더미",
|
||||
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
|
||||
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
|
||||
"SettingsTabSystemAudioBackendSoundIO": "사운드IO",
|
||||
"SettingsTabSystemAudioBackendSDL2": "SDL2",
|
||||
"SettingsTabSystemHacks": "해킹",
|
||||
"SettingsTabSystemHacksNote": " (불안정을 일으킬 수 있음)",
|
||||
"SettingsTabSystemExpandDramSize": "DRAM 크기를 6GiB로 확장",
|
||||
"SettingsTabSystemExpandDramSize": "대체 메모리 레이아웃 사용 (개발자)\n",
|
||||
"SettingsTabSystemIgnoreMissingServices": "누락된 서비스 무시",
|
||||
"SettingsTabGraphics": "제도법",
|
||||
"SettingsTabGraphics": "그래픽",
|
||||
"SettingsTabGraphicsAPI": "그래픽 API",
|
||||
"SettingsTabGraphicsEnableShaderCache": "셰이더 캐시 활성화",
|
||||
"SettingsTabGraphicsAnisotropicFiltering": "이방성 필터링 :",
|
||||
"SettingsTabGraphicsAnisotropicFilteringAuto": "자동적 인",
|
||||
"SettingsTabGraphicsAnisotropicFiltering2x": "2x",
|
||||
"SettingsTabGraphicsAnisotropicFiltering4x": "4x",
|
||||
"SettingsTabGraphicsAnisotropicFiltering8x": "8x",
|
||||
"SettingsTabGraphicsAnisotropicFiltering16x": "16x",
|
||||
"SettingsTabGraphicsResolutionScale": "해상도 스케일 :",
|
||||
"SettingsTabGraphicsResolutionScaleCustom": "사용자 지정(권장하지 않음)",
|
||||
"SettingsTabGraphicsAnisotropicFiltering": "이방성 필터링:",
|
||||
"SettingsTabGraphicsAnisotropicFilteringAuto": "자동",
|
||||
"SettingsTabGraphicsAnisotropicFiltering2x": "2 배",
|
||||
"SettingsTabGraphicsAnisotropicFiltering4x": "4 배",
|
||||
"SettingsTabGraphicsAnisotropicFiltering8x": "8 배",
|
||||
"SettingsTabGraphicsAnisotropicFiltering16x": "16 배",
|
||||
"SettingsTabGraphicsResolutionScale": "해상도 스케일:",
|
||||
"SettingsTabGraphicsResolutionScaleCustom": "사용자 지정 (권장하지 않음)",
|
||||
"SettingsTabGraphicsResolutionScaleNative": "기본 (720p/1080p)",
|
||||
"SettingsTabGraphicsResolutionScale2x": "2x (1440p/2160p)",
|
||||
"SettingsTabGraphicsResolutionScale3x": "3x (2160p/3240p)",
|
||||
"SettingsTabGraphicsResolutionScale4x": "4x (2880p/4320p)",
|
||||
"SettingsTabGraphicsAspectRatio": "종횡비 :",
|
||||
"SettingsTabGraphicsResolutionScale2x": "2 배 (1440p/2160p)",
|
||||
"SettingsTabGraphicsResolutionScale3x": "3 배 (2160p/3240p)",
|
||||
"SettingsTabGraphicsResolutionScale4x": "4 배 (2880p/4320p)",
|
||||
"SettingsTabGraphicsAspectRatio": "화면비:",
|
||||
"SettingsTabGraphicsAspectRatio4x3": "4:3",
|
||||
"SettingsTabGraphicsAspectRatio16x9": "16:9",
|
||||
"SettingsTabGraphicsAspectRatio16x10": "16:10",
|
||||
@ -144,31 +145,33 @@
|
||||
"SettingsTabGraphicsAspectRatio32x9": "32:9",
|
||||
"SettingsTabGraphicsAspectRatioStretch": "창에 맞게 늘리기",
|
||||
"SettingsTabGraphicsDeveloperOptions": "개발자 옵션",
|
||||
"SettingsTabGraphicsShaderDumpPath": "그래픽 쉐이더 덤프 경로 :",
|
||||
"SettingsTabGraphicsShaderDumpPath": "그래픽 쉐이더 덤프 경로:",
|
||||
"SettingsTabLogging": "로깅",
|
||||
"SettingsTabLoggingLogging": "로깅",
|
||||
"SettingsTabLoggingEnableLoggingToFile": "파일에 로깅 활성화",
|
||||
"SettingsTabLoggingEnableStubLogs": "스텁 로그 켜기 ",
|
||||
"SettingsTabLoggingEnableInfoLogs": "정보 로그 켜기",
|
||||
"SettingsTabLoggingEnableWarningLogs": "경고 로그 켜기",
|
||||
"SettingsTabLoggingEnableErrorLogs": "오류 로그 켜기",
|
||||
"SettingsTabLoggingEnableGuestLogs": "게스트 로그 켜기",
|
||||
"SettingsTabLoggingEnableFsAccessLogs": "Fs 액세스 로그 켜기",
|
||||
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs 전역 액세스 로그 모드 :",
|
||||
"SettingsTabLoggingDeveloperOptions": "개발자 옵션 (경고 : 성능이 저하됩니다.)",
|
||||
"SettingsTabLoggingEnableStubLogs": "스텁 로그 활성화",
|
||||
"SettingsTabLoggingEnableInfoLogs": "정보 로그 활성화",
|
||||
"SettingsTabLoggingEnableWarningLogs": "경고 로그 활성화",
|
||||
"SettingsTabLoggingEnableErrorLogs": "오류 로그 활성화",
|
||||
"SettingsTabLoggingEnableTraceLogs": "추적 로그 활성화",
|
||||
"SettingsTabLoggingEnableGuestLogs": "게스트 로그 활성화",
|
||||
"SettingsTabLoggingEnableFsAccessLogs": "Fs 접속 로그 활성화",
|
||||
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs 글로벌 접속 로그 모드:",
|
||||
"SettingsTabLoggingDeveloperOptions": "개발자 옵션 (경고 : 성능이 저하됨)",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevel": "그래픽 백엔드 로그 수준:",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelNone": "없음",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelError": "오류",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "감속",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelAll": "모두",
|
||||
"SettingsTabLoggingEnableDebugLogs": "디버그 로그 사용",
|
||||
"SettingsTabLoggingEnableDebugLogs": "디버그 로그 활성화",
|
||||
"SettingsTabInput": "입력",
|
||||
"SettingsTabInputEnableDockedMode": "도킹 모드 활성화",
|
||||
"SettingsTabInputDirectKeyboardAccess": "직접 키보드 액세스",
|
||||
"SettingsButtonSave": "구하다",
|
||||
"SettingsButtonClose": "출구",
|
||||
"SettingsButtonOk": "좋아",
|
||||
"SettingsTabInputEnableDockedMode": "도킹 모드",
|
||||
"SettingsTabInputDirectKeyboardAccess": "직접 키보드 접속",
|
||||
"SettingsButtonSave": "저장",
|
||||
"SettingsButtonClose": "닫기",
|
||||
"SettingsButtonOk": "확인",
|
||||
"SettingsButtonCancel": "취소",
|
||||
"SettingsButtonApply": "적용하다",
|
||||
"SettingsButtonApply": "적용",
|
||||
"ControllerSettingsPlayer": "플레이어",
|
||||
"ControllerSettingsPlayer1": "플레이어 1",
|
||||
"ControllerSettingsPlayer2": "플레이어 2",
|
||||
@ -180,316 +183,432 @@
|
||||
"ControllerSettingsPlayer8": "플레이어 8",
|
||||
"ControllerSettingsHandheld": "휴대용",
|
||||
"ControllerSettingsInputDevice": "입력 장치",
|
||||
"ControllerSettingsRefresh": "새로 고치다",
|
||||
"ControllerSettingsDeviceDisabled": "장애가있는",
|
||||
"ControllerSettingsRefresh": "새로 고침",
|
||||
"ControllerSettingsDeviceDisabled": "비활성화됨",
|
||||
"ControllerSettingsControllerType": "컨트롤러 유형",
|
||||
"ControllerSettingsControllerTypeHandheld": "휴대용",
|
||||
"ControllerSettingsControllerTypeProController": "Pro Controller",
|
||||
"ControllerSettingsControllerTypeJoyConPair": "JoyCon 페어",
|
||||
"ControllerSettingsControllerTypeJoyConLeft": "JoyCon 왼쪽",
|
||||
"ControllerSettingsControllerTypeJoyConRight": "JoyCon 오른쪽",
|
||||
"ControllerSettingsProfile": "프로필",
|
||||
"ControllerSettingsControllerTypeProController": "프로 컨트롤러",
|
||||
"ControllerSettingsControllerTypeJoyConPair": "조이콘 페어링",
|
||||
"ControllerSettingsControllerTypeJoyConLeft": "왼쪽 조이콘",
|
||||
"ControllerSettingsControllerTypeJoyConRight": "오른쪽 조이콘",
|
||||
"ControllerSettingsProfile": "프로파일",
|
||||
"ControllerSettingsProfileDefault": "기본",
|
||||
"ControllerSettingsLoad": "짐",
|
||||
"ControllerSettingsAdd": "추가하다",
|
||||
"ControllerSettingsRemove": "제거하다",
|
||||
"ControllerSettingsLoad": "불러오기",
|
||||
"ControllerSettingsAdd": "추가",
|
||||
"ControllerSettingsRemove": "제거",
|
||||
"ControllerSettingsButtons": "버튼",
|
||||
"ControllerSettingsButtonA": "A",
|
||||
"ControllerSettingsButtonB": "B",
|
||||
"ControllerSettingsButtonX": "X",
|
||||
"ControllerSettingsButtonY": "Y",
|
||||
"ControllerSettingsButtonPlus": "+",
|
||||
"ControllerSettingsButtonMinus": "-",
|
||||
"ControllerSettingsDPad": "Directional Pad",
|
||||
"ControllerSettingsDPadUp": "위로",
|
||||
"ControllerSettingsDPadDown": "아래에",
|
||||
"ControllerSettingsButtonA": "A 버튼",
|
||||
"ControllerSettingsButtonB": "B 버튼",
|
||||
"ControllerSettingsButtonX": "X 버튼",
|
||||
"ControllerSettingsButtonY": "Y 버튼",
|
||||
"ControllerSettingsButtonPlus": "+ 버튼",
|
||||
"ControllerSettingsButtonMinus": "- 버튼",
|
||||
"ControllerSettingsDPad": "방향 패드",
|
||||
"ControllerSettingsDPadUp": "위쪽",
|
||||
"ControllerSettingsDPadDown": "아래쪽",
|
||||
"ControllerSettingsDPadLeft": "왼쪽",
|
||||
"ControllerSettingsDPadRight": "오른쪽",
|
||||
"ControllerSettingsLStick": "왼쪽 스틱",
|
||||
"ControllerSettingsLStickButton": "단추",
|
||||
"ControllerSettingsLStickUp": "위로",
|
||||
"ControllerSettingsLStickDown": "아래에",
|
||||
"ControllerSettingsLStickButton": "버튼",
|
||||
"ControllerSettingsLStickUp": "위쪽",
|
||||
"ControllerSettingsLStickDown": "아래쪽",
|
||||
"ControllerSettingsLStickLeft": "왼쪽",
|
||||
"ControllerSettingsLStickRight": "오른쪽",
|
||||
"ControllerSettingsLStickStick": "막대",
|
||||
"ControllerSettingsLStickInvertXAxis": "스틱 X축 반전",
|
||||
"ControllerSettingsLStickInvertYAxis": "스틱 Y축 반전",
|
||||
"ControllerSettingsLStickDeadzone": "데드 존 :",
|
||||
"ControllerSettingsLStickStick": "스틱",
|
||||
"ControllerSettingsLStickInvertXAxis": "스틱 X 축 반전",
|
||||
"ControllerSettingsLStickInvertYAxis": "스틱 Y 축 반전",
|
||||
"ControllerSettingsLStickDeadzone": "데드존:",
|
||||
"ControllerSettingsRStick": "오른쪽 스틱",
|
||||
"ControllerSettingsRStickButton": "단추",
|
||||
"ControllerSettingsRStickUp": "위로",
|
||||
"ControllerSettingsRStickDown": "아래에",
|
||||
"ControllerSettingsRStickButton": "버튼",
|
||||
"ControllerSettingsRStickUp": "위쪽",
|
||||
"ControllerSettingsRStickDown": "아래쪽",
|
||||
"ControllerSettingsRStickLeft": "왼쪽",
|
||||
"ControllerSettingsRStickRight": "오른쪽",
|
||||
"ControllerSettingsRStickStick": "Stick",
|
||||
"ControllerSettingsRStickInvertXAxis": "스틱 X축 반전",
|
||||
"ControllerSettingsRStickInvertYAxis": "스틱 Y축 반전",
|
||||
"ControllerSettingsRStickDeadzone": "데드 존 :",
|
||||
"ControllerSettingsRStickStick": "스틱",
|
||||
"ControllerSettingsRStickInvertXAxis": "스틱 X 축 반전",
|
||||
"ControllerSettingsRStickInvertYAxis": "스틱 Y 축 반전",
|
||||
"ControllerSettingsRStickDeadzone": "데드존:",
|
||||
"ControllerSettingsTriggersLeft": "왼쪽 트리거",
|
||||
"ControllerSettingsTriggersRight": "오른쪽 트리거",
|
||||
"ControllerSettingsTriggersButtonsLeft": "트리거 버튼 왼쪽",
|
||||
"ControllerSettingsTriggersButtonsRight": "트리거 버튼 오른쪽",
|
||||
"ControllerSettingsTriggers": "방아쇠",
|
||||
"ControllerSettingsTriggerL": "L",
|
||||
"ControllerSettingsTriggerR": "R",
|
||||
"ControllerSettingsTriggerZL": "ZL",
|
||||
"ControllerSettingsTriggerZR": "ZR",
|
||||
"ControllerSettingsLeftSL": "SL",
|
||||
"ControllerSettingsLeftSR": "SR",
|
||||
"ControllerSettingsRightSL": "SL",
|
||||
"ControllerSettingsRightSR": "SR",
|
||||
"ControllerSettingsTriggersButtonsLeft": "왼쪽 트리거 버튼",
|
||||
"ControllerSettingsTriggersButtonsRight": "오른쪽 트리거 버튼",
|
||||
"ControllerSettingsTriggers": "트리거 버튼",
|
||||
"ControllerSettingsTriggerL": "L 버튼",
|
||||
"ControllerSettingsTriggerR": "R 버튼",
|
||||
"ControllerSettingsTriggerZL": "ZL 버튼",
|
||||
"ControllerSettingsTriggerZR": "ZR 버튼",
|
||||
"ControllerSettingsLeftSL": "SL 버튼",
|
||||
"ControllerSettingsLeftSR": "SR 버튼",
|
||||
"ControllerSettingsRightSL": "SL 버튼",
|
||||
"ControllerSettingsRightSR": "SR 버튼",
|
||||
"ControllerSettingsExtraButtonsLeft": "왼쪽 버튼",
|
||||
"ControllerSettingsExtraButtonsRight": "버튼 오른쪽",
|
||||
"ControllerSettingsMisc": "여러 가지 잡다한",
|
||||
"ControllerSettingsExtraButtonsRight": "오른쪽 버튼",
|
||||
"ControllerSettingsMisc": "기타",
|
||||
"ControllerSettingsTriggerThreshold": "트리거 임계값 :",
|
||||
"ControllerSettingsMotion": "운동",
|
||||
"ControllerSettingsMotion": "동작",
|
||||
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "CemuHook 호환 모션 사용",
|
||||
"ControllerSettingsMotionControllerSlot": "컨트롤러 슬롯 :",
|
||||
"ControllerSettingsMotionControllerSlot": "컨트롤러 슬롯:",
|
||||
"ControllerSettingsMotionMirrorInput": "미러 입력",
|
||||
"ControllerSettingsMotionRightJoyConSlot": "오른쪽 JoyCon 슬롯 :",
|
||||
"ControllerSettingsMotionServerHost": "서버 호스트 :",
|
||||
"ControllerSettingsMotionGyroSensitivity": "자이로 감도 :",
|
||||
"ControllerSettingsMotionGyroDeadzone": "자이로 데드존 :",
|
||||
"ControllerSettingsSave": "구하다",
|
||||
"ControllerSettingsClose": "출구",
|
||||
"UserProfilesSelectedUserProfile": "선택한 사용자 프로필 :",
|
||||
"UserProfilesSaveProfileName": "프로필 이름 저장",
|
||||
"UserProfilesChangeProfileImage": "프로필 이미지 변경",
|
||||
"UserProfilesAvailableUserProfiles": "사용 가능한 사용자 프로필 :",
|
||||
"UserProfilesAddNewProfile": "새 프로필 추가",
|
||||
"UserProfilesDeleteSelectedProfile": "선택한 프로필 삭제",
|
||||
"UserProfilesClose": "출구",
|
||||
"ProfileImageSelectionTitle": "프로필 이미지 선택",
|
||||
"ProfileImageSelectionHeader": "이미지 선택",
|
||||
"ProfileImageSelectionNote": "사용자 정의 프로필 이미지를 사용하거나 시스템 펌웨어에서 하나를 선택할 수 있습니다",
|
||||
"ControllerSettingsMotionRightJoyConSlot": "오른쪽 조이콘 슬롯 :",
|
||||
"ControllerSettingsMotionServerHost": "서버 호스트:",
|
||||
"ControllerSettingsMotionGyroSensitivity": "자이로 감도:",
|
||||
"ControllerSettingsMotionGyroDeadzone": "자이로 데드존:",
|
||||
"ControllerSettingsSave": "저장",
|
||||
"ControllerSettingsClose": "닫기",
|
||||
"UserProfilesSelectedUserProfile": "선택한 사용자 프로파일:",
|
||||
"UserProfilesSaveProfileName": "프로파일 이름 저장",
|
||||
"UserProfilesChangeProfileImage": "프로파일 이미지 변경",
|
||||
"UserProfilesAvailableUserProfiles": "사용 가능한 사용자 프로파일:",
|
||||
"UserProfilesAddNewProfile": "프로파일 생성",
|
||||
"UserProfilesDeleteSelectedProfile": "선택한 프로파일 삭제",
|
||||
"UserProfilesClose": "닫기",
|
||||
"ProfileImageSelectionTitle": "프로파일 이미지 선택",
|
||||
"ProfileImageSelectionHeader": "프로파일 이미지 선택",
|
||||
"ProfileImageSelectionNote": "사용자 지정 프로파일 이미지를 가져오거나 시스템 펌웨어에서 아바타를 선택할 수 있음\n",
|
||||
"ProfileImageSelectionImportImage": "이미지 파일 가져오기",
|
||||
"ProfileImageSelectionSelectAvatar": "펌웨어 아바타 선택",
|
||||
"InputDialogTitle": "입력 대화 상자",
|
||||
"InputDialogTitle": "입력 대화상자",
|
||||
"InputDialogOk": "확인",
|
||||
"InputDialogCancel": "취소",
|
||||
"InputDialogAddNewProfileTitle": "프로필 이름 선택",
|
||||
"InputDialogAddNewProfileHeader": "프로필 이름을 입력하세요",
|
||||
"InputDialogAddNewProfileSubtext": "최대 길이 : {0})",
|
||||
"AvatarChoose": "선택하다",
|
||||
"InputDialogAddNewProfileTitle": "프로파일 이름 선택",
|
||||
"InputDialogAddNewProfileHeader": "프로파일 이름 입력",
|
||||
"InputDialogAddNewProfileSubtext": "(최대 길이: {0})\n",
|
||||
"AvatarChoose": "선택",
|
||||
"AvatarSetBackgroundColor": "배경색 설정",
|
||||
"AvatarClose": "출구",
|
||||
"ControllerSettingsLoadProfileToolTip": "프로필 로드",
|
||||
"ControllerSettingsAddProfileToolTip": "프로필 추가",
|
||||
"ControllerSettingsRemoveProfileToolTip": "프로필 제거",
|
||||
"ControllerSettingsSaveProfileToolTip": "프로필 저장",
|
||||
"MenuBarFileToolsTakeScreenshot": "스크린 샷을 찍다",
|
||||
"MenuBarFileToolsHideUi": "사용자 인터페이스 숨기기",
|
||||
"GameListContextMenuToggleFavorite": "즐겨찾기 설정",
|
||||
"GameListContextMenuToggleFavoriteToolTip": "이 게임이 즐겨찾기인지 여부를 전환합니다",
|
||||
"AvatarClose": "닫기",
|
||||
"ControllerSettingsLoadProfileToolTip": "프로파일 불러오기",
|
||||
"ControllerSettingsAddProfileToolTip": "프로파일 추가",
|
||||
"ControllerSettingsRemoveProfileToolTip": "프로파일 제거",
|
||||
"ControllerSettingsSaveProfileToolTip": "프로파일 저장",
|
||||
"MenuBarFileToolsTakeScreenshot": "스크린 샷 찍기",
|
||||
"MenuBarFileToolsHideUi": "Hide UI",
|
||||
"GameListContextMenuToggleFavorite": "즐겨찾기 전환",
|
||||
"GameListContextMenuToggleFavoriteToolTip": "게임 즐겨찾기 상태 전환\n",
|
||||
"SettingsTabGeneralTheme": "테마",
|
||||
"SettingsTabGeneralThemeCustomTheme": "사용자 정의 테마 경로",
|
||||
"SettingsTabGeneralThemeBaseStyle": "기본 스타일",
|
||||
"SettingsTabGeneralThemeBaseStyleDark": "어두운",
|
||||
"SettingsTabGeneralThemeBaseStyleLight": "빛",
|
||||
"SettingsTabGeneralThemeBaseStyleDark": "어두움",
|
||||
"SettingsTabGeneralThemeBaseStyleLight": "밝음",
|
||||
"SettingsTabGeneralThemeEnableCustomTheme": "사용자 정의 테마 활성화",
|
||||
"ButtonBrowse": "검색",
|
||||
"ControllerSettingsConfigureGeneral": "션 구성",
|
||||
"ControllerSettingsRumble": "하인 좌석",
|
||||
"ControllerSettingsRumbleStrongMultiplier": "강력한 럼블 배율기",
|
||||
"ControllerSettingsRumbleWeakMultiplier": "약한 럼블 승수",
|
||||
"DialogMessageSaveNotAvailableMessage": "에 대한 세이브 데이터가 없습니다 {0} [{1:x16}]",
|
||||
"DialogMessageSaveNotAvailableCreateSaveMessage": "이 게임의 세이브 데이터를 생성하시겠습니까?",
|
||||
"ButtonBrowse": "찾아보기",
|
||||
"ControllerSettingsConfigureGeneral": "구성",
|
||||
"ControllerSettingsRumble": "진동",
|
||||
"ControllerSettingsRumbleStrongMultiplier": "강력한 진동 증폭기",
|
||||
"ControllerSettingsRumbleWeakMultiplier": "약한 진동 증폭기",
|
||||
"DialogMessageSaveNotAvailableMessage": "{0} [{1:x16}]에 대한 저장 데이터가 없음\n",
|
||||
"DialogMessageSaveNotAvailableCreateSaveMessage": "이 게임에 대한 저장 데이터를 생성하겠습니까?\n",
|
||||
"DialogConfirmationTitle": "Ryujinx - 확인",
|
||||
"DialogUpdaterTitle": "Ryujinx - 업데이터",
|
||||
"DialogErrorTitle": "Ryujinx - 오류",
|
||||
"DialogWarningTitle": "Ryujinx - 경고",
|
||||
"DialogExitTitle": "Ryujinx - 출구",
|
||||
"DialogErrorMessage": "Ryujinx에 오류가 발생했습니다",
|
||||
"DialogExitMessage": "Ryujinx를 종료하시겠습니까?",
|
||||
"DialogExitTitle": "Ryujinx - 종료",
|
||||
"DialogErrorMessage": "Ryujinx 오류 발생",
|
||||
"DialogExitMessage": "Ryujinx를 종료하겠습니까?",
|
||||
"DialogExitSubMessage": "저장하지 않은 모든 데이터는 손실됩니다!",
|
||||
"DialogMessageCreateSaveErrorMessage": "지정된 세이브 데이터를 작성하는 중에 오류가 발생했습니다 : {0}",
|
||||
"DialogMessageFindSaveErrorMessage": "지정된 저장 데이터를 찾는 중에 오류가 발생했습니다 : {0}",
|
||||
"DialogMessageCreateSaveErrorMessage": "지정된 저장 데이터를 작성하는 중에 오류 발생: {0}\n",
|
||||
"DialogMessageFindSaveErrorMessage": "지정된 저장 데이터를 찾는 중에 오류 발생: {0}\n",
|
||||
"FolderDialogExtractTitle": "추출할 폴더 선택",
|
||||
"DialogNcaExtractionMessage": "{1}에서 섹션 {0} 추출···",
|
||||
"DialogNcaExtractionMessage": "{1}에서 {0} 섹션을 추출하는 중...\n",
|
||||
"DialogNcaExtractionTitle": "Ryujinx - NCA 섹션 추출기",
|
||||
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "추출 실패. 선택한 파일에 기본 NCA가 없습니다.",
|
||||
"DialogNcaExtractionCheckLogErrorMessage": "추출 실패. 자세한 내용은 로그 파일을 읽으십시오.",
|
||||
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "추출 실패하였습니다. 선택한 파일에 기본 NCA가 없습니다.\n",
|
||||
"DialogNcaExtractionCheckLogErrorMessage": "추출 실패하였습니다. 자세한 내용은 로그 파일을 읽으세요.\n",
|
||||
"DialogNcaExtractionSuccessMessage": "추출이 성공적으로 완료되었습니다.",
|
||||
"DialogUpdaterConvertFailedMessage": "현재 Ryujinx 버전을 변환하지 못했습니다.",
|
||||
"DialogUpdaterCancelUpdateMessage": "업데이트 취소 중!",
|
||||
"DialogUpdaterCancelUpdateMessage": "업데이트 취소 중 입니다!",
|
||||
"DialogUpdaterAlreadyOnLatestVersionMessage": "이미 최신 버전의 Ryujinx를 사용하고 있습니다!",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "Github 릴리스에서 릴리스 정보를 가져오는 중에 오류가 발생했습니다. 이는 GitHub Actions에서 새 릴리스를 컴파일하는 경우 발생할 수 있습니다. 몇 분 후에 다시 시도하십시오.",
|
||||
"DialogUpdaterConvertFailedGithubMessage": "Github Release에서 받은 Ryujinx 버전을 변환하지 못했습니다.",
|
||||
"DialogUpdaterDownloadingMessage": "업데이트 다운로드 중···",
|
||||
"DialogUpdaterExtractionMessage": "업데이트 추출···",
|
||||
"DialogUpdaterRenamingMessage": "업데이트 이름 바꾸기···",
|
||||
"DialogUpdaterAddingFilesMessage": "새 업데이트 추가···",
|
||||
"DialogUpdaterCompleteMessage": "업데이트 완료!",
|
||||
"DialogUpdaterRestartMessage": "지금 Ryujinx를 다시 시작하시겠습니까?",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "GitHub 릴리스에서 릴리스 정보를 가져오는 중에 오류가 발생했습니다. 이는 GitHub Actions에서 새 릴리스를 컴파일하는 경우 발생할 수 있습니다. 몇 분 후에 다시 시도하세요.",
|
||||
"DialogUpdaterConvertFailedGithubMessage": "Github 개정에서 받은 Ryujinx 버전을 변환하지 못했습니다.\n",
|
||||
"DialogUpdaterDownloadingMessage": "업데이트 다운로드 중...\n",
|
||||
"DialogUpdaterExtractionMessage": "업데이트 추출 중...\n",
|
||||
"DialogUpdaterRenamingMessage": "업데이트 이름 바꾸는 중...\n",
|
||||
"DialogUpdaterAddingFilesMessage": "새 업데이트 추가 중...\n",
|
||||
"DialogUpdaterCompleteMessage": "업데이트 완료하였습니다!\n",
|
||||
"DialogUpdaterRestartMessage": "지금 Ryujinx를 다시 시작하겠습니까?",
|
||||
"DialogUpdaterArchNotSupportedMessage": "지원되는 시스템 아키텍처를 실행하고 있지 않습니다!",
|
||||
"DialogUpdaterArchNotSupportedSubMessage": "(x86 시스템만 지원됩니다!)",
|
||||
"DialogUpdaterArchNotSupportedSubMessage": "(x64 시스템만 지원됩니다!)\n",
|
||||
"DialogUpdaterNoInternetMessage": "인터넷에 연결되어 있지 않습니다!",
|
||||
"DialogUpdaterNoInternetSubMessage": "인터넷 연결이 작동하는지 확인하십시오!",
|
||||
"DialogUpdaterDirtyBuildMessage": "Ryujinx의 더러운 빌드는 업데이트할 수 없습니다!",
|
||||
"DialogUpdaterDirtyBuildSubMessage": "지원되는 버전을 찾고 있다면 https://ryujinx.org/에서 Ryujinx를 다운로드하십시오.",
|
||||
"DialogUpdaterNoInternetSubMessage": "인터넷 연결이 작동하는지 확인하세요!",
|
||||
"DialogUpdaterDirtyBuildMessage": "Ryujinx의 나쁜 빌드는 업데이트할 수 없습니다!\n",
|
||||
"DialogUpdaterDirtyBuildSubMessage": "지원되는 버전을 찾고 있다면 https://ryujinx.org/에서 Ryujinx를 다운로드하세요.",
|
||||
"DialogRestartRequiredMessage": "재시작 필요",
|
||||
"DialogThemeRestartMessage": "테마가 저장되었습니다. 테마를 적용하려면 다시 시작해야 합니다.",
|
||||
"DialogThemeRestartSubMessage": "다시 시작하시겠습니까?",
|
||||
"DialogFirmwareInstallEmbeddedMessage": "이 게임에 내장된 펌웨어를 설치하시겠습니까? (펌웨어 {0})",
|
||||
"DialogFirmwareInstallEmbeddedSuccessMessage": "설치된 펌웨어를 찾을 수 없지만 Ryujinx는 제공된 게임에서 펌웨어 {0} 설치할 수 있었습니다.\n이제 에뮬레이터가 시작됩니다.",
|
||||
"DialogFirmwareNoFirmwareInstalledMessage": "펌웨어가 설치되지 않았습니다",
|
||||
"DialogFirmwareInstalledMessage": "펌웨어 {0} 설치되었습니다.",
|
||||
"DialogThemeRestartSubMessage": "다시 시작하겠습니까?\n",
|
||||
"DialogFirmwareInstallEmbeddedMessage": "이 게임에 내장된 펌웨어를 설치하겠습니까? (펌웨어 {0})",
|
||||
"DialogFirmwareInstallEmbeddedSuccessMessage": "설치된 펌웨어가 없지만 Ryujinx가 제공된 게임에서 펌웨어 {0}을(를) 설치할 수 있었습니다.\\n이제 에뮬레이터가 시작됩니다.",
|
||||
"DialogFirmwareNoFirmwareInstalledMessage": "설치된 펌웨어 없음",
|
||||
"DialogFirmwareInstalledMessage": "펌웨어 {0}이(가) 설치됨",
|
||||
"DialogOpenSettingsWindowLabel": "설정 창 열기",
|
||||
"DialogControllerAppletTitle": "컨트롤러 애플릿",
|
||||
"DialogMessageDialogErrorExceptionMessage": "메시지 대화 상자를 표시하는 동안 오류가 발생했습니다 : {0}",
|
||||
"DialogSoftwareKeyboardErrorExceptionMessage": "소프트웨어 키보드를 표시하는 동안 오류가 발생했습니다 : {0}",
|
||||
"DialogErrorAppletErrorExceptionMessage": "ErrorApplet 대화 상자를 표시하는 동안 오류가 발생했습니다 : {0}",
|
||||
"DialogMessageDialogErrorExceptionMessage": "메시지 대화상자를 표시하는 동안 오류 발생: {0}\n",
|
||||
"DialogSoftwareKeyboardErrorExceptionMessage": "소프트웨어 키보드를 표시하는 동안 오류 발생: {0}",
|
||||
"DialogErrorAppletErrorExceptionMessage": "오류에플릿 대화상자를 표시하는 동안 오류 발생: {0}",
|
||||
"DialogUserErrorDialogMessage": "{0}: {1}",
|
||||
"DialogUserErrorDialogInfoMessage": "\n이 오류를 수정하는 방법에 대한 자세한 내용은 설정 가이드를 따르십시오",
|
||||
"DialogUserErrorDialogTitle": "Ryuijnx의 오류 ({0})",
|
||||
"DialogUserErrorDialogInfoMessage": "\n이 오류를 수정하는 방법에 대한 자세한 내용은 설정 가이드를 따르세요.",
|
||||
"DialogUserErrorDialogTitle": "Ryuijnx 오류 ({0})",
|
||||
"DialogAmiiboApiTitle": "Amiibo API",
|
||||
"DialogAmiiboApiFailFetchMessage": "API에서 정보를 가져오는 동안 오류가 발생했습니다.",
|
||||
"DialogAmiiboApiConnectErrorMessage": "Amiibo API 서버에 연결할 수 없습니다. 서비스가 다운되었거나 인터넷 연결이 오프라인인지 확인해야 할 수 있습니다.",
|
||||
"DialogProfileInvalidProfileErrorMessage": "프로필 AAA는 현재 입력 구성 시스템과 호환되지 않습니다.",
|
||||
"DialogProfileDefaultProfileOverwriteErrorMessage": "기본 프로필을 덮어쓸 수 없습니다",
|
||||
"DialogProfileDeleteProfileTitle": "프로필 삭제",
|
||||
"DialogProfileDeleteProfileMessage": "이 작업은 되돌릴 수 없습니다. 계속하시겠습니까?",
|
||||
"DialogProfileInvalidProfileErrorMessage": "{0} 프로파일은 현재 입력 구성 시스템과 호환되지 않습니다.",
|
||||
"DialogProfileDefaultProfileOverwriteErrorMessage": "기본 프로파일을 덮어쓸 수 없음",
|
||||
"DialogProfileDeleteProfileTitle": "프로파일 삭제",
|
||||
"DialogProfileDeleteProfileMessage": "이 작업은 되돌릴 수 없습니다. 계속하겠습니까?",
|
||||
"DialogWarning": "경고",
|
||||
"DialogPPTCDeletionMessage": "{0}에\n\n 대한 PPTC 캐시를 삭제하려고 합니다.\n\n계속하시겠습니까?",
|
||||
"DialogPPTCDeletionErrorMessage": "{0} : {1}에서 PPTC 캐시를 제거하는 동안 오류가 발생했습니다.",
|
||||
"DialogShaderDeletionMessage": "{0}에\n\n 대한 셰이더 캐시를 삭제하려고 합니다.\n\n계속하시겠습니까?",
|
||||
"DialogShaderDeletionErrorMessage": "{0} : {1}에서 셰이더 캐시를 제거하는 동안 오류가 발생했습니다.",
|
||||
"DialogRyujinxErrorMessage": "Ryujinx에 오류가 발생했습니다",
|
||||
"DialogInvalidTitleIdErrorMessage": "UI 오류 : 선택한 게임에 유효한 제목 ID가 없습니다",
|
||||
"DialogPPTCDeletionMessage": "다음에 부팅할 때 PPTC 재구축을 대기시키려고 합니다:\n\n{0}\n\n계속하겠습니까?",
|
||||
"DialogPPTCDeletionErrorMessage": "{0}에서 PPTC 캐시 삭제 오류: {1}",
|
||||
"DialogShaderDeletionMessage": "다음에 대한 셰이더 캐시를 삭제하려고 합니다:\n\n{0}\n\n계속하겠습니까?",
|
||||
"DialogShaderDeletionErrorMessage": "{0}에서 셰이더 캐시 제거 오류: {1}",
|
||||
"DialogRyujinxErrorMessage": "Ryujinx에 오류 발생",
|
||||
"DialogInvalidTitleIdErrorMessage": "UI 오류: 선택한 게임에 유효한 타이틀 ID가 없음",
|
||||
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "{0}에서 유효한 시스템 펌웨어를 찾을 수 없습니다.",
|
||||
"DialogFirmwareInstallerFirmwareInstallTitle": "펌웨어 {0} 설치",
|
||||
"DialogFirmwareInstallerFirmwareInstallMessage": "시스템 버전 {0}가 설치되려고 합니다",
|
||||
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\n이것은 현재 설치된 버전 {0}를 대체합니다.",
|
||||
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n계속하시겠습니까?",
|
||||
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "펌웨어 설치···",
|
||||
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "시스템 버전 {0}가 성공적으로 설치되었습니다.",
|
||||
"DialogUserProfileDeletionWarningMessage": "선택한 프로필이 삭제되면 사용 가능한 다른 프로필이 없습니다",
|
||||
"DialogUserProfileDeletionConfirmMessage": "선택한 프로필을 삭제하시겠습니까",
|
||||
"DialogFirmwareInstallerFirmwareInstallMessage": "시스템 버전 {0}이(가) 설치됩니다.",
|
||||
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\n이것은 현재 시스템 버전 {0}을(를) 대체합니다.",
|
||||
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n계속하겠습니까?",
|
||||
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "펌웨어 설치 중...",
|
||||
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "시스템 버전 {0}이(가) 성공적으로 설치되었습니다.",
|
||||
"DialogUserProfileDeletionWarningMessage": "선택한 프로파일이 삭제되면 사용 가능한 다른 프로파일이 없음",
|
||||
"DialogUserProfileDeletionConfirmMessage": "선택한 프로파일을 삭제하겠습니까?",
|
||||
"DialogControllerSettingsModifiedConfirmMessage": "현재 컨트롤러 설정이 업데이트되었습니다.",
|
||||
"DialogControllerSettingsModifiedConfirmSubMessage": "저장하시겠습니까?",
|
||||
"DialogDlcLoadNcaErrorMessage": "{0}. 오류 파일 : {1}",
|
||||
"DialogDlcNoDlcErrorMessage": "지정한 파일에 선택한 타이틀의 DLC가 없습니다!",
|
||||
"DialogPerformanceCheckLoggingEnabledMessage": "개발자 전용으로 설계된 디버그 로깅을 활성화했습니다.",
|
||||
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "최적의 성능을 위해 디버그 로깅을 비활성화하는 것이 좋습니다. 지금 디버그 로깅을 비활성화하시겠습니까?",
|
||||
"DialogPerformanceCheckShaderDumpEnabledMessage": "Y개발자만 사용하도록 설계된 셰이더 덤핑이 활성화되어 있습니다.",
|
||||
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "최적의 성능을 위해 셰이더 덤핑을 비활성화하는 것이 좋습니다. 지금 셰이더 덤핑을 비활성화하시겠습니까?",
|
||||
"DialogLoadAppGameAlreadyLoadedMessage": "다른 게임이 이미 로드되었습니다",
|
||||
"DialogLoadAppGameAlreadyLoadedSubMessage": "다른 게임을 시작하기 전에 에뮬레이션을 중지하거나 에뮬레이터를 닫으십시오.",
|
||||
"DialogUpdateAddUpdateErrorMessage": "파일에 선택한 제목에 대한 업데이트가 포함되어 있지 않습니다!",
|
||||
"DialogControllerSettingsModifiedConfirmSubMessage": "저장하겠습니까?",
|
||||
"DialogDlcLoadNcaErrorMessage": "{0}입니다. 오류 발생 파일: {1}",
|
||||
"DialogDlcNoDlcErrorMessage": "지정된 파일에 선택한 타이틀에 대한 DLC가 포함되어 있지 않습니다!",
|
||||
"DialogPerformanceCheckLoggingEnabledMessage": "개발자만 사용하도록 설계된 추적 로깅이 활성화되어 있습니다.",
|
||||
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "최적의 성능을 위해 추적 로깅을 비활성화하는 것이 좋습니다. 지금 추적 로깅을 비활성화하겠습니까?",
|
||||
"DialogPerformanceCheckShaderDumpEnabledMessage": "개발자만 사용하도록 설계된 셰이더 덤프를 활성화했습니다.",
|
||||
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "최적의 성능을 위해 세이더 덤핑을 비활성화하는 것이 좋습니다. 지금 세이더 덤핑을 비활성화하겠습니까?",
|
||||
"DialogLoadAppGameAlreadyLoadedMessage": "게임을 이미 불러 왔습니다.",
|
||||
"DialogLoadAppGameAlreadyLoadedSubMessage": "다른 게임을 시작하기 전에 에뮬레이션을 중지하거나 에뮬레이터를 닫으세요.",
|
||||
"DialogUpdateAddUpdateErrorMessage": "지정된 파일에 선택한 제목에 대한 업데이트가 포함되어 있지 않습니다!",
|
||||
"DialogSettingsBackendThreadingWarningTitle": "경고 - 백엔드 스레딩",
|
||||
"DialogSettingsBackendThreadingWarningMessage": "변경 사항을 완전히 적용하려면 이 옵션을 변경한 후 Ryujinx를 다시 시작해야 합니다. 플랫폼에 따라 Ryujinx를 사용할 때 드라이버 자체의 멀티스레딩을 수동으로 비활성화해야 할 수도 있습니다.",
|
||||
"SettingsTabGraphicsFeaturesOptions": "특징",
|
||||
"SettingsTabGraphicsBackendMultithreading": "그래픽 백엔드 멀티스레딩 :",
|
||||
"CommonAuto": "자동적 인",
|
||||
"CommonOff": "끄다",
|
||||
"CommonOn": "켜짐",
|
||||
"SettingsTabGraphicsFeaturesOptions": "기능",
|
||||
"SettingsTabGraphicsBackendMultithreading": "그래픽 백엔드 멀티스레딩:",
|
||||
"CommonAuto": "자동",
|
||||
"CommonOff": "끔",
|
||||
"CommonOn": "켬",
|
||||
"InputDialogYes": "네",
|
||||
"InputDialogNo": "아니",
|
||||
"DialogProfileInvalidProfileNameErrorMessage": "파일 이름에 잘못된 기호가 있습니다. 다시 시도하십시오.",
|
||||
"MenuBarOptionsPauseEmulation": "정지시키다",
|
||||
"MenuBarOptionsResumeEmulation": "재개하다",
|
||||
"AboutUrlTooltipMessage": "기본 브라우저에서 Ryujinx 웹사이트를 열려면 클릭하십시오.",
|
||||
"AboutDisclaimerMessage": "Ryujinx는 Nintendo™와 제휴하지 않으며,\n어떤 식으로든 또는 그 파트너.",
|
||||
"AboutAmiiboDisclaimerMessage": "AmiiboAPI(www.amiiboapi.com) 사용\nAmiibo 에뮬레이션에서.",
|
||||
"InputDialogNo": "아니오",
|
||||
"DialogProfileInvalidProfileNameErrorMessage": "파일 이름에 잘못된 문자가 포함되어 있습니다. 다시 시도하세요.",
|
||||
"MenuBarOptionsPauseEmulation": "일시 정지",
|
||||
"MenuBarOptionsResumeEmulation": "다시 시작",
|
||||
"AboutUrlTooltipMessage": "기본 브라우저에서 Ryujinx 웹사이트를 열려면 클릭하세요.",
|
||||
"AboutDisclaimerMessage": "Ryujinx는 닌텐도™,\n또는 그 파트너와 제휴하지 않습니다.",
|
||||
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com)는\nAmiibo 에뮬레이션에 사용됩니다.",
|
||||
"AboutPatreonUrlTooltipMessage": "기본 브라우저에서 Ryujinx Patreon 페이지를 열려면 클릭하세요.",
|
||||
"AboutGithubUrlTooltipMessage": "클릭하여 기본 브라우저에서 Ryujinx GitHub 페이지를 엽니다.",
|
||||
"AboutDiscordUrlTooltipMessage": "기본 브라우저에서 Ryujinx Discord 서버 초대를 열려면 클릭하세요.",
|
||||
"AboutTwitterUrlTooltipMessage": "클릭하여 기본 브라우저에서 Ryujinx Twitter 페이지를 엽니다.",
|
||||
"AboutRyujinxAboutTitle": "에 대한 :",
|
||||
"AboutRyujinxAboutContent": "Ryujinx는 Nintendo Switch™용 에뮬레이터입니다.\nPatreon에서 지원해 주세요.\n모든 최신 뉴스는 Twitter 또는 Discord에서 확인하세요.\n기고에 관심이 있는 개발자는 GitHub 또는 Discord에서 자세한 내용을 확인할 수 있습니다.",
|
||||
"AboutRyujinxMaintainersTitle": "유지 관리 :",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "기본 브라우저에서 기여자 페이지를 열려면 클릭하십시오.",
|
||||
"AboutRyujinxSupprtersTitle": "Patreon에서 지원 :",
|
||||
"AboutGithubUrlTooltipMessage": "기본 브라우저에서 Ryujinx GitHub 페이지를 열려면 클릭하세요.",
|
||||
"AboutDiscordUrlTooltipMessage": "기본 브라우저에서 Ryujinx 디스코드 서버에 대한 초대를 열려면 클릭하세요.",
|
||||
"AboutTwitterUrlTooltipMessage": "기본 브라우저에서 Ryujinx 트위터 페이지를 열려면 클릭하세요.",
|
||||
"AboutRyujinxAboutTitle": "정보:",
|
||||
"AboutRyujinxAboutContent": "Ryujinx는 닌텐도 스위치™용 에뮬레이터입니다.\nPatreon에서 지원해 주세요.\n모든 최신 뉴스는 트위터 또는 디스코드에서 확인하세요.\n기여에 관심이 있는 개발자는 GitHub 또는 디스코드에서 자세한 내용을 확인할 수 있습니다",
|
||||
"AboutRyujinxMaintainersTitle": "유지 관리:",
|
||||
"AboutRyujinxMaintainersContentTooltipMessage": "기본 브라우저에서 기여자 페이지를 열려면 클릭하세요.",
|
||||
"AboutRyujinxSupprtersTitle": "Patreon에서 후원:",
|
||||
"AmiiboSeriesLabel": "Amiibo 시리즈",
|
||||
"AmiiboCharacterLabel": "성격",
|
||||
"AmiiboCharacterLabel": "캐릭터",
|
||||
"AmiiboScanButtonLabel": "스캔",
|
||||
"AmiiboOptionsShowAllLabel": "모든 Amiibo 표시",
|
||||
"AmiiboOptionsUsRandomTagLabel": "해킹: 임의의 태그 UUID 사용",
|
||||
"DlcManagerTableHeadingEnabledLabel": "활성화됨",
|
||||
"DlcManagerTableHeadingTitleIdLabel": "제목 ID",
|
||||
"DlcManagerTableHeadingTitleIdLabel": "타이틀 ID",
|
||||
"DlcManagerTableHeadingContainerPathLabel": "컨테이너 경로",
|
||||
"DlcManagerTableHeadingFullPathLabel": "전체 경로",
|
||||
"DlcManagerRemoveAllButton": "모두 제거",
|
||||
"DlcManagerEnableAllButton": "모두 활성화",
|
||||
"DlcManagerDisableAllButton": "모두 비활성화",
|
||||
"MenuBarOptionsChangeLanguage": "언어 변경",
|
||||
"CommonSort": "정렬",
|
||||
"CommonShowNames": "이름 표시",
|
||||
"CommonFavorite": "가장 좋아하는",
|
||||
"CommonFavorite": "즐겨찾기",
|
||||
"OrderAscending": "오름차순",
|
||||
"OrderDescending": "내림차순",
|
||||
"SettingsTabGraphicsFeatures": "특징ㆍ개선 사항",
|
||||
"SettingsTabGraphicsFeatures": "기능ㆍ개선 사항",
|
||||
"ErrorWindowTitle": "오류 창",
|
||||
"ToggleDiscordTooltip": "Discord Rich Presence 활성화 또는 비활성화",
|
||||
"AddGameDirBoxTooltip": "게임 디렉토리를 입력하여 목록에 추가하세요",
|
||||
"ToggleDiscordTooltip": "\"현재 재생 중인\" 디스코드 활동에 Ryujinx를 표시할지 여부 선택",
|
||||
"AddGameDirBoxTooltip": "목록에 추가할 게임 디렉토리 입력",
|
||||
"AddGameDirTooltip": "목록에 게임 디렉토리 추가",
|
||||
"RemoveGameDirTooltip": "선택한 게임 디렉토리 제거",
|
||||
"CustomThemeCheckTooltip": "GUI에서 사용자 정의 테마 활성화 또는 비활성화",
|
||||
"CustomThemePathTooltip": "사용자 지정 GUI 테마 경로",
|
||||
"CustomThemeBrowseTooltip": "사용자 정의 GUI 테마 찾기",
|
||||
"DockModeToggleTooltip": "도킹 모드 활성화 또는 비활성화",
|
||||
"DirectKeyboardTooltip": "\"직접 키보드 액세스(HID) 지원\" 활성화 또는 비활성화(텍스트 입력 장치로 키보드에 대한 게임 액세스 제공)",
|
||||
"DirectMouseTooltip": "\"직접 마우스 액세스(HID) 지원\" 활성화 또는 비활성화(포인팅 장치로 마우스에 대한 게임 액세스 제공)",
|
||||
"CustomThemeCheckTooltip": "GUI에 사용자 지정 Avalonia 테마를 사용하여 에뮬레이터 메뉴의 모양 변경",
|
||||
"CustomThemePathTooltip": "사용자 정의 GUI 테마 경로",
|
||||
"CustomThemeBrowseTooltip": "사용자 정의 GUI 테마 찾아보기",
|
||||
"DockModeToggleTooltip": "도킹 모드에서는 에뮬레이트된 시스템이 도킹된 닌텐도 스위치처럼 작동합니다. 이것은 대부분의 게임에서 그래픽 충실도를 향상시킵니다. 반대로 이 기능을 비활성화하면 에뮬레이트된 시스템이 휴대용 닌텐도 스위치처럼 작동하여 그래픽 품질이 저하됩니다.\n\n도킹 모드를 사용하려는 경우 플레이어 1 컨트롤을 구성하세요. 휴대용 모드를 사용하려는 경우 휴대용 컨트롤을 구성합니다.\n\n확실하지 않으면 켜 두세요.",
|
||||
"DirectKeyboardTooltip": "직접 키보드 접속 (HID) 지원합니다. 텍스트 입력 장치로 키보드에 대한 게임 접속을 제공합니다.",
|
||||
"DirectMouseTooltip": "직접 마우스 접속 (HID) 지원합니다. 포인팅 장치로 마우스에 대한 게임 접속을 제공합니다.",
|
||||
"RegionTooltip": "시스템 지역 변경",
|
||||
"LanguageTooltip": "시스템 언어 변경",
|
||||
"TimezoneTooltip": "시스템 시간대 변경",
|
||||
"TimeTooltip": "시스템 시간 변경",
|
||||
"VSyncToggleTooltip": "수직 동기화 활성화 또는 비활성화",
|
||||
"PptcToggleTooltip": "PPTC 활성화 또는 비활성화",
|
||||
"FsIntegrityToggleTooltip": "게임 콘텐츠 파일에 대한 무결성 검사 활성화",
|
||||
"AudioBackendTooltip": "오디오 백엔드 변경",
|
||||
"MemoryManagerTooltip": "게스트 메모리가 매핑되고 액세스되는 방식을 변경합니다. 에뮬레이트된 CPU 성능에 큰 영향을 줍니다.",
|
||||
"MemoryManagerSoftwareTooltip": "주소 변환을 위해 소프트웨어 페이지 테이블을 사용하십시오. 정확도는 가장 높지만 성능은 가장 느립니다.",
|
||||
"MemoryManagerHostTooltip": "호스트 주소 공간에서 메모리를 직접 매핑합니다. 훨씬 더 빠른 JIT 컴파일 및 실행.",
|
||||
"MemoryManagerUnsafeTooltip": "메모리를 직접 매핑하지만 액세스하기 전에 게스트 주소 공간 내의 주소를 마스킹하지 마십시오. 더 빠르지만 안전을 희생해야 합니다. 게스트 응용 프로그램은 Ryujinx의 어디에서나 메모리에 액세스할 수 있으므로 이 모드로 신뢰할 수 있는 프로그램만 실행하십시오.",
|
||||
"DRamTooltip": "에뮬레이트된 시스템의 메모리 양을 4GiB에서 6GiB로 확장",
|
||||
"IgnoreMissingServicesTooltip": "누락된 서비스 무시 옵션 활성화 또는 비활성화",
|
||||
"GraphicsBackendThreadingTooltip": "그래픽 백엔드 멀티스레딩 활성화",
|
||||
"GalThreadingTooltip": "두 번째 스레드에서 그래픽 백엔드 명령을 실행합니다. 셰이더 컴파일의 런타임 멀티스레딩을 허용하고, 말더듬을 줄이고, 자체 멀티스레딩 지원 없이 드라이버의 성능을 개선합니다. 멀티스레딩이 있는 드라이버에서 약간 다른 최대 성능. 드라이버 내장 멀티스레딩을 올바르게 비활성화하려면 Ryujinx를 다시 시작해야 할 수도 있고 최상의 성능을 얻으려면 수동으로 수행해야 할 수도 있습니다.",
|
||||
"ShaderCacheToggleTooltip": "셰이더 캐시 활성화 또는 비활성화",
|
||||
"ResolutionScaleTooltip": "적용 가능한 렌더 타겟에 적용된 해상도 배율",
|
||||
"ResolutionScaleEntryTooltip": "1.5와 같은 부동 소수점 해상도 스케일. 비적분 스케일은 문제나 충돌을 일으킬 가능성이 더 큽니다.",
|
||||
"AnisotropyTooltip": "이방성 필터링 수준(게임에서 요청한 값을 사용하려면 자동으로 설정)",
|
||||
"AspectRatioTooltip": "렌더러 창에 적용된 종횡비.",
|
||||
"VSyncToggleTooltip": "에뮬레이트된 콘솔의 수직 동기화입니다. 기본적으로 대부분의 게임에 대한 프레임 제한 장치입니다. 비활성화하면 게임이 더 빠른 속도로 실행되거나 로딩 화면이 더 오래 걸리거나 멈출 수 있습니다.\n\n게임 내에서 선호하는 핫키로 전환할 수 있습니다. 비활성화할 계획이라면 이 작업을 수행하는 것이 좋습니다.\n\n확실하지 않으면 켜 두세요.",
|
||||
"PptcToggleTooltip": "게임이 불러올 때마다 번역할 필요가 없도록 번역된 JIT 기능을 저장합니다.\n\n게임을 처음 부팅한 후 끊김 현상을 줄이고 부팅 시간을 크게 단축합니다.\n\n확실하지 않으면 켜 두세요.",
|
||||
"FsIntegrityToggleTooltip": "게임을 부팅할 때 손상된 파일을 확인하고 손상된 파일이 감지되면 로그에 해시 오류를 표시합니다.\n\n성능에 영향을 미치지 않으며 문제 해결에 도움이 됩니다.\n\n확실하지 않으면 켜 두세요.",
|
||||
"AudioBackendTooltip": "오디오를 렌더링하는 데 사용되는 백엔드를 변경합니다.\n\nSDL2가 선호되는 반면 OpenAL 및 사운드IO는 폴백으로 사용됩니다. 더미는 소리가 나지 않습니다.\n\n확실하지 않으면 SDL2로 설정하세요.",
|
||||
"MemoryManagerTooltip": "게스트 메모리가 매핑되고 접속되는 방식을 변경합니다. 에뮬레이트된 CPU 성능에 크게 영향을 미칩니다.\n\n확실하지 않은 경우 호스트 확인 안함으로 설정하십시오.",
|
||||
"MemoryManagerSoftwareTooltip": "주소 변환을 위해 소프트웨어 페이지 테이블을 사용하세요. 정확도는 가장 높지만 성능은 가장 느립니다.",
|
||||
"MemoryManagerHostTooltip": "호스트 주소 공간의 메모리를 직접 매핑합니다. 훨씬 빠른 JIT 컴파일 및 실행합니다.",
|
||||
"MemoryManagerUnsafeTooltip": "메모리를 직접 매핑하지만 접속하기 전에 게스트 주소 공간 내의 주소를 마스킹하지 마십시오. 더 빠르지만 안전을 희생해야 합니다. 게스트 응용 프로그램은 Ryujinx의 어디에서나 메모리에 접속할 수 있으므로 이 모드에서는 신뢰할 수 있는 프로그램만 실행하세요.",
|
||||
"DRamTooltip": "대체 메모리모드 레이아웃을 활용하여 스위치 개발 모델을 모방합니다.\n\n고해상도 텍스처 팩 또는 4k 해상도 모드에만 유용합니다. 성능을 향상시키지 않습니다.\n\n확실하지 않으면 꺼 두세요.",
|
||||
"IgnoreMissingServicesTooltip": "구현되지 않은 호라이즌 OS 서비스를 무시합니다. 이것은 특정 게임을 부팅할 때 충돌을 우회하는 데 도움이 될 수 있습니다.\n\n확실하지 않으면 꺼 두세요.",
|
||||
"GraphicsBackendThreadingTooltip": "두 번째 스레드에서 그래픽 백엔드 명령을 실행합니다.\n\n세이더 컴파일 속도를 높이고 끊김 현상을 줄이며 자체 멀티스레딩 지원 없이 GPU 드라이버의 성능을 향상시킵니다. 멀티스레딩이 있는 드라이버에서 성능이 약간 향상되었습니다.\n\n잘 모르겠으면 자동으로 설정하세요.",
|
||||
"GalThreadingTooltip": "두 번째 스레드에서 그래픽 백엔드 명령을 실행합니다.\n\n세이더 컴파일 속도를 높이고 끊김 현상을 줄이며 자체 멀티스레딩 지원 없이 GPU 드라이버의 성능을 향상시킵니다. 멀티스레딩이 있는 드라이버에서 성능이 약간 향상되었습니다.\n\n잘 모르겠으면 자동으로 설정하세요.",
|
||||
"ShaderCacheToggleTooltip": "후속 실행에서 끊김 현상을 줄이는 디스크 세이더 캐시를 저장합니다.\n\n확실하지 않으면 켜 두세요.",
|
||||
"ResolutionScaleTooltip": "적용 가능한 렌더 타겟에 적용된 해상도 스케일",
|
||||
"ResolutionScaleEntryTooltip": "1.5와 같은 부동 소수점 분해능 스케일입니다. 비통합 척도는 문제나 충돌을 일으킬 가능성이 더 큽니다.",
|
||||
"AnisotropyTooltip": "이방성 필터링 수준 (게임에서 요청한 값을 사용하려면 자동으로 설정)",
|
||||
"AspectRatioTooltip": "렌더러 창에 적용된 화면비입니다.",
|
||||
"ShaderDumpPathTooltip": "그래픽 셰이더 덤프 경로",
|
||||
"FileLogTooltip": "디스크의 파일에 대한 로깅 활성화 또는 비활성화",
|
||||
"StubLogTooltip": "스텁 로그 메시지 인쇄 활성화",
|
||||
"InfoLogTooltip": "정보 로그 메시지 인쇄 활성화",
|
||||
"WarnLogTooltip": "경고 로그 메시지 인쇄 활성화",
|
||||
"ErrorLogTooltip": "오류 로그 메시지 인쇄 활성화",
|
||||
"GuestLogTooltip": "게스트 로그 메시지 인쇄 활성화",
|
||||
"FileAccessLogTooltip": "파일 액세스 로그 메시지 인쇄 활성화",
|
||||
"FSAccessLogModeTooltip": "콘솔에 대한 FS 액세스 로그 출력을 활성화합니다. 가능한 모드는 0-3입니다",
|
||||
"FileLogTooltip": "디스크의 로그 파일에 콘솔 로깅을 저장합니다. 성능에 영향을 미치지 않습니다.",
|
||||
"StubLogTooltip": "콘솔에 스텁 로그 메시지를 인쇄합니다. 성능에 영향을 미치지 않습니다.",
|
||||
"InfoLogTooltip": "콘솔에 정보 로그 메시지를 인쇄합니다. 성능에 영향을 미치지 않습니다.",
|
||||
"WarnLogTooltip": "콘솔에 경고 로그 메시지를 인쇄합니다. 성능에 영향을 미치지 않습니다.",
|
||||
"ErrorLogTooltip": "콘솔에 오류 로그 메시지를 인쇄합니다. 성능에 영향을 미치지 않습니다.",
|
||||
"TraceLogTooltip": "콘솔에 추적 로그 메시지를 인쇄합니다. 성능에 영향을 미치지 않습니다.",
|
||||
"GuestLogTooltip": "콘솔에 게스트 로그 메시지를 인쇄합니다. 성능에 영향을 미치지 않습니다.",
|
||||
"FileAccessLogTooltip": "콘솔에 파일 액세스 로그 메시지를 인쇄합니다.",
|
||||
"FSAccessLogModeTooltip": "콘솔에 대한 FS 접속 로그 출력을 활성화합니다. 가능한 모드는 0-3\t\t\t\t",
|
||||
"DeveloperOptionTooltip": "주의해서 사용",
|
||||
"OpenGlLogLevel": "적절한 로그 수준이 활성화되어 있어야 합니다",
|
||||
"DebugLogTooltip": "디버그 로그 메시지 인쇄 활성화",
|
||||
"LoadApplicationFileTooltip": "로드할 Switch 호환 파일을 선택하려면 파일 선택기를 엽니다.",
|
||||
"LoadApplicationFolderTooltip": "파일 선택기를 열어 로드할 Switch 호환 가능하고 압축을 푼 응용 프로그램을 선택합니다",
|
||||
"OpenGlLogLevel": "적절한 로그 수준을 활성화해야 함",
|
||||
"DebugLogTooltip": "콘솔에 디버그 로그 메시지를 인쇄합니다.\n\n로그를 읽기 어렵게 만들고 에뮬레이터 성능을 악화시키므로 직원이 구체적으로 지시한 경우에만 사용하세요.",
|
||||
"LoadApplicationFileTooltip": "파일 탐색기를 열어 불러올 스위치 호환 파일 선택",
|
||||
"LoadApplicationFolderTooltip": "파일 탐색기를 열어 불러올 스위치 호환 압축 해제 애플리케이션 선택",
|
||||
"OpenRyujinxFolderTooltip": "Ryujinx 파일 시스템 폴더 열기",
|
||||
"OpenRyujinxLogsTooltip": "로그가 기록되는 폴더를 엽니다.",
|
||||
"OpenRyujinxLogsTooltip": "로그가 기록된 폴더 열기",
|
||||
"ExitTooltip": "Ryujinx 종료",
|
||||
"OpenSettingsTooltip": "설정 창 열기",
|
||||
"OpenProfileManagerTooltip": "사용자 프로필 관리자 창 열기",
|
||||
"StopEmulationTooltip": "현재 게임의 에뮬레이션을 중지하고 게임 선택으로 돌아가기",
|
||||
"OpenProfileManagerTooltip": "사용자 프로파일 관리자 창 열기",
|
||||
"StopEmulationTooltip": "현재 게임의 에뮬레이션을 중지하고 게임 선택으로 돌아감",
|
||||
"CheckUpdatesTooltip": "Ryujinx 업데이트 확인",
|
||||
"OpenAboutTooltip": "정보 창 열기",
|
||||
"GridSize": "그리드 크기",
|
||||
"GridSizeTooltip": "그리드 항목의 크기 변경",
|
||||
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "포르투갈어(브라질)",
|
||||
"GridSize": "격자 크기",
|
||||
"GridSizeTooltip": "격자 항목의 크기 변경\n",
|
||||
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "포르투갈어 (브라질)",
|
||||
"AboutRyujinxContributorsButtonHeader": "모든 기여자 보기",
|
||||
"SettingsTabSystemAudioVolume": "용량 : ",
|
||||
"SettingsTabSystemAudioVolume": "볼륨 : ",
|
||||
"AudioVolumeTooltip": "오디오 볼륨 변경",
|
||||
"SettingsTabSystemEnableInternetAccess": "게스트 인터넷 액세스 활성화s",
|
||||
"EnableInternetAccessTooltip": "게스트 인터넷 액세스를 활성화합니다. 활성화된 경우 응용 프로그램은 에뮬레이트된 스위치 콘솔이 인터넷에 연결된 것처럼 작동합니다. 경우에 따라 이 옵션이 비활성화된 경우에도 응용 프로그램이 인터넷에 계속 액세스할 수 있습니다",
|
||||
"GameListContextMenuManageCheatToolTip" : "치트 관리",
|
||||
"GameListContextMenuManageCheat" : "치트 관리",
|
||||
"ControllerSettingsStickRange" : "범위:",
|
||||
"DialogStopEmulationTitle" : "Ryujinx - 에뮬레이션 중지",
|
||||
"DialogStopEmulationMessage": "에뮬레이션을 중지하시겠습니까?",
|
||||
"SettingsTabSystemEnableInternetAccess": "게스트 인터넷 접속/LAN 모드",
|
||||
"EnableInternetAccessTooltip": "에뮬레이션된 애플리케이션이 인터넷에 연결되도록 허용합니다.\n\nLAN 모드가 있는 게임은 이 모드가 활성화되고 시스템이 동일한 접속 포인트에 연결된 경우 서로 연결할 수 있습니다. 여기에는 실제 콘솔도 포함됩니다.\n\n닌텐도 서버에 연결할 수 없습니다. 인터넷에 연결을 시도하는 특정 게임에서 충돌이 발생할 수 있습니다.\n\n확실하지 않으면 꺼두세요.",
|
||||
"GameListContextMenuManageCheatToolTip": "치트 관리",
|
||||
"GameListContextMenuManageCheat": "치트 관리",
|
||||
"ControllerSettingsStickRange": "범위:",
|
||||
"DialogStopEmulationTitle": "Ryujinx - 에뮬레이션 중지",
|
||||
"DialogStopEmulationMessage": "에뮬레이션을 중지하겠습니까?",
|
||||
"SettingsTabCpu": "CPU",
|
||||
"SettingsTabAudio": "오디오",
|
||||
"SettingsTabNetwork": "회로망",
|
||||
"SettingsTabNetworkConnection" : "네트워크 연결",
|
||||
"SettingsTabCpuCache" : "CPU 캐시",
|
||||
"SettingsTabCpuMemory" : "CPU 메모리",
|
||||
"ControllerMotionTitle": "Motion Control Settings",
|
||||
"ControllerRumbleTitle": "Rumble Settings"
|
||||
"SettingsTabNetwork": "네트워크",
|
||||
"SettingsTabNetworkConnection": "네트워크 연결",
|
||||
"SettingsTabCpuCache": "CPU 캐시",
|
||||
"SettingsTabCpuMemory": "CPU 메모리",
|
||||
"DialogUpdaterFlatpakNotSupportedMessage": "FlatHub를 통해 Ryujinx를 업데이트하세요.",
|
||||
"UpdaterDisabledWarningTitle": "업데이터 비활성화입니다!",
|
||||
"GameListContextMenuOpenSdModsDirectory": "엣모스피어 Mod 디렉토리 열기",
|
||||
"GameListContextMenuOpenSdModsDirectoryToolTip": "응용 프로그램의 모드가 포함된 대체 SD 카드 Atmosphere 디렉토리를 엽니다. 실제 하드웨어용으로 패키징된 모드에 유용합니다.\n",
|
||||
"ControllerSettingsRotate90": "시계 방향으로 90° 회전",
|
||||
"IconSize": "아이콘 크기",
|
||||
"IconSizeTooltip": "게임 아이콘 크기 변경",
|
||||
"MenuBarOptionsShowConsole": "콘솔 표시",
|
||||
"ShaderCachePurgeError": "{0}에서 셰이더 캐시를 제거하는 중 오류 발생: {1}",
|
||||
"UserErrorNoKeys": "키를 찾을 수 없음",
|
||||
"UserErrorNoFirmware": "펌웨어를 찾을 수 없음",
|
||||
"UserErrorFirmwareParsingFailed": "펌웨어 구문 분석 오류",
|
||||
"UserErrorApplicationNotFound": "응용 프로그램을 찾을 수 없음",
|
||||
"UserErrorUnknown": "알 수 없는 오류",
|
||||
"UserErrorUndefined": "정의되지 않은 오류",
|
||||
"UserErrorNoKeysDescription": "Ryujinx가 'prod.keys' 파일을 찾을 수 없음",
|
||||
"UserErrorNoFirmwareDescription": "Ryujinx가 설치된 펌웨어를 찾을 수 없음",
|
||||
"UserErrorFirmwareParsingFailedDescription": "Ryujinx가 제공된 펌웨어를 구문 분석할 수 없습니다. 일반적으로 오래된 키가 원인입니다.\n",
|
||||
"UserErrorApplicationNotFoundDescription": "Ryujinx가 지정된 경로에서 유효한 응용 프로그램을 찾을 수 없습니다.\n",
|
||||
"UserErrorUnknownDescription": "알 수 없는 오류가 발생했습니다!\n",
|
||||
"UserErrorUndefinedDescription": "정의되지 않은 오류가 발생했습니다! 이런 일이 발생하면 안 되므로, 개발자에게 문의하세요!\n",
|
||||
"OpenSetupGuideMessage": "설정 가이드 열기",
|
||||
"NoUpdate": "업데이트 없음",
|
||||
"TitleUpdateVersionLabel": "버전 {0} - {1}",
|
||||
"RyujinxInfo": "Ryujinx - 정보",
|
||||
"RyujinxConfirm": "Ryujinx - 확인",
|
||||
"FileDialogAllTypes": "모든 유형",
|
||||
"Never": "절대 안 함",
|
||||
"SwkbdMinCharacters": "{0} 자 이상이어야 함",
|
||||
"SwkbdMinRangeCharacters": "{0}-{1} 자여야 함",
|
||||
"SoftwareKeyboard": "소프트웨어 키보드",
|
||||
"DialogControllerAppletMessagePlayerRange": "응용 프로그램은 다음을 사용하여 {0} 플레이어를 요청합니다:\n\n유형: {1}\n\n플레이어: {2}\n\n{3} 지금 설정을 열고 입력을 재구성하거나 닫기를 누르세요.\n",
|
||||
"DialogControllerAppletMessage": "애플리케이션은 다음을 사용하여 정확히 {0}명의 플레이어를 요청합니다:\n\n유형: {1}\n\n플레이어: {2}\n\n{3} 지금 설정을 열고 입력을 재구성하거나 닫기를 누르세요.\n",
|
||||
"DialogControllerAppletDockModeSet": "도킹 모드가 설정되었습니다. 휴대용도 유효하지 않습니다.\n\n\n",
|
||||
"UpdaterRenaming": "이전 파일 이름 바꾸는 중...",
|
||||
"UpdaterRenameFailed": "업데이터가 파일 이름을 바꿀 수 없습니다: {0}",
|
||||
"UpdaterAddingFiles": "새로운 파일을 추가하는 중...",
|
||||
"UpdaterExtracting": "업데이트를 추출하는 중...",
|
||||
"UpdaterDownloading": "업데이트 다운로드 중...",
|
||||
"Game": "게임",
|
||||
"Docked": "도킹됨",
|
||||
"Handheld": "휴대용",
|
||||
"ConnectionError": "연결 오류입니다.",
|
||||
"AboutPageDeveloperListMore": "{0} 등...",
|
||||
"ApiError": "API 오류입니다.",
|
||||
"LoadingHeading": "{0} 로딩 중",
|
||||
"CompilingPPTC": "PTC 컴파일 중",
|
||||
"CompilingShaders": "세이더 컴파일",
|
||||
"AllKeyboards": "모든 키보드",
|
||||
"OpenFileDialogTitle": "지원되는 파일을 선택",
|
||||
"OpenFolderDialogTitle": "압축을 푼 게임이 있는 폴더 선택",
|
||||
"AllSupportedFormats": "지원되는 모든 형식",
|
||||
"RyujinxUpdater": "Ryujinx 업데이터",
|
||||
"SettingsTabHotkeys": "키보드 단축키",
|
||||
"SettingsTabHotkeysHotkeys": "키보드 단축키",
|
||||
"SettingsTabHotkeysToggleVsyncHotkey": "수직 동기화 전환:",
|
||||
"SettingsTabHotkeysScreenshotHotkey": "스크린샷:",
|
||||
"SettingsTabHotkeysShowUiHotkey": "UI 표시:",
|
||||
"SettingsTabHotkeysPauseHotkey": "일시정지:",
|
||||
"SettingsTabHotkeysToggleMuteHotkey": "음소거:",
|
||||
"ControllerMotionTitle": "동작 제어 설정",
|
||||
"ControllerRumbleTitle": "진동 설정",
|
||||
"SettingsSelectThemeFileDialogTitle": "테마 파일 선택",
|
||||
"SettingsXamlThemeFile": "Xaml 테마 파일",
|
||||
"AvatarWindowTitle": "계정 관리 - 아바타",
|
||||
"Amiibo": "Amiibo",
|
||||
"Unknown": "알 수 없음",
|
||||
"Usage": "사용법",
|
||||
"Writable": "쓰기 가능",
|
||||
"SelectDlcDialogTitle": "DLC 파일 선택",
|
||||
"SelectUpdateDialogTitle": "업데이트 파일 선택",
|
||||
"UserProfileWindowTitle": "사용자 프로파일 관리자",
|
||||
"CheatWindowTitle": "치트 관리자",
|
||||
"DlcWindowTitle": "다운로드 가능한 콘텐츠 관리자",
|
||||
"UpdateWindowTitle": "타이틀 업데이트 관리자",
|
||||
"CheatWindowHeading": "{0} [{1}]에 사용할 수 있는 치트",
|
||||
"DlcWindowHeading": "{1} ({2})에 사용할 수 있는 {0} 다운로드 가능한 콘텐츠",
|
||||
"UserProfilesEditProfile": "선택 항목 편집",
|
||||
"Cancel": "취소",
|
||||
"Save": "저장",
|
||||
"Discard": "삭제",
|
||||
"UserProfilesSetProfileImage": "프로파일 이미지 설정",
|
||||
"UserProfileEmptyNameError": "이름 필요",
|
||||
"UserProfileNoImageError": "프로파일 이미지를 설정해야 함",
|
||||
"GameUpdateWindowHeading": "{1} ({2})에 대한 {0} 업데이트 사용 가능",
|
||||
"SettingsTabHotkeysResScaleUpHotkey": "해상도 증가:",
|
||||
"SettingsTabHotkeysResScaleDownHotkey": "해상도 감소:",
|
||||
"UserProfilesName": "이름:",
|
||||
"UserProfilesUserId": "사용자 Id:",
|
||||
"SettingsTabGraphicsBackend": "그래픽 백엔드",
|
||||
"SettingsTabGraphicsBackendTooltip": "사용할 그래픽 백엔드",
|
||||
"SettingsEnableTextureRecompression": "텍스처 재압축 활성화",
|
||||
"SettingsEnableTextureRecompressionTooltip": "VRAM 사용량을 줄이기 위해 특정 텍스처를 압축합니다.\n\n4GiB VRAM 미만의 GPU와 함께 사용하는 것이 좋습니다.\n\n확실하지 않으면 꺼 두세요.",
|
||||
"SettingsTabGraphicsPreferredGpu": "선호하는 GPU",
|
||||
"SettingsTabGraphicsPreferredGpuTooltip": "Vulkan 그래픽 백엔드와 함께 사용할 그래픽 카드를 선택하세요.\n\nOpenGL이 사용할 GPU에는 영향을 미치지 않습니다.\n\n확실하지 않은 경우 \"dGPU\" 플래그가 지정된 GPU로 설정하세요. 없는 경우, 그대로 두세요.\n",
|
||||
"SettingsAppRequiredRestartMessage": "Ryujinx 재시작 필요",
|
||||
"SettingsGpuBackendRestartMessage": "그래픽 백엔드 또는 GPU 설정이 수정되었습니다. 적용하려면 다시 시작해야 함\n",
|
||||
"SettingsGpuBackendRestartSubMessage": "지금 다시 시작하겠습니까?",
|
||||
"RyujinxUpdaterMessage": "Ryujinx를 최신 버전으로 업데이트하겠습니까?",
|
||||
"SettingsTabHotkeysVolumeUpHotkey": "볼륨 증가:",
|
||||
"SettingsTabHotkeysVolumeDownHotkey": "볼륨 감소:",
|
||||
"SettingsEnableMacroHLE": "매크로 HLE 활성화",
|
||||
"SettingsEnableMacroHLETooltip": "GPU 매크로 코드의 높은 수준 에뮬레이션입니다.\n\n성능이 향상되지만 일부 게임에서 그래픽 결함이 발생할 수 있습니다.\n\n확실하지 않으면 켜 두세요.",
|
||||
"VolumeShort": "볼륨",
|
||||
"UserProfilesManageSaves": "저장 관리",
|
||||
"DeleteUserSave": "이 게임에 대한 사용자 저장을 삭제하겠습니까?",
|
||||
"IrreversibleActionNote": "이 작업은 되돌릴 수 없습니다.",
|
||||
"SaveManagerHeading": "{0}의 저장 관리",
|
||||
"SaveManagerTitle": "저장 관리자",
|
||||
"Name": "이름",
|
||||
"Size": "크기",
|
||||
"Search": "검색",
|
||||
"UserProfilesRecoverLostAccounts": "잃어버린 계정 복구",
|
||||
"Recover": "복구",
|
||||
"UserProfilesRecoverHeading": "다음 계정에 대한 저장 발견"
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
{
|
||||
"Language": "Polski",
|
||||
"MenuBarFileOpenApplet": "Otwórz Aplet",
|
||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Otwórz aplet Mii Editor w trybie Indywidualnym",
|
||||
"SettingsTabInputDirectMouseAccess": "Bezpośredni Dostęp do Myszy",
|
||||
"SettingsTabSystemMemoryManagerMode": "Tryb Menedżera Pamięci:",
|
||||
"SettingsTabSystemMemoryManagerModeSoftware": "Software",
|
||||
"SettingsTabSystemMemoryManagerModeSoftware": "Oprogramowania",
|
||||
"SettingsTabSystemMemoryManagerModeHost": "Host (szybko)",
|
||||
"SettingsTabSystemMemoryManagerModeHostUnchecked": "Host Niesprawdzony (najszybciej, niebezpiecznie)",
|
||||
"MenuBarFile": "_Plik",
|
||||
@ -28,7 +29,7 @@
|
||||
"MenuBarHelp": "Pomoc",
|
||||
"MenuBarHelpCheckForUpdates": "Sprawdź Aktualizacje",
|
||||
"MenuBarHelpAbout": "O Aplikacji",
|
||||
"MenuSearch": "Szukaj...",
|
||||
"MenuSearch": "Wyszukaj...",
|
||||
"GameListHeaderFavorite": "Ulub",
|
||||
"GameListHeaderIcon": "Ikona",
|
||||
"GameListHeaderApplication": "Nazwa",
|
||||
@ -41,10 +42,10 @@
|
||||
"GameListHeaderPath": "Ścieżka",
|
||||
"GameListContextMenuOpenUserSaveDirectory": "Otwórz Katalog Zapisów Użytkownika",
|
||||
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Otwiera katalog, który zawiera Zapis Użytkownika Aplikacji",
|
||||
"GameListContextMenuOpenUserDeviceDirectory": "Otwórz Katalog Urządzeń Użytkownika",
|
||||
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Otwiera katalog, który zawiera Zapis Urządzenia Aplikacji",
|
||||
"GameListContextMenuOpenUserBcatDirectory": "Otwórz Katalog BCAT Użytkownika",
|
||||
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Otwiera katalog, który zawiera Zapis BCAT Aplikacji",
|
||||
"GameListContextMenuOpenDeviceSaveDirectory": "Otwórz Katalog Urządzeń Użytkownika",
|
||||
"GameListContextMenuOpenDeviceSaveDirectoryToolTip": "Otwiera katalog, który zawiera Zapis Urządzenia Aplikacji",
|
||||
"GameListContextMenuOpenBcatSaveDirectory": "Otwórz Katalog BCAT Użytkownika",
|
||||
"GameListContextMenuOpenBcatSaveDirectoryToolTip": "Otwiera katalog, który zawiera Zapis BCAT Aplikacji",
|
||||
"GameListContextMenuManageTitleUpdates": "Zarządzaj Aktualizacjami Tytułów",
|
||||
"GameListContextMenuManageTitleUpdatesToolTip": "Otwiera okno zarządzania Aktualizacjami Tytułu",
|
||||
"GameListContextMenuManageDlc": "Zarządzaj DLC",
|
||||
@ -119,7 +120,7 @@
|
||||
"SettingsTabSystemAudioBackendSDL2": "SDL2",
|
||||
"SettingsTabSystemHacks": "Hacki",
|
||||
"SettingsTabSystemHacksNote": " (mogą powodować niestabilność)",
|
||||
"SettingsTabSystemExpandDramSize": "Rozszerz Rozmiar DRAM do 6 GiB",
|
||||
"SettingsTabSystemExpandDramSize": "Użyj alternatywnego układu pamięci (Deweloperzy)",
|
||||
"SettingsTabSystemIgnoreMissingServices": "Ignoruj Brakujące Usługi",
|
||||
"SettingsTabGraphics": "Grafika",
|
||||
"SettingsTabGraphicsAPI": "Graficzne API",
|
||||
@ -157,6 +158,7 @@
|
||||
"SettingsTabLoggingEnableFsAccessLogs": "Włącz Logi Dostępu do Systemu Plików",
|
||||
"SettingsTabLoggingFsGlobalAccessLogMode": "Tryb Globalnych Logów Systemu Plików:",
|
||||
"SettingsTabLoggingDeveloperOptions": "Opcje programistyczne (OSTRZEŻENIE: Zmniejszą wydajność)",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevel": "Ilość Logów Backendu Graficznego:",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Żadne",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelError": "Błędy",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Spowolnienia",
|
||||
@ -215,7 +217,7 @@
|
||||
"ControllerSettingsLStickStick": "Gałka",
|
||||
"ControllerSettingsLStickInvertXAxis": "Odwróć X Gałki",
|
||||
"ControllerSettingsLStickInvertYAxis": "Odwróć Y Gałki",
|
||||
"ControllerSettingsLStickDeadzone": "Deadzone:",
|
||||
"ControllerSettingsLStickDeadzone": "Martwa Strefa:",
|
||||
"ControllerSettingsRStick": "Prawa Gałka",
|
||||
"ControllerSettingsRStickButton": "Przycisk",
|
||||
"ControllerSettingsRStickUp": "Góra",
|
||||
@ -225,7 +227,7 @@
|
||||
"ControllerSettingsRStickStick": "Gałka",
|
||||
"ControllerSettingsRStickInvertXAxis": "Odwróć X Gałki",
|
||||
"ControllerSettingsRStickInvertYAxis": "Odwróć Y Gałki",
|
||||
"ControllerSettingsRStickDeadzone": "Deadzone:",
|
||||
"ControllerSettingsRStickDeadzone": "Martwa Strefa:",
|
||||
"ControllerSettingsTriggersLeft": "Lewe Triggery",
|
||||
"ControllerSettingsTriggersRight": "Prawe Triggery",
|
||||
"ControllerSettingsTriggersButtonsLeft": "Lewe Przyciski Triggerów",
|
||||
@ -258,7 +260,7 @@
|
||||
"UserProfilesChangeProfileImage": "Zmień Obraz Profilu",
|
||||
"UserProfilesAvailableUserProfiles": "Dostępne Profile Użytkowników:",
|
||||
"UserProfilesAddNewProfile": "Utwórz Profil",
|
||||
"UserProfilesDeleteSelectedProfile": "Usuń Zaznaczone",
|
||||
"UserProfilesDelete": "Usuwać",
|
||||
"UserProfilesClose": "Zamknij",
|
||||
"ProfileImageSelectionTitle": "Wybór Obrazu Profilu",
|
||||
"ProfileImageSelectionHeader": "Wybierz zdjęcie profilowe",
|
||||
@ -314,7 +316,7 @@
|
||||
"DialogUpdaterConvertFailedMessage": "Nie udało się przekonwertować obecnej wersji Ryujinx.",
|
||||
"DialogUpdaterCancelUpdateMessage": "Anulowanie Aktualizacji!",
|
||||
"DialogUpdaterAlreadyOnLatestVersionMessage": "Używasz już najnowszej wersji Ryujinx!",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "Wystąpił błąd podczas próby uzyskania informacji o wydaniu z Github Release. Może to być spowodowane nową wersją kompilowaną przez GitHub Actions. Spróbuj ponownie za kilka minut.",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "Wystąpił błąd podczas próby uzyskania informacji o wydaniu z GitHub Release. Może to być spowodowane nową wersją kompilowaną przez GitHub Actions. Spróbuj ponownie za kilka minut.",
|
||||
"DialogUpdaterConvertFailedGithubMessage": "Nie udało się przekonwertować otrzymanej wersji Ryujinx z Github Release.",
|
||||
"DialogUpdaterDownloadingMessage": "Pobieranie Aktualizacji...",
|
||||
"DialogUpdaterExtractionMessage": "Wypakowywanie Aktualizacji...",
|
||||
@ -411,6 +413,8 @@
|
||||
"DlcManagerTableHeadingContainerPathLabel": "Ścieżka Kontenera",
|
||||
"DlcManagerTableHeadingFullPathLabel": "Pełna Ścieżka",
|
||||
"DlcManagerRemoveAllButton": "Usuń Wszystkie",
|
||||
"DlcManagerEnableAllButton": "Włącz Wszystkie",
|
||||
"DlcManagerDisableAllButton": "Wyłącz Wszystkie",
|
||||
"MenuBarOptionsChangeLanguage": "Zmień Język",
|
||||
"CommonSort": "Sortuj",
|
||||
"CommonShowNames": "Pokaż Nazwy",
|
||||
@ -441,7 +445,7 @@
|
||||
"MemoryManagerSoftwareTooltip": "Użyj tabeli stron oprogramowania do translacji adresów. Najwyższa celność, ale najwolniejsza wydajność.",
|
||||
"MemoryManagerHostTooltip": "Bezpośrednio mapuj pamięć w przestrzeni adresowej hosta. Znacznie szybsza kompilacja i wykonanie JIT.",
|
||||
"MemoryManagerUnsafeTooltip": "Bezpośrednio mapuj pamięć, ale nie maskuj adresu w przestrzeni adresowej gościa przed uzyskaniem dostępu. Szybciej, ale kosztem bezpieczeństwa. Aplikacja gościa może uzyskać dostęp do pamięci z dowolnego miejsca w Ryujinx, więc w tym trybie uruchamiaj tylko programy, którym ufasz.",
|
||||
"DRamTooltip": "Zwiększa ilość pamięci w emulowanym systemie z 4 GiB do 6 GiB.\n\nJest to przydatne tylko w przypadku pakietów tekstur o wyższej rozdzielczości lub modów w rozdzielczości 4k. NIE poprawia wydajności.\n\nW razie wątpliwości pozostaw WYŁĄCZONE.",
|
||||
"DRamTooltip": "Wykorzystuje alternatywny układ MemoryMode, aby naśladować model rozwojowy Switcha.\n\nJest to przydatne tylko w przypadku pakietów tekstur o wyższej rozdzielczości lub modów w rozdzielczości 4k. NIE poprawia wydajności.\n\nW razie wątpliwości pozostaw WYŁĄCZONE.",
|
||||
"IgnoreMissingServicesTooltip": "Ignoruje niezaimplementowane usługi Horizon OS. Może to pomóc w ominięciu awarii podczas uruchamiania niektórych gier.\n\nW razie wątpliwości pozostaw WYŁĄCZONE.",
|
||||
"GraphicsBackendThreadingTooltip": "Wykonuje polecenia backend'u graficznego w drugim wątku.\n\nPrzyspiesza kompilację shaderów, zmniejsza zacinanie się i poprawia wydajność sterowników GPU bez własnej obsługi wielowątkowości. Nieco lepsza wydajność w sterownikach z wielowątkowością.\n\nUstaw na AUTO, jeśli nie masz pewności.",
|
||||
"GalThreadingTooltip": "Wykonuje polecenia backend'u graficznego w drugim wątku.\n\nPrzyspiesza kompilację shaderów, zmniejsza zacinanie się i poprawia wydajność sterowników GPU bez własnej obsługi wielowątkowości. Nieco lepsza wydajność w sterownikach z wielowątkowością.\n\nUstaw na AUTO, jeśli nie masz pewności.",
|
||||
@ -563,24 +567,24 @@
|
||||
"Writable": "Zapisywalne",
|
||||
"SelectDlcDialogTitle": "Wybierz pliki DLC",
|
||||
"SelectUpdateDialogTitle": "Wybierz pliki aktualizacji",
|
||||
"UserProfileWindowTitle": "Zarządzaj Profilami Użytkowników",
|
||||
"CheatWindowTitle": "Zarządzaj Kodami do Gier",
|
||||
"DlcWindowTitle": "Zarządzaj DLC Gier",
|
||||
"UpdateWindowTitle": "Zarządzaj Aktualizacjami Gier",
|
||||
"UserProfileWindowTitle": "Menedżer Profili Użytkowników",
|
||||
"CheatWindowTitle": "Menedżer Kodów",
|
||||
"DlcWindowTitle": "Menedżer Zawartości do Pobrania",
|
||||
"UpdateWindowTitle": "Menedżer Aktualizacji Tytułu",
|
||||
"CheatWindowHeading": "Kody Dostępne dla {0} [{1}]",
|
||||
"DlcWindowHeading": "DLC Dostępne dla {0} [{1}]",
|
||||
"DlcWindowHeading": "{0} Zawartości do Pobrania dostępna dla {1} ({2})",
|
||||
"UserProfilesEditProfile": "Edytuj Zaznaczone",
|
||||
"Cancel": "Anuluj",
|
||||
"Save": "Zapisz",
|
||||
"Discard": "Odrzuć",
|
||||
"UserProfilesSetProfileImage": "Ustaw Obraz Profilu",
|
||||
"UserProfileEmptyNameError": "Nazwa jest wymagana",
|
||||
"UserProfileNoImageError": "Należy ustawić obraz profilowy",
|
||||
"GameUpdateWindowHeading": "Aktualizacje Dostępne dla {0} [{1}]",
|
||||
"UserProfileNoImageError": "Należy ustawić obraz profilowy",
|
||||
"GameUpdateWindowHeading": "{0} Aktualizacje dostępne dla {1} ({2})",
|
||||
"SettingsTabHotkeysResScaleUpHotkey": "Zwiększ Rozdzielczość:",
|
||||
"SettingsTabHotkeysResScaleDownHotkey": "Zmniejsz Rozdzielczość:",
|
||||
"UserProfilesName": "Nazwa:",
|
||||
"UserProfilesUserId" : "ID Użytkownika:",
|
||||
"UserProfilesUserId": "ID Użytkownika:",
|
||||
"SettingsTabGraphicsBackend": "Backend Graficzny",
|
||||
"SettingsTabGraphicsBackendTooltip": "Używalne Backendy Graficzne",
|
||||
"SettingsEnableTextureRecompression": "Włącz Rekompresję Tekstur",
|
||||
@ -593,5 +597,18 @@
|
||||
"RyujinxUpdaterMessage": "Czy chcesz zaktualizować Ryujinx do najnowszej wersji?",
|
||||
"SettingsTabHotkeysVolumeUpHotkey": "Zwiększ Głośność:",
|
||||
"SettingsTabHotkeysVolumeDownHotkey": "Zmniejsz Głośność:",
|
||||
"VolumeShort": "Głoś"
|
||||
"SettingsEnableMacroHLE": "Włącz Macro HLE",
|
||||
"SettingsEnableMacroHLETooltip": "Wysokopoziomowa emulacja kodu GPU Macro.\n\nPoprawia wydajność, ale może powodować błędy graficzne w niektórych grach.\n\nW razie wątpliwości pozostaw WŁĄCZONE.",
|
||||
"VolumeShort": "Głoś",
|
||||
"UserProfilesManageSaves": "Zarządzaj Zapisami",
|
||||
"DeleteUserSave": "Czy chcesz usunąć zapis użytkownika dla tej gry?",
|
||||
"IrreversibleActionNote": "Ta czynność nie jest odwracalna.",
|
||||
"SaveManagerHeading": "Zarządzaj Zapisami dla {0}",
|
||||
"SaveManagerTitle": "Menedżer Zapisów",
|
||||
"Name": "Nazwa",
|
||||
"Size": "Rozmiar",
|
||||
"Search": "Wyszukaj",
|
||||
"UserProfilesRecoverLostAccounts": "Odzyskaj Utracone Konta",
|
||||
"Recover": "Odzyskaj",
|
||||
"UserProfilesRecoverHeading": "Znaleziono zapisy dla następujących kont"
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"Language": "Português (BR)",
|
||||
"MenuBarFileOpenApplet": "Abrir Applet",
|
||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Abrir editor Mii em modo avulso",
|
||||
"SettingsTabInputDirectMouseAccess": "Acesso direto ao mouse",
|
||||
@ -14,7 +15,7 @@
|
||||
"MenuBarFileExit": "_Sair",
|
||||
"MenuBarOptions": "_Opções",
|
||||
"MenuBarOptionsToggleFullscreen": "_Mudar para tela cheia",
|
||||
"MenuBarOptionsStartGamesInFullscreen": "_Iniciar jogos em tela cheia",
|
||||
"MenuBarOptionsStartGamesInFullscreen": "Iniciar jogos em tela cheia",
|
||||
"MenuBarOptionsStopEmulation": "_Encerrar emulação",
|
||||
"MenuBarOptionsSettings": "_Configurações",
|
||||
"MenuBarOptionsManageUserProfiles": "_Gerenciar perfis de usuário",
|
||||
@ -41,10 +42,10 @@
|
||||
"GameListHeaderPath": "Caminho",
|
||||
"GameListContextMenuOpenUserSaveDirectory": "Abrir diretório de saves do usuário",
|
||||
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Abre o diretório que contém jogos salvos para o usuário atual",
|
||||
"GameListContextMenuOpenUserDeviceDirectory": "Abrir diretório de saves de dispositivo do usuário",
|
||||
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Abre o diretório que contém saves do dispositivo para o usuário atual",
|
||||
"GameListContextMenuOpenUserBcatDirectory": "Abrir diretório de saves BCAT do usuário",
|
||||
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Abre o diretório que contém saves BCAT para o usuário atual",
|
||||
"GameListContextMenuOpenDeviceSaveDirectory": "Abrir diretório de saves de dispositivo do usuário",
|
||||
"GameListContextMenuOpenDeviceSaveDirectoryToolTip": "Abre o diretório que contém saves do dispositivo para o usuário atual",
|
||||
"GameListContextMenuOpenBcatSaveDirectory": "Abrir diretório de saves BCAT do usuário",
|
||||
"GameListContextMenuOpenBcatSaveDirectoryToolTip": "Abre o diretório que contém saves BCAT para o usuário atual",
|
||||
"GameListContextMenuManageTitleUpdates": "Gerenciar atualizações do jogo",
|
||||
"GameListContextMenuManageTitleUpdatesToolTip": "Abre a janela de gerenciamento de atualizações",
|
||||
"GameListContextMenuManageDlc": "Gerenciar DLCs",
|
||||
@ -125,7 +126,7 @@
|
||||
"SettingsTabGraphicsAPI": "API gráfica",
|
||||
"SettingsTabGraphicsEnableShaderCache": "Habilitar cache de shader",
|
||||
"SettingsTabGraphicsAnisotropicFiltering": "Filtragem anisotrópica:",
|
||||
"SettingsTabGraphicsAnisotropicFilteringAuto": "Auto",
|
||||
"SettingsTabGraphicsAnisotropicFilteringAuto": "Automático",
|
||||
"SettingsTabGraphicsAnisotropicFiltering2x": "2x",
|
||||
"SettingsTabGraphicsAnisotropicFiltering4x": "4x",
|
||||
"SettingsTabGraphicsAnisotropicFiltering8x": "8x",
|
||||
@ -157,6 +158,7 @@
|
||||
"SettingsTabLoggingEnableFsAccessLogs": "Habilitar logs de acesso ao sistema de arquivos",
|
||||
"SettingsTabLoggingFsGlobalAccessLogMode": "Modo global de logs do sistema de arquivos:",
|
||||
"SettingsTabLoggingDeveloperOptions": "Opções do desenvolvedor (AVISO: Vai reduzir a performance)",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevel": "Nível de log do backend gráfico:",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Nenhum",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelError": "Erro",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Lentidão",
|
||||
@ -182,7 +184,7 @@
|
||||
"ControllerSettingsHandheld": "Portátil",
|
||||
"ControllerSettingsInputDevice": "Dispositivo de entrada",
|
||||
"ControllerSettingsRefresh": "Atualizar",
|
||||
"ControllerSettingsDeviceDisabled": "Disabled",
|
||||
"ControllerSettingsDeviceDisabled": "Desabilitado",
|
||||
"ControllerSettingsControllerType": "Tipo do controle",
|
||||
"ControllerSettingsControllerTypeHandheld": "Portátil",
|
||||
"ControllerSettingsControllerTypeProController": "Pro Controller",
|
||||
@ -226,11 +228,11 @@
|
||||
"ControllerSettingsRStickInvertXAxis": "Inverter eixo X",
|
||||
"ControllerSettingsRStickInvertYAxis": "Inverter eixo Y",
|
||||
"ControllerSettingsRStickDeadzone": "Zona morta:",
|
||||
"ControllerSettingsTriggers": "Gatilhos",
|
||||
"ControllerSettingsTriggersLeft": "Gatilhos esquerda",
|
||||
"ControllerSettingsTriggersRight": "Gatilhos direita",
|
||||
"ControllerSettingsTriggersButtonsLeft": "Botões de gatilho esquerda",
|
||||
"ControllerSettingsTriggersButtonsRight": "Botões de gatilho direita",
|
||||
"ControllerSettingsTriggers": "Gatilhos",
|
||||
"ControllerSettingsTriggerL": "L",
|
||||
"ControllerSettingsTriggerR": "R",
|
||||
"ControllerSettingsTriggerZL": "ZL",
|
||||
@ -258,7 +260,7 @@
|
||||
"UserProfilesChangeProfileImage": "Mudar imagem de perfil",
|
||||
"UserProfilesAvailableUserProfiles": "Perfis de usuário disponíveis:",
|
||||
"UserProfilesAddNewProfile": "Adicionar novo perfil",
|
||||
"UserProfilesDeleteSelectedProfile": "Apagar perfil selecionado",
|
||||
"UserProfilesDelete": "Apagar",
|
||||
"UserProfilesClose": "Fechar",
|
||||
"ProfileImageSelectionTitle": "Seleção da imagem de perfil",
|
||||
"ProfileImageSelectionHeader": "Escolha uma imagem de perfil",
|
||||
@ -279,7 +281,7 @@
|
||||
"ControllerSettingsRemoveProfileToolTip": "Remover perfil",
|
||||
"ControllerSettingsSaveProfileToolTip": "Salvar perfil",
|
||||
"MenuBarFileToolsTakeScreenshot": "Salvar captura de tela",
|
||||
"MenuBarFileToolsHideUi": "Esconder interface gráfica",
|
||||
"MenuBarFileToolsHideUi": "Hide UI",
|
||||
"GameListContextMenuToggleFavorite": "Alternar favorito",
|
||||
"GameListContextMenuToggleFavoriteToolTip": "Marca ou desmarca jogo como favorito",
|
||||
"SettingsTabGeneralTheme": "Tema",
|
||||
@ -314,7 +316,7 @@
|
||||
"DialogUpdaterConvertFailedMessage": "Falha ao converter a versão atual do Ryujinx.",
|
||||
"DialogUpdaterCancelUpdateMessage": "Cancelando atualização!",
|
||||
"DialogUpdaterAlreadyOnLatestVersionMessage": "Você já está usando a versão mais recente do Ryujinx!",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "Ocorreu um erro ao tentar obter informações de atualização do AppVeyor.",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "Ocorreu um erro ao tentar obter as informações de atualização do GitHub Release. Isso pode ser causado se uma nova versão estiver sendo compilado pelas Ações do GitHub. Tente novamente em alguns minutos.",
|
||||
"DialogUpdaterConvertFailedGithubMessage": "Falha ao converter a versão do Ryujinx recebida do AppVeyor.",
|
||||
"DialogUpdaterDownloadingMessage": "Baixando atualização...",
|
||||
"DialogUpdaterExtractionMessage": "Extraindo atualização...",
|
||||
@ -411,6 +413,8 @@
|
||||
"DlcManagerTableHeadingContainerPathLabel": "Caminho do container",
|
||||
"DlcManagerTableHeadingFullPathLabel": "Caminho completo",
|
||||
"DlcManagerRemoveAllButton": "Remover todos",
|
||||
"DlcManagerEnableAllButton": "Habilitar todos",
|
||||
"DlcManagerDisableAllButton": "Desabilitar todos",
|
||||
"MenuBarOptionsChangeLanguage": "Mudar idioma",
|
||||
"CommonSort": "Ordenar",
|
||||
"CommonShowNames": "Exibir nomes",
|
||||
@ -477,7 +481,7 @@
|
||||
"GridSizeTooltip": "Mudar tamanho dos items da grade",
|
||||
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "Português do Brasil",
|
||||
"AboutRyujinxContributorsButtonHeader": "Ver todos os contribuidores",
|
||||
"SettingsTabSystemAudioVolume": "Volume: ",
|
||||
"SettingsTabSystemAudioVolume": "Volume:",
|
||||
"AudioVolumeTooltip": "Mudar volume do áudio",
|
||||
"SettingsTabSystemEnableInternetAccess": "Habilitar acesso à internet do programa convidado",
|
||||
"EnableInternetAccessTooltip": "Habilita acesso à internet do programa convidado. Se habilitado, o aplicativo vai se comportar como se o sistema Switch emulado estivesse conectado a Internet. Note que em alguns casos, aplicativos podem acessar a Internet mesmo com essa opção desabilitada",
|
||||
@ -516,7 +520,7 @@
|
||||
"OpenSetupGuideMessage": "Abrir o guia de configuração",
|
||||
"NoUpdate": "Sem atualizações",
|
||||
"TitleUpdateVersionLabel": "Versão {0} - {1}",
|
||||
"RyujinxInfo": "Ryujinx - Info",
|
||||
"RyujinxInfo": "Ryujinx - Informação",
|
||||
"RyujinxConfirm": "Ryujinx - Confirmação",
|
||||
"FileDialogAllTypes": "Todos os tipos",
|
||||
"Never": "Nunca",
|
||||
@ -554,10 +558,57 @@
|
||||
"SettingsTabHotkeysToggleMuteHotkey": "Mudo:",
|
||||
"ControllerMotionTitle": "Configurações do controle de movimento",
|
||||
"ControllerRumbleTitle": "Configurações de vibração",
|
||||
"SettingsSelectThemeFileDialogTitle" : "Selecionar arquivo do tema",
|
||||
"SettingsXamlThemeFile" : "Arquivo de tema Xaml",
|
||||
"SettingsSelectThemeFileDialogTitle": "Selecionar arquivo do tema",
|
||||
"SettingsXamlThemeFile": "Arquivo de tema Xaml",
|
||||
"AvatarWindowTitle": "Gerenciar contas - Avatar",
|
||||
"Amiibo": "Amiibo",
|
||||
"Unknown": "Desconhecido",
|
||||
"Usage": "Uso",
|
||||
"Writable": "Gravável",
|
||||
"SelectDlcDialogTitle": "Selecionar arquivos de DLC",
|
||||
"SelectUpdateDialogTitle": "Selecionar arquivos de atualização",
|
||||
"UserProfileWindowTitle": "Gerenciador de perfis de usuário",
|
||||
"CheatWindowTitle": "Gerenciador de Cheats",
|
||||
"DlcWindowTitle": "Gerenciador de DLC",
|
||||
"UpdateWindowTitle": "Gerenciador de atualizações",
|
||||
"CheatWindowHeading": "Cheats disponíveis para {0} [{1}]",
|
||||
"DlcWindowHeading": "{0} DLCs disponíveis para {1} ({2})",
|
||||
"UserProfilesEditProfile": "Editar selecionado",
|
||||
"Cancel": "Cancelar",
|
||||
"Save": "Salvar",
|
||||
"Discard": "Descartar",
|
||||
"UserProfilesSetProfileImage": "Definir imagem de perfil",
|
||||
"UserProfileEmptyNameError": "É necessário um nome",
|
||||
"UserProfileNoImageError": "A imagem de perfil deve ser definida",
|
||||
"GameUpdateWindowHeading": "{0} atualizações disponíveis para {1} ({2})",
|
||||
"SettingsTabHotkeysResScaleUpHotkey": "Aumentar a resolução:",
|
||||
"SettingsTabHotkeysResScaleDownHotkey": "Diminuir a resolução:",
|
||||
"UserProfilesName": "Nome:",
|
||||
"UserProfilesUserId": "ID de usuário:",
|
||||
"SettingsTabGraphicsBackend": "Backend gráfico",
|
||||
"SettingsTabGraphicsBackendTooltip": "Backend gráfico a ser usado",
|
||||
"SettingsEnableTextureRecompression": "Habilitar recompressão de texturas",
|
||||
"SettingsEnableTextureRecompressionTooltip": "Comprime certas texturas para reduzir o uso da VRAM.\n\nRecomendado para uso com GPUs com menos de 4GB VRAM.\n\nEm caso de dúvida, deixe DESLIGADO.",
|
||||
"SettingsTabGraphicsPreferredGpu": "GPU preferencial",
|
||||
"SettingsTabGraphicsPreferredGpuTooltip": "Selecione a placa de vídeo que será usada com o backend gráfico Vulkan.\n\nNão afeta a GPU que OpenGL usará.\n\nSelecione \"dGPU\" em caso de dúvida. Se não houver nenhuma, não mexa.",
|
||||
"SettingsAppRequiredRestartMessage": "Reinicialização do Ryujinx necessária",
|
||||
"SettingsGpuBackendRestartMessage": "Configurações do backend gráfico ou da GPU foram alteradas. Uma reinicialização é necessária para que as mudanças tenham efeito.",
|
||||
"SettingsGpuBackendRestartSubMessage": "Deseja reiniciar agora?",
|
||||
"RyujinxUpdaterMessage": "Você quer atualizar o Ryujinx para a última versão?",
|
||||
"SettingsTabHotkeysVolumeUpHotkey": "Aumentar volume:",
|
||||
"SettingsTabHotkeysVolumeDownHotkey": "Diminuir volume:",
|
||||
"SettingsEnableMacroHLE": "Habilitar emulação de alto nível para Macros",
|
||||
"SettingsEnableMacroHLETooltip": "Habilita emulação de alto nível de códigos Macro da GPU.\n\nMelhora a performance, mas pode causar problemas gráficos em alguns jogos.\n\nEm caso de dúvida, deixe ATIVADO."
|
||||
"SettingsEnableMacroHLETooltip": "Habilita emulação de alto nível de códigos Macro da GPU.\n\nMelhora a performance, mas pode causar problemas gráficos em alguns jogos.\n\nEm caso de dúvida, deixe ATIVADO.",
|
||||
"VolumeShort": "Vol",
|
||||
"UserProfilesManageSaves": "Gerenciar jogos salvos",
|
||||
"DeleteUserSave": "Deseja apagar o jogo salvo do usuário para este jogo?",
|
||||
"IrreversibleActionNote": "Esta ação não é reversível.",
|
||||
"SaveManagerHeading": "Gerenciar jogos salvos para {0}",
|
||||
"SaveManagerTitle": "Gerenciador de jogos salvos",
|
||||
"Name": "Nome",
|
||||
"Size": "Tamanho",
|
||||
"Search": "Buscar",
|
||||
"UserProfilesRecoverLostAccounts": "Recuperar contas perdidas",
|
||||
"Recover": "Recuperar",
|
||||
"UserProfilesRecoverHeading": "Jogos salvos foram encontrados para as seguintes contas"
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"Language": "Русский",
|
||||
"MenuBarFileOpenApplet": "Открыть апплет",
|
||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Открыть апплет Mii Editor в автономном режиме.",
|
||||
"SettingsTabInputDirectMouseAccess": "Прямой доступ с помощью мыши",
|
||||
@ -41,10 +42,10 @@
|
||||
"GameListHeaderPath": "Путь",
|
||||
"GameListContextMenuOpenUserSaveDirectory": "Открыть каталог сохранений пользователя",
|
||||
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Открывает каталог, содержащий пользовательское сохранение приложения",
|
||||
"GameListContextMenuOpenUserDeviceDirectory": "Открыть каталог пользовательских устройств",
|
||||
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Открывает каталог, содержащий сохранение устройства приложения",
|
||||
"GameListContextMenuOpenUserBcatDirectory": "Открыть каталог пользователей BCAT",
|
||||
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Открывает каталог, содержащий BCAT сохранения приложения.",
|
||||
"GameListContextMenuOpenDeviceSaveDirectory": "Открыть каталог пользовательских устройств",
|
||||
"GameListContextMenuOpenDeviceSaveDirectoryToolTip": "Открывает каталог, содержащий сохранение устройства приложения",
|
||||
"GameListContextMenuOpenBcatSaveDirectory": "Открыть каталог пользователей BCAT",
|
||||
"GameListContextMenuOpenBcatSaveDirectoryToolTip": "Открывает каталог, содержащий BCAT сохранения приложения.",
|
||||
"GameListContextMenuManageTitleUpdates": "Управление обновлениями заголовков",
|
||||
"GameListContextMenuManageTitleUpdatesToolTip": "Открывает окно управления обновлением заголовков",
|
||||
"GameListContextMenuManageDlc": "Управление DLC",
|
||||
@ -113,7 +114,7 @@
|
||||
"SettingsTabSystemEnablePptc": "Включить PPTC (Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "Включить проверку целостности FS",
|
||||
"SettingsTabSystemAudioBackend": "Аудио бэкэнд:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Dummy",
|
||||
"SettingsTabSystemAudioBackendDummy": "Муляж",
|
||||
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
|
||||
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
|
||||
"SettingsTabSystemAudioBackendSDL2": "SDL2",
|
||||
@ -152,10 +153,12 @@
|
||||
"SettingsTabLoggingEnableInfoLogs": "Включить информационные журналы",
|
||||
"SettingsTabLoggingEnableWarningLogs": "Включить журналы предупреждений",
|
||||
"SettingsTabLoggingEnableErrorLogs": "Включить журналы ошибок",
|
||||
"SettingsTabLoggingEnableTraceLogs": "Включить журнал трассировки",
|
||||
"SettingsTabLoggingEnableGuestLogs": "Включить гостевые журналы",
|
||||
"SettingsTabLoggingEnableFsAccessLogs": "Включить журналы доступа Fs",
|
||||
"SettingsTabLoggingFsGlobalAccessLogMode": "Режим журнала глобального доступа Fs:",
|
||||
"SettingsTabLoggingDeveloperOptions": "Параметры разработчика (ВНИМАНИЕ: снизит производительность)",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevel": "Graphics Backend Log Level:",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Ничего",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelError": "Ошибка",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Замедления",
|
||||
@ -166,7 +169,7 @@
|
||||
"SettingsTabInputDirectKeyboardAccess": "Прямой доступ с клавиатуры",
|
||||
"SettingsButtonSave": "Сохранить",
|
||||
"SettingsButtonClose": "Закрыть",
|
||||
"SettingsButtonOk": "OK",
|
||||
"SettingsButtonOk": "Ок",
|
||||
"SettingsButtonCancel": "Отмена",
|
||||
"SettingsButtonApply": "Применить",
|
||||
"ControllerSettingsPlayer": "Игрок",
|
||||
@ -200,7 +203,7 @@
|
||||
"ControllerSettingsButtonY": "Y",
|
||||
"ControllerSettingsButtonPlus": "+",
|
||||
"ControllerSettingsButtonMinus": "-",
|
||||
"ControllerSettingsDPad": "Directional Pad",
|
||||
"ControllerSettingsDPad": "Направляющая панель",
|
||||
"ControllerSettingsDPadUp": "Верх",
|
||||
"ControllerSettingsDPadDown": "Низ",
|
||||
"ControllerSettingsDPadLeft": "Лево",
|
||||
@ -257,7 +260,7 @@
|
||||
"UserProfilesChangeProfileImage": "Изменить изображение профиля",
|
||||
"UserProfilesAvailableUserProfiles": "Доступные профили пользователей:",
|
||||
"UserProfilesAddNewProfile": "Добавить новый профиль",
|
||||
"UserProfilesDeleteSelectedProfile": "Удалить выбранный профиль",
|
||||
"UserProfilesDelete": "Удалить",
|
||||
"UserProfilesClose": "Закрыть",
|
||||
"ProfileImageSelectionTitle": "Выбор изображения профиля",
|
||||
"ProfileImageSelectionHeader": "Выберите изображение профиля",
|
||||
@ -278,7 +281,7 @@
|
||||
"ControllerSettingsRemoveProfileToolTip": "Удалить профиль",
|
||||
"ControllerSettingsSaveProfileToolTip": "Сохранить профиль",
|
||||
"MenuBarFileToolsTakeScreenshot": "Сделать снимок экрана",
|
||||
"MenuBarFileToolsHideUi": "Спрятать пользовательский интерфейс",
|
||||
"MenuBarFileToolsHideUi": "Скрыть UI",
|
||||
"GameListContextMenuToggleFavorite": "Переключить Избранное",
|
||||
"GameListContextMenuToggleFavoriteToolTip": "Переключить любимый статус игры",
|
||||
"SettingsTabGeneralTheme": "Тема",
|
||||
@ -313,7 +316,7 @@
|
||||
"DialogUpdaterConvertFailedMessage": "Не удалось преобразовать текущую версию Ryujinx.",
|
||||
"DialogUpdaterCancelUpdateMessage": "Отмена обновления!",
|
||||
"DialogUpdaterAlreadyOnLatestVersionMessage": "Вы уже используете самую последнюю версию Ryujinx!",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "Произошла ошибка при попытке получить информацию о выпуске из Github Release. Это может быть вызвано тем, что GitHub Actions компилирует новый выпуск. Повторите попытку через несколько минут.",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "Произошла ошибка при попытке получить информацию о выпуске от GitHub Release. Это может быть вызвано, если GitHub Actions компилирует новый релиз. Попробуйте ещё раз через несколько минут.",
|
||||
"DialogUpdaterConvertFailedGithubMessage": "Не удалось преобразовать полученную версию Ryujinx из Github Release.",
|
||||
"DialogUpdaterDownloadingMessage": "Загрузка обновления...",
|
||||
"DialogUpdaterExtractionMessage": "Извлечение обновления...",
|
||||
@ -410,6 +413,8 @@
|
||||
"DlcManagerTableHeadingContainerPathLabel": "Путь к контейнеру",
|
||||
"DlcManagerTableHeadingFullPathLabel": "Полный путь",
|
||||
"DlcManagerRemoveAllButton": "Убрать все",
|
||||
"DlcManagerEnableAllButton": "Включить все",
|
||||
"DlcManagerDisableAllButton": "Отключить все",
|
||||
"MenuBarOptionsChangeLanguage": "Изменить язык",
|
||||
"CommonSort": "Сортировать",
|
||||
"CommonShowNames": "Показать названия",
|
||||
@ -455,6 +460,7 @@
|
||||
"InfoLogTooltip": "Включает печать сообщений информационного журнала",
|
||||
"WarnLogTooltip": "Включает печать сообщений журнала предупреждений",
|
||||
"ErrorLogTooltip": "Включает печать сообщений журнала ошибок",
|
||||
"TraceLogTooltip": "Выводит сообщения журнала трассировки в консоли. Не влияет на производительность.",
|
||||
"GuestLogTooltip": "Включает печать сообщений гостевого журнала",
|
||||
"FileAccessLogTooltip": "Включает печать сообщений журнала доступа к файлам",
|
||||
"FSAccessLogModeTooltip": "Включает вывод журнала доступа к FS на консоль. Возможные режимы 0-3",
|
||||
@ -479,17 +485,130 @@
|
||||
"AudioVolumeTooltip": "Изменяет громкость звука",
|
||||
"SettingsTabSystemEnableInternetAccess": "Включить гостевой доступ в Интернет",
|
||||
"EnableInternetAccessTooltip": "Включает гостевой доступ в Интернет. Если этот параметр включен, приложение будет вести себя так, как если бы эмулированная консоль Switch была подключена к Интернету. Обратите внимание, что в некоторых случаях приложения могут по-прежнему получать доступ к Интернету, даже если эта опция отключена.",
|
||||
"GameListContextMenuManageCheatToolTip" : "Управление читами",
|
||||
"GameListContextMenuManageCheat" : "Управление читами",
|
||||
"ControllerSettingsStickRange" : "Диапазон:",
|
||||
"DialogStopEmulationTitle" : "Ryujinx - Остановить эмуляцию",
|
||||
"GameListContextMenuManageCheatToolTip": "Управление читами",
|
||||
"GameListContextMenuManageCheat": "Управление читами",
|
||||
"ControllerSettingsStickRange": "Диапазон:",
|
||||
"DialogStopEmulationTitle": "Ryujinx - Остановить эмуляцию",
|
||||
"DialogStopEmulationMessage": "Вы уверены, что хотите остановить эмуляцию?",
|
||||
"SettingsTabCpu": "ЦП",
|
||||
"SettingsTabAudio": "Аудио",
|
||||
"SettingsTabNetwork": "Сеть",
|
||||
"SettingsTabNetworkConnection" : "Подключение к сети",
|
||||
"SettingsTabCpuCache" : "Кэш ЦП",
|
||||
"SettingsTabCpuMemory" : "Память ЦП",
|
||||
"SettingsTabNetworkConnection": "Подключение к сети",
|
||||
"SettingsTabCpuCache": "Кэш ЦП",
|
||||
"SettingsTabCpuMemory": "Память ЦП",
|
||||
"DialogUpdaterFlatpakNotSupportedMessage": "Пожалуйста, обновите Ryujinx через FlatHub.",
|
||||
"UpdaterDisabledWarningTitle": "Updater Disabled!",
|
||||
"GameListContextMenuOpenSdModsDirectory": "Open Atmosphere Mods Directory",
|
||||
"GameListContextMenuOpenSdModsDirectoryToolTip": "Opens the alternative SD card Atmosphere directory which contains Application's Mods. Useful for mods that are packaged for real hardware.",
|
||||
"ControllerSettingsRotate90": "Rotate 90° Clockwise",
|
||||
"IconSize": "Icon Size",
|
||||
"IconSizeTooltip": "Change the size of game icons",
|
||||
"MenuBarOptionsShowConsole": "Открыть консоль",
|
||||
"ShaderCachePurgeError": "Error purging shader cache at {0}: {1}",
|
||||
"UserErrorNoKeys": "Keys not found",
|
||||
"UserErrorNoFirmware": "Прошивка не найдена",
|
||||
"UserErrorFirmwareParsingFailed": "Firmware parsing error",
|
||||
"UserErrorApplicationNotFound": "Приложение не найдено",
|
||||
"UserErrorUnknown": "Неизвестная ошибка",
|
||||
"UserErrorUndefined": "Неопределенная ошибка",
|
||||
"UserErrorNoKeysDescription": "Ryujinx was unable to find your 'prod.keys' file",
|
||||
"UserErrorNoFirmwareDescription": "Ryujinx was unable to find any firmwares installed",
|
||||
"UserErrorFirmwareParsingFailedDescription": "Ryujinx was unable to parse the provided firmware. This is usually caused by outdated keys.",
|
||||
"UserErrorApplicationNotFoundDescription": "Ryujinx couldn't find a valid application at the given path.",
|
||||
"UserErrorUnknownDescription": "Произошла неизвестная ошибка!",
|
||||
"UserErrorUndefinedDescription": "Произошла неизвестная ошибка! Такого не должно происходить. Пожалуйста, свяжитесь с разработчиками!",
|
||||
"OpenSetupGuideMessage": "Open the Setup Guide",
|
||||
"NoUpdate": "No Update",
|
||||
"TitleUpdateVersionLabel": "Version {0} - {1}",
|
||||
"RyujinxInfo": "Ryujinx - Info",
|
||||
"RyujinxConfirm": "Ryujinx - Confirmation",
|
||||
"FileDialogAllTypes": "Все типы",
|
||||
"Never": "Никогда",
|
||||
"SwkbdMinCharacters": "Must be at least {0} characters long",
|
||||
"SwkbdMinRangeCharacters": "Must be {0}-{1} characters long",
|
||||
"SoftwareKeyboard": "Software Keyboard",
|
||||
"DialogControllerAppletMessagePlayerRange": "Application requests {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
|
||||
"DialogControllerAppletMessage": "Application requests exactly {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
|
||||
"DialogControllerAppletDockModeSet": "Docked mode set. Handheld is also invalid.\n\n",
|
||||
"UpdaterRenaming": "Переименование старых файлов...",
|
||||
"UpdaterRenameFailed": "Updater was unable to rename file: {0}",
|
||||
"UpdaterAddingFiles": "Добавление новых файлов...",
|
||||
"UpdaterExtracting": "Извлечение обновления...",
|
||||
"UpdaterDownloading": "Загрузка обновления...",
|
||||
"Game": "Игра",
|
||||
"Docked": "Docked",
|
||||
"Handheld": "Handheld",
|
||||
"ConnectionError": "Connection Error.",
|
||||
"AboutPageDeveloperListMore": "{0} and more...",
|
||||
"ApiError": "Ошибка API.",
|
||||
"LoadingHeading": "Loading {0}",
|
||||
"CompilingPPTC": "Compiling PTC",
|
||||
"CompilingShaders": "Компилируем шейдеры",
|
||||
"AllKeyboards": "Все клавиатуры",
|
||||
"OpenFileDialogTitle": "Select a supported file to open",
|
||||
"OpenFolderDialogTitle": "Select a folder with an unpacked game",
|
||||
"AllSupportedFormats": "Все поддерживаемые форматы",
|
||||
"RyujinxUpdater": "Ryujinx Updater",
|
||||
"SettingsTabHotkeys": "Keyboard Hotkeys",
|
||||
"SettingsTabHotkeysHotkeys": "Keyboard Hotkeys",
|
||||
"SettingsTabHotkeysToggleVsyncHotkey": "Toggle VSync:",
|
||||
"SettingsTabHotkeysScreenshotHotkey": "Скриншот:",
|
||||
"SettingsTabHotkeysShowUiHotkey": "Показать UI:",
|
||||
"SettingsTabHotkeysPauseHotkey": "Pause:",
|
||||
"SettingsTabHotkeysToggleMuteHotkey": "Mute:",
|
||||
"ControllerMotionTitle": "Motion Control Settings",
|
||||
"ControllerRumbleTitle": "Rumble Settings"
|
||||
"ControllerRumbleTitle": "Rumble Settings",
|
||||
"SettingsSelectThemeFileDialogTitle": "Select Theme File",
|
||||
"SettingsXamlThemeFile": "Xaml Theme File",
|
||||
"AvatarWindowTitle": "Manage Accounts - Avatar",
|
||||
"Amiibo": "Amiibo",
|
||||
"Unknown": "Unknown",
|
||||
"Usage": "Usage",
|
||||
"Writable": "Writable",
|
||||
"SelectDlcDialogTitle": "Выберите файлы DLC",
|
||||
"SelectUpdateDialogTitle": "Выберите файлы обновления",
|
||||
"UserProfileWindowTitle": "User Profiles Manager",
|
||||
"CheatWindowTitle": "Cheats Manager",
|
||||
"DlcWindowTitle": "Downloadable Content Manager",
|
||||
"UpdateWindowTitle": "Title Update Manager",
|
||||
"CheatWindowHeading": "Cheats Available for {0} [{1}]",
|
||||
"DlcWindowHeading": "{0} Downloadable Content(s) available for {1} ({2})",
|
||||
"UserProfilesEditProfile": "Edit Selected",
|
||||
"Cancel": "Cancel",
|
||||
"Save": "Сохранить",
|
||||
"Discard": "Discard",
|
||||
"UserProfilesSetProfileImage": "Set Profile Image",
|
||||
"UserProfileEmptyNameError": "Name is required",
|
||||
"UserProfileNoImageError": "Profile image must be set",
|
||||
"GameUpdateWindowHeading": "{0} Update(s) available for {1} ({2})",
|
||||
"SettingsTabHotkeysResScaleUpHotkey": "Увеличить разрешение:",
|
||||
"SettingsTabHotkeysResScaleDownHotkey": "Уменьшить разрешение:",
|
||||
"UserProfilesName": "Name:",
|
||||
"UserProfilesUserId": "User Id:",
|
||||
"SettingsTabGraphicsBackend": "Graphics Backend",
|
||||
"SettingsTabGraphicsBackendTooltip": "Graphics Backend to use",
|
||||
"SettingsEnableTextureRecompression": "Включить пережатие текстур",
|
||||
"SettingsEnableTextureRecompressionTooltip": "Сжимает некоторые текстуры для уменьшения использования видеопамяти.\n\nРекомендуется для ГП с 4 ГиБ видеопамяти и менее.\n\nЕсли не уверены, оставьте ВЫКЛ.",
|
||||
"SettingsTabGraphicsPreferredGpu": "Preferred GPU",
|
||||
"SettingsTabGraphicsPreferredGpuTooltip": "Select the graphics card that will be used with the Vulkan graphics backend.\n\nDoes not affect the GPU that OpenGL will use.\n\nSet to the GPU flagged as \"dGPU\" if unsure. If there isn't one, leave untouched.",
|
||||
"SettingsAppRequiredRestartMessage": "Ryujinx Restart Required",
|
||||
"SettingsGpuBackendRestartMessage": "Graphics Backend or GPU settings have been modified. This will require a restart to be applied",
|
||||
"SettingsGpuBackendRestartSubMessage": "Do you want to restart now?",
|
||||
"RyujinxUpdaterMessage": "Вы хотите обновить Ryujinx до последней версии?",
|
||||
"SettingsTabHotkeysVolumeUpHotkey": "Увеличить громкость:",
|
||||
"SettingsTabHotkeysVolumeDownHotkey": "Уменьшить громкость:",
|
||||
"SettingsEnableMacroHLE": "Enable Macro HLE",
|
||||
"SettingsEnableMacroHLETooltip": "High-level emulation of GPU Macro code.\n\nImproves performance, but may cause graphical glitches in some games.\n\nLeave ON if unsure.",
|
||||
"VolumeShort": "Vol",
|
||||
"UserProfilesManageSaves": "Manage Saves",
|
||||
"DeleteUserSave": "Do you want to delete user save for this game?",
|
||||
"IrreversibleActionNote": "Данное действие является необратимым.",
|
||||
"SaveManagerHeading": "Manage Saves for {0}",
|
||||
"SaveManagerTitle": "Save Manager",
|
||||
"Name": "Название",
|
||||
"Size": "Размер",
|
||||
"Search": "Search",
|
||||
"UserProfilesRecoverLostAccounts": "Recover Lost Accounts",
|
||||
"Recover": "Recover",
|
||||
"UserProfilesRecoverHeading": "Saves were found for the following accounts"
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
{
|
||||
"Language": "Türkçe",
|
||||
"MenuBarFileOpenApplet": "Applet'i Aç",
|
||||
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "Mii Editör Applet'ini Bağımsız Mod'da Aç",
|
||||
"SettingsTabInputDirectMouseAccess": "Doğrudan Mouse Erişimi",
|
||||
"SettingsTabSystemMemoryManagerMode": "Hafıza Yönetim Modu:",
|
||||
"SettingsTabSystemMemoryManagerModeSoftware": "Software",
|
||||
"SettingsTabSystemMemoryManagerModeSoftware": "Yazılım",
|
||||
"SettingsTabSystemMemoryManagerModeHost": "Host (hızlı)",
|
||||
"SettingsTabSystemMemoryManagerModeHostUnchecked": "Host Unchecked (en hızlısı, tehlikeli)",
|
||||
"MenuBarFile": "_Dosya",
|
||||
@ -13,22 +14,22 @@
|
||||
"MenuBarFileOpenLogsFolder": "Logs Klasörünü aç",
|
||||
"MenuBarFileExit": "_Çıkış",
|
||||
"MenuBarOptions": "Seçenekler",
|
||||
"MenuBarOptionsToggleFullscreen": "Tam Ekran Modu",
|
||||
"MenuBarOptionsToggleFullscreen": "Tam Ekran Modunu Aç",
|
||||
"MenuBarOptionsStartGamesInFullscreen": "Oyunları Tam Ekran Modunda Başlat",
|
||||
"MenuBarOptionsStopEmulation": "Emülasyonu Durdur",
|
||||
"MenuBarOptionsSettings": "_Seçenekler",
|
||||
"MenuBarOptionsManageUserProfiles": "_Kullanıcı Profillerini Yönet",
|
||||
"MenuBarActions": "_Eylemler",
|
||||
"MenuBarOptionsSimulateWakeUpMessage": "Uyandırma Mesajı Simüle Et",
|
||||
"MenuBarActionsScanAmiibo": "Amiibo Tarama",
|
||||
"MenuBarTools": "_Aletler",
|
||||
"MenuBarToolsInstallFirmware": "Firmware Yükle",
|
||||
"MenuBarFileToolsInstallFirmwareFromFile": "Firmware Yükle (XCI veya ZIP)",
|
||||
"MenuBarFileToolsInstallFirmwareFromDirectory": "Firmware Yükle (Dizin üzerinden)",
|
||||
"MenuBarActionsScanAmiibo": "Bir Amiibo Tara",
|
||||
"MenuBarTools": "_Araçlar",
|
||||
"MenuBarToolsInstallFirmware": "Yazılım Yükle",
|
||||
"MenuBarFileToolsInstallFirmwareFromFile": "XCI veya ZIP'ten Yazılım Yükle",
|
||||
"MenuBarFileToolsInstallFirmwareFromDirectory": "Bir Dizin Üzerinden Yazılım Yükle",
|
||||
"MenuBarHelp": "Yardım",
|
||||
"MenuBarHelpCheckForUpdates": "Güncellemeleri Denetle",
|
||||
"MenuBarHelpAbout": "Hakkında",
|
||||
"MenuSearch": "Arama...",
|
||||
"MenuSearch": "Ara...",
|
||||
"GameListHeaderFavorite": "Favori",
|
||||
"GameListHeaderIcon": "Simge",
|
||||
"GameListHeaderApplication": "Oyun Adı",
|
||||
@ -41,26 +42,26 @@
|
||||
"GameListHeaderPath": "Yol",
|
||||
"GameListContextMenuOpenUserSaveDirectory": "Kullanıcı Kayıt Dosyası Dizinini Aç",
|
||||
"GameListContextMenuOpenUserSaveDirectoryToolTip": "Uygulamanın Kullanıcı Kaydı'nın bulunduğu dizini açar",
|
||||
"GameListContextMenuOpenUserDeviceDirectory": "Kullanıcı Cihaz Dizinini Aç",
|
||||
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "Uygulamanın Kullanıcı Cihaz Kaydı'nın bulunduğu dizini açar",
|
||||
"GameListContextMenuOpenUserBcatDirectory": "Kullanıcı BCAT Dizinini Aç",
|
||||
"GameListContextMenuOpenUserBcatDirectoryToolTip": "Uygulamanın Kullanıcı BCAT Kaydı'nın bulunduğu dizini açar",
|
||||
"GameListContextMenuOpenDeviceSaveDirectory": "Kullanıcı Cihaz Dizinini Aç",
|
||||
"GameListContextMenuOpenDeviceSaveDirectoryToolTip": "Uygulamanın Kullanıcı Cihaz Kaydı'nın bulunduğu dizini açar",
|
||||
"GameListContextMenuOpenBcatSaveDirectory": "Kullanıcı BCAT Dizinini Aç",
|
||||
"GameListContextMenuOpenBcatSaveDirectoryToolTip": "Uygulamanın Kullanıcı BCAT Kaydı'nın bulunduğu dizini açar",
|
||||
"GameListContextMenuManageTitleUpdates": "Oyun Güncellemelerini Yönet",
|
||||
"GameListContextMenuManageTitleUpdatesToolTip": "Oyun güncelleme yönetim penceresini açar",
|
||||
"GameListContextMenuManageDlc": "DLC Yönet",
|
||||
"GameListContextMenuManageTitleUpdatesToolTip": "Oyun Güncelleme Yönetim Penceresini Açar",
|
||||
"GameListContextMenuManageDlc": "DLC'leri Yönet",
|
||||
"GameListContextMenuManageDlcToolTip": "DLC yönetim penceresini açar",
|
||||
"GameListContextMenuOpenModsDirectory": "Mod Dizinini Aç",
|
||||
"GameListContextMenuOpenModsDirectoryToolTip": "Uygulamanın modlarının bulunduğu dizini açar",
|
||||
"GameListContextMenuCacheManagement": "Cache Yönetimi",
|
||||
"GameListContextMenuCacheManagementPurgePptc": "PPTC Cache'ini Temizle",
|
||||
"GameListContextMenuCacheManagementPurgePptcToolTip": "Uygulamanın PPTC cache'ini siler",
|
||||
"GameListContextMenuCacheManagementPurgeShaderCache": "Shader Cache'i temizle",
|
||||
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Uygulamanın shader cache'ini siler",
|
||||
"GameListContextMenuCacheManagement": "Önbellek Yönetimi",
|
||||
"GameListContextMenuCacheManagementPurgePptc": "PPTC Yeniden Yapılandırmasını Başlat",
|
||||
"GameListContextMenuCacheManagementPurgePptcToolTip": "Oyunun bir sonraki açılışında PPTC'yi yeniden yapılandır",
|
||||
"GameListContextMenuCacheManagementPurgeShaderCache": "Shader Önbelleğini Temizle",
|
||||
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Uygulamanın shader önbelleğini temizler",
|
||||
"GameListContextMenuCacheManagementOpenPptcDirectory": "PPTC Dizinini Aç",
|
||||
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "Uygulamanın PPTC Cache'inin bulunduğu dizini açar",
|
||||
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "Shader Cache Dizinini Aç",
|
||||
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "Uygulamanın shader cache'inin bulunduğu dizini açar",
|
||||
"GameListContextMenuExtractData": "Veri Ayıkla",
|
||||
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "Uygulamanın PPTC Önbelleğinin bulunduğu dizini açar",
|
||||
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "Shader Önbelleği Dizinini Aç",
|
||||
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "Uygulamanın shader önbelleğinin bulunduğu dizini açar",
|
||||
"GameListContextMenuExtractData": "Veriyi Ayıkla",
|
||||
"GameListContextMenuExtractDataExeFS": "ExeFS",
|
||||
"GameListContextMenuExtractDataExeFSToolTip": "Uygulamanın geçerli yapılandırmasından ExeFS kısmını ayıkla (Güncellemeler dahil)",
|
||||
"GameListContextMenuExtractDataRomFS": "RomFS",
|
||||
@ -69,10 +70,10 @@
|
||||
"GameListContextMenuExtractDataLogoToolTip": "Uygulamanın geçerli yapılandırmasından Logo kısmını ayıkla (Güncellemeler dahil)",
|
||||
"StatusBarGamesLoaded": "{0}/{1} Oyun Yüklendi",
|
||||
"StatusBarSystemVersion": "Sistem Sürümü: {0}",
|
||||
"Settings": "Yapılandırma",
|
||||
"Settings": "Ayarlar",
|
||||
"SettingsTabGeneral": "Kullancı Arayüzü",
|
||||
"SettingsTabGeneralGeneral": "Genel",
|
||||
"SettingsTabGeneralEnableDiscordRichPresence": "Discord Rich Presence'i Etkinleştir",
|
||||
"SettingsTabGeneralEnableDiscordRichPresence": "Discord Zengin İçerik'i Etkinleştir",
|
||||
"SettingsTabGeneralCheckUpdatesOnLaunch": "Her Açılışta Güncellemeleri Denetle",
|
||||
"SettingsTabGeneralShowConfirmExitDialog": "\"Çıkışı Onayla\" Diyaloğunu Göster",
|
||||
"SettingsTabGeneralHideCursorOnIdle": "Hareketsizlik durumunda imleci gizle",
|
||||
@ -109,21 +110,21 @@
|
||||
"SettingsTabSystemSystemLanguageTraditionalChinese": "Geleneksel Çince",
|
||||
"SettingsTabSystemSystemTimeZone": "Sistem Saat Dilimi:",
|
||||
"SettingsTabSystemSystemTime": "Sistem Saati:",
|
||||
"SettingsTabSystemEnableVsync": "VSync'i Etkinleştir",
|
||||
"SettingsTabSystemEnablePptc": "PPTC'yi Etkinleştir (Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "FS Bütünlük Kontrollerini Etkinleştir",
|
||||
"SettingsTabSystemEnableVsync": "VSync",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (Profilli Sürekli Çeviri Önbelleği)",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "FS Bütünlük Kontrolleri",
|
||||
"SettingsTabSystemAudioBackend": "Ses Motoru:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Dummy",
|
||||
"SettingsTabSystemAudioBackendDummy": "Yapay",
|
||||
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
|
||||
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
|
||||
"SettingsTabSystemAudioBackendSDL2": "SDL2",
|
||||
"SettingsTabSystemHacks": "Hacklar",
|
||||
"SettingsTabSystemHacksNote": " (Bunlar birçok dengesizlik oluşturabilir)",
|
||||
"SettingsTabSystemExpandDramSize": "DRAM boyutunu 6GiB'a genişlet",
|
||||
"SettingsTabSystemHacks": "Hack'ler",
|
||||
"SettingsTabSystemHacksNote": " (dengesizlik oluşturabilir)",
|
||||
"SettingsTabSystemExpandDramSize": "Alternatif bellek düzeni kullan (Geliştirici)",
|
||||
"SettingsTabSystemIgnoreMissingServices": "Eksik Servisleri Görmezden Gel",
|
||||
"SettingsTabGraphics": "Grafikler",
|
||||
"SettingsTabGraphicsAPI": "Grafikler API",
|
||||
"SettingsTabGraphicsEnableShaderCache": "Shader Cache'i Etkinleştir",
|
||||
"SettingsTabGraphicsEnableShaderCache": "Shader Önbelleğini Etkinleştir",
|
||||
"SettingsTabGraphicsAnisotropicFiltering": "Eşyönsüz Doku Süzmesi:",
|
||||
"SettingsTabGraphicsAnisotropicFilteringAuto": "Otomatik",
|
||||
"SettingsTabGraphicsAnisotropicFiltering2x": "2x",
|
||||
@ -142,7 +143,7 @@
|
||||
"SettingsTabGraphicsAspectRatio16x10": "16:10",
|
||||
"SettingsTabGraphicsAspectRatio21x9": "21:9",
|
||||
"SettingsTabGraphicsAspectRatio32x9": "32:9",
|
||||
"SettingsTabGraphicsAspectRatioStretch": "Pencereye sığdırmak için genişlet",
|
||||
"SettingsTabGraphicsAspectRatioStretch": "Pencereye Sığdırmak İçin Genişlet",
|
||||
"SettingsTabGraphicsDeveloperOptions": "Geliştirici Seçenekleri",
|
||||
"SettingsTabGraphicsShaderDumpPath": "Grafik Shader Döküm Yolu:",
|
||||
"SettingsTabLogging": "Loglama",
|
||||
@ -157,13 +158,14 @@
|
||||
"SettingsTabLoggingEnableFsAccessLogs": "Fs Erişim Loglarını Etkinleştir",
|
||||
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs Evrensel Erişim Log Modu:",
|
||||
"SettingsTabLoggingDeveloperOptions": "Geliştirici Seçenekleri (UYARI: Performansı düşürecektir)",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Hiç",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevel": "Grafik Arka Uç Günlük Düzeyi",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelNone": "Hiçbiri",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelError": "Hata",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelPerformance": "Yavaşlamalar",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelAll": "Her Şey",
|
||||
"SettingsTabLoggingGraphicsBackendLogLevelAll": "Hepsi",
|
||||
"SettingsTabLoggingEnableDebugLogs": "Hata Ayıklama Loglarını Etkinleştir",
|
||||
"SettingsTabInput": "Giriş Yöntemi",
|
||||
"SettingsTabInputEnableDockedMode": "Docked Modunu Etkinleştir",
|
||||
"SettingsTabInputEnableDockedMode": "Docked Modu Etkinleştir",
|
||||
"SettingsTabInputDirectKeyboardAccess": "Doğrudan Klavye Erişimi",
|
||||
"SettingsButtonSave": "Kaydet",
|
||||
"SettingsButtonClose": "Kapat",
|
||||
@ -179,14 +181,14 @@
|
||||
"ControllerSettingsPlayer6": "Oyuncu 6",
|
||||
"ControllerSettingsPlayer7": "Oyuncu 7",
|
||||
"ControllerSettingsPlayer8": "Oyuncu 8",
|
||||
"ControllerSettingsHandheld": "Handheld",
|
||||
"ControllerSettingsHandheld": "Portatif Mod",
|
||||
"ControllerSettingsInputDevice": "Giriş Cihazı",
|
||||
"ControllerSettingsRefresh": "Yenile",
|
||||
"ControllerSettingsDeviceDisabled": "Devre Dışı",
|
||||
"ControllerSettingsControllerType": "Kontrolcü Tarzı",
|
||||
"ControllerSettingsControllerTypeHandheld": "Handheld",
|
||||
"ControllerSettingsControllerTypeProController": "Pro Controller",
|
||||
"ControllerSettingsControllerTypeJoyConPair": "JoyCon İkilisi",
|
||||
"ControllerSettingsControllerType": "Kontrolcü Tipi",
|
||||
"ControllerSettingsControllerTypeHandheld": "Portatif Mod",
|
||||
"ControllerSettingsControllerTypeProController": "Profesyonel Denetleyici",
|
||||
"ControllerSettingsControllerTypeJoyConPair": "JoyCon Çifti",
|
||||
"ControllerSettingsControllerTypeJoyConLeft": "JoyCon Sol",
|
||||
"ControllerSettingsControllerTypeJoyConRight": "JoyCon Sağ",
|
||||
"ControllerSettingsProfile": "Profil",
|
||||
@ -194,7 +196,7 @@
|
||||
"ControllerSettingsLoad": "Yükle",
|
||||
"ControllerSettingsAdd": "Ekle",
|
||||
"ControllerSettingsRemove": "Kaldır",
|
||||
"ControllerSettingsButtons": "Düğmeler",
|
||||
"ControllerSettingsButtons": "Tuşlar",
|
||||
"ControllerSettingsButtonA": "A",
|
||||
"ControllerSettingsButtonB": "B",
|
||||
"ControllerSettingsButtonX": "X",
|
||||
@ -207,29 +209,29 @@
|
||||
"ControllerSettingsDPadLeft": "Sol",
|
||||
"ControllerSettingsDPadRight": "Sağ",
|
||||
"ControllerSettingsLStick": "Sol Analog",
|
||||
"ControllerSettingsLStickButton": "Tıklama",
|
||||
"ControllerSettingsLStickButton": "Tuş",
|
||||
"ControllerSettingsLStickUp": "Yukarı",
|
||||
"ControllerSettingsLStickDown": "Aşağı",
|
||||
"ControllerSettingsLStickLeft": "Sol",
|
||||
"ControllerSettingsLStickRight": "Sağ",
|
||||
"ControllerSettingsLStickStick": "Tıklama",
|
||||
"ControllerSettingsLStickStick": "Analog",
|
||||
"ControllerSettingsLStickInvertXAxis": "X Eksenini Tersine Çevir",
|
||||
"ControllerSettingsLStickInvertYAxis": "Y Eksenini Tersine Çevir",
|
||||
"ControllerSettingsLStickDeadzone": "Ölü Bölge:",
|
||||
"ControllerSettingsRStick": "Sağ Analog",
|
||||
"ControllerSettingsRStickButton": "Tıklama",
|
||||
"ControllerSettingsRStickButton": "Tuş",
|
||||
"ControllerSettingsRStickUp": "Yukarı",
|
||||
"ControllerSettingsRStickDown": "Aşağı",
|
||||
"ControllerSettingsRStickLeft": "Sol",
|
||||
"ControllerSettingsRStickRight": "Sağ",
|
||||
"ControllerSettingsRStickStick": "Tıklama",
|
||||
"ControllerSettingsRStickStick": "Analog",
|
||||
"ControllerSettingsRStickInvertXAxis": "X Eksenini Tersine Çevir",
|
||||
"ControllerSettingsRStickInvertYAxis": "Y Eksenini Tersine Çevir",
|
||||
"ControllerSettingsRStickDeadzone": "Ölü Bölge:",
|
||||
"ControllerSettingsTriggersLeft": "Sol Tetikler",
|
||||
"ControllerSettingsTriggersRight": "Sağ Tetikler",
|
||||
"ControllerSettingsTriggersButtonsLeft": "Sol Tetik Tuşları",
|
||||
"ControllerSettingsTriggersButtonsRight": "Sağ Tetik Tuşları",
|
||||
"ControllerSettingsTriggersLeft": "Tetikler Sol",
|
||||
"ControllerSettingsTriggersRight": "Tetikler Sağ",
|
||||
"ControllerSettingsTriggersButtonsLeft": "Tetik Tuşları Sol",
|
||||
"ControllerSettingsTriggersButtonsRight": "Tetik Tuşları Sağ",
|
||||
"ControllerSettingsTriggers": "Tetikler",
|
||||
"ControllerSettingsTriggerL": "L",
|
||||
"ControllerSettingsTriggerR": "R",
|
||||
@ -239,49 +241,49 @@
|
||||
"ControllerSettingsLeftSR": "SR",
|
||||
"ControllerSettingsRightSL": "SL",
|
||||
"ControllerSettingsRightSR": "SR",
|
||||
"ControllerSettingsExtraButtonsLeft": "Sol Tuşlar",
|
||||
"ControllerSettingsExtraButtonsRight": "Sağ Tuşlar",
|
||||
"ControllerSettingsExtraButtonsLeft": "Tuşlar Sol",
|
||||
"ControllerSettingsExtraButtonsRight": "Tuşlar Sağ",
|
||||
"ControllerSettingsMisc": "Diğer",
|
||||
"ControllerSettingsTriggerThreshold": "Tetik Eşiği:",
|
||||
"ControllerSettingsMotion": "Hareket",
|
||||
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "CemuHook Uyumlu Hareket",
|
||||
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "CemuHook uyumlu hareket kullan",
|
||||
"ControllerSettingsMotionControllerSlot": "Kontrolcü Yuvası:",
|
||||
"ControllerSettingsMotionMirrorInput": "Girişi Aynala",
|
||||
"ControllerSettingsMotionRightJoyConSlot": "Sağ JoyCon Yuvası:",
|
||||
"ControllerSettingsMotionServerHost": "Sunucu Host'u:",
|
||||
"ControllerSettingsMotionServerHost": "Sunucu Sahibi:",
|
||||
"ControllerSettingsMotionGyroSensitivity": "Gyro Hassasiyeti:",
|
||||
"ControllerSettingsMotionGyroDeadzone": "Gyro Ölü Bölgesi:",
|
||||
"ControllerSettingsSave": "Kaydet",
|
||||
"ControllerSettingsClose": "Kapat",
|
||||
"UserProfilesSelectedUserProfile": "Aktif Kullanıcı Profili:",
|
||||
"UserProfilesSelectedUserProfile": "Seçili Kullanıcı Profili:",
|
||||
"UserProfilesSaveProfileName": "Profil İsmini Kaydet",
|
||||
"UserProfilesChangeProfileImage": "Profil Resmini Değiştir",
|
||||
"UserProfilesAvailableUserProfiles": "Mevcut Kullanıcı Profilleri:",
|
||||
"UserProfilesAddNewProfile": "Yeni Profil Ekle",
|
||||
"UserProfilesDeleteSelectedProfile": "Seçili Profili Sil",
|
||||
"UserProfilesDelete": "Sil",
|
||||
"UserProfilesClose": "Kapat",
|
||||
"ProfileImageSelectionTitle": "Profile Resmi Seçimi",
|
||||
"ProfileImageSelectionTitle": "Profil Resmi Seçimi",
|
||||
"ProfileImageSelectionHeader": "Profil Resmi Seç",
|
||||
"ProfileImageSelectionNote": "Özel bir profil resmi içeri aktarabilir veya sistem avatarlarından birini seçebilirsiniz",
|
||||
"ProfileImageSelectionImportImage": "Resim İçeri Aktar",
|
||||
"ProfileImageSelectionSelectAvatar": "Sistem Avatarı Seç",
|
||||
"ProfileImageSelectionSelectAvatar": "Yazılım Avatarı Seç",
|
||||
"InputDialogTitle": "Giriş Yöntemi Diyaloğu",
|
||||
"InputDialogOk": "OK",
|
||||
"InputDialogOk": "Tamam",
|
||||
"InputDialogCancel": "İptal",
|
||||
"InputDialogAddNewProfileTitle": "Profil İsmini Seç",
|
||||
"InputDialogAddNewProfileHeader": "Profil İsmi girin",
|
||||
"InputDialogAddNewProfileHeader": "Lütfen Bir Profil İsmi Girin",
|
||||
"InputDialogAddNewProfileSubtext": "(Maksimum Uzunluk: {0})",
|
||||
"AvatarChoose": "Seç",
|
||||
"AvatarSetBackgroundColor": "Arka Plan Rengi Ayarla",
|
||||
"AvatarClose": "Kapat",
|
||||
"ControllerSettingsLoadProfileToolTip": "Profil Yükle",
|
||||
"ControllerSettingsAddProfileToolTip": "Profil Ekle",
|
||||
"ControllerSettingsRemoveProfileToolTip": "Profil Kaldır",
|
||||
"ControllerSettingsSaveProfileToolTip": "Profil Kaydet",
|
||||
"ControllerSettingsRemoveProfileToolTip": "Profili Kaldır",
|
||||
"ControllerSettingsSaveProfileToolTip": "Profili Kaydet",
|
||||
"MenuBarFileToolsTakeScreenshot": "Ekran Görüntüsü Al",
|
||||
"MenuBarFileToolsHideUi": "Arayüzü Gizle",
|
||||
"GameListContextMenuToggleFavorite": "Favori Ayarla",
|
||||
"GameListContextMenuToggleFavoriteToolTip": "Oyunun favorilere eklenmesini veya kaldırmasını sağlar",
|
||||
"GameListContextMenuToggleFavoriteToolTip": "Oyunu Favorilere Ekle/Çıkar",
|
||||
"SettingsTabGeneralTheme": "Tema",
|
||||
"SettingsTabGeneralThemeCustomTheme": "Özel Tema Yolu",
|
||||
"SettingsTabGeneralThemeBaseStyle": "Temel Stil",
|
||||
@ -291,7 +293,7 @@
|
||||
"ButtonBrowse": "Göz At",
|
||||
"ControllerSettingsConfigureGeneral": "Ayarla",
|
||||
"ControllerSettingsRumble": "Titreşim",
|
||||
"ControllerSettingsRumbleStrongMultiplier": "Güçlü Titreşim Seviyesi",
|
||||
"ControllerSettingsRumbleStrongMultiplier": "Güçlü Titreşim Çoklayıcı",
|
||||
"ControllerSettingsRumbleWeakMultiplier": "Zayıf Titreşim Seviyesi",
|
||||
"DialogMessageSaveNotAvailableMessage": "{0} [{1:x16}] için kayıt verisi bulunamadı",
|
||||
"DialogMessageSaveNotAvailableCreateSaveMessage": "Bu oyun için kayıt verisi oluşturmak ister misiniz?",
|
||||
@ -303,24 +305,24 @@
|
||||
"DialogErrorMessage": "Ryujinx bir hata ile karşılaştı",
|
||||
"DialogExitMessage": "Ryujinx'i kapatmak istediğinizden emin misiniz?",
|
||||
"DialogExitSubMessage": "Kaydedilmeyen bütün veriler kaybedilecek!",
|
||||
"DialogMessageCreateSaveErrorMessage": "Belirtilen kayıt verisi oluşturulurken hata: {0}",
|
||||
"DialogMessageCreateSaveErrorMessage": "Belirtilen kayıt verisi oluşturulurken bir hata oluştu: {0}",
|
||||
"DialogMessageFindSaveErrorMessage": "Belirtilen kayıt verisi bulunmaya çalışırken hata: {0}",
|
||||
"FolderDialogExtractTitle": "İçine ayıklanacak klasörü seç",
|
||||
"DialogNcaExtractionMessage": "{1} den {0} kısmı ayıklanıyor...",
|
||||
"DialogNcaExtractionTitle": "Ryujinx - NCA Kısmı Ayıklayıcısı",
|
||||
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "Ayıklama hatası. Ana NCA seçilen dosyada bulunamadı.",
|
||||
"DialogNcaExtractionCheckLogErrorMessage": "Ayıklama hatası. Ek bilgi için log dosyasını okuyun.",
|
||||
"DialogNcaExtractionCheckLogErrorMessage": "Ayıklama hatası. Ek bilgi için kayıt dosyasını okuyun.",
|
||||
"DialogNcaExtractionSuccessMessage": "Ayıklama başarıyla tamamlandı.",
|
||||
"DialogUpdaterConvertFailedMessage": "Güncel Ryujinx sürümü dönüştürülemedi.",
|
||||
"DialogUpdaterCancelUpdateMessage": "Güncelleme iptal ediliyor!",
|
||||
"DialogUpdaterAlreadyOnLatestVersionMessage": "Zaten Ryujinx'in en güncel sürümünü kullanıyorsunuz!",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "Github Release'den yayınlanma bilgisi alınırken hata oluştu. Bu durum yeni bir sürümün Github Actions tarafından derleniyor olmasından kaynaklanıyor olabilir. Birkaç dakika sonra tekrar deneyin.",
|
||||
"DialogUpdaterFailedToGetVersionMessage": "GitHub tarafından sürüm bilgileri alınırken bir hata oluştu. Eğer yeni sürüm için hazırlıklar yapılıyorsa bu hatayı almanız olasıdır. Lütfen birkaç dakika sonra tekrar deneyiniz.",
|
||||
"DialogUpdaterConvertFailedGithubMessage": "Github Release'den alınan Ryujinx sürümü dönüştürülemedi.",
|
||||
"DialogUpdaterDownloadingMessage": "Güncelleme indiriliyor...",
|
||||
"DialogUpdaterExtractionMessage": "Güncelleme ayıklanıyor...",
|
||||
"DialogUpdaterRenamingMessage": "Güncelleme yeniden adlandırılıyor...",
|
||||
"DialogUpdaterAddingFilesMessage": "Yeni güncelleme ekleniyor...",
|
||||
"DialogUpdaterCompleteMessage": "Güncelleme tamamlandı!",
|
||||
"DialogUpdaterDownloadingMessage": "Güncelleme İndiriliyor...",
|
||||
"DialogUpdaterExtractionMessage": "Güncelleme Ayıklanıyor...",
|
||||
"DialogUpdaterRenamingMessage": "Güncelleme Yeniden Adlandırılıyor...",
|
||||
"DialogUpdaterAddingFilesMessage": "Yeni Güncelleme Ekleniyor...",
|
||||
"DialogUpdaterCompleteMessage": "Güncelleme Tamamlandı!",
|
||||
"DialogUpdaterRestartMessage": "Ryujinx'i şimdi yeniden başlatmak istiyor musunuz?",
|
||||
"DialogUpdaterArchNotSupportedMessage": "Sistem mimariniz desteklenmemektedir!",
|
||||
"DialogUpdaterArchNotSupportedSubMessage": "(Sadece x64 sistemleri desteklenmektedir!)",
|
||||
@ -331,10 +333,10 @@
|
||||
"DialogRestartRequiredMessage": "Yeniden Başlatma Gerekli",
|
||||
"DialogThemeRestartMessage": "Tema kaydedildi. Temayı uygulamak için yeniden başlatma gerekiyor.",
|
||||
"DialogThemeRestartSubMessage": "Yeniden başlatmak ister misiniz",
|
||||
"DialogFirmwareInstallEmbeddedMessage": "Bu oyunun içine gömülü olan firmware'i yüklemek ister misiniz? (Firmware {0})",
|
||||
"DialogFirmwareInstallEmbeddedSuccessMessage": "Yüklü firmware bulunamadı ancak Ryujinx sağlanan oyundan {0} firmware sürümünü yükledi.\nRyujinx şimdi başlatılacak.",
|
||||
"DialogFirmwareNoFirmwareInstalledMessage": "Firmware Yüklü Değil",
|
||||
"DialogFirmwareInstalledMessage": "Firmware {0} yüklendi",
|
||||
"DialogFirmwareInstallEmbeddedMessage": "Bu oyunun içine gömülü olan yazılımı yüklemek ister misiniz? (Firmware {0})",
|
||||
"DialogFirmwareInstallEmbeddedSuccessMessage": "Yüklü firmware bulunamadı ancak Ryujinx sağlanan oyundan {0} firmware sürümünü yükledi.\nEmülatör şimdi başlatılacak.",
|
||||
"DialogFirmwareNoFirmwareInstalledMessage": "Yazılım Yüklü Değil",
|
||||
"DialogFirmwareInstalledMessage": "Yazılım {0} yüklendi",
|
||||
"DialogOpenSettingsWindowLabel": "Seçenekler Penceresini Aç",
|
||||
"DialogControllerAppletTitle": "Kontrolcü Applet'i",
|
||||
"DialogMessageDialogErrorExceptionMessage": "Mesaj diyaloğu gösterilirken hata: {0}",
|
||||
@ -407,10 +409,12 @@
|
||||
"AmiiboOptionsShowAllLabel": "Tüm Amiibo'ları Göster",
|
||||
"AmiiboOptionsUsRandomTagLabel": "Hack: Rastgele bir Uuid kullan",
|
||||
"DlcManagerTableHeadingEnabledLabel": "Etkin",
|
||||
"DlcManagerTableHeadingTitleIdLabel": "Title ID",
|
||||
"DlcManagerTableHeadingTitleIdLabel": "Başlık ID",
|
||||
"DlcManagerTableHeadingContainerPathLabel": "Container Yol",
|
||||
"DlcManagerTableHeadingFullPathLabel": "Tam Yol",
|
||||
"DlcManagerRemoveAllButton": "Tümünü kaldır",
|
||||
"DlcManagerEnableAllButton": "Tümünü Aktif Et",
|
||||
"DlcManagerDisableAllButton": "Tümünü Devre Dışı Bırak",
|
||||
"MenuBarOptionsChangeLanguage": "Dili Değiştir",
|
||||
"CommonSort": "Sırala",
|
||||
"CommonShowNames": "İsimleri Göster",
|
||||
@ -445,7 +449,7 @@
|
||||
"IgnoreMissingServicesTooltip": "Henüz programlanmamış Horizon işletim sistemi servislerini görmezden gelir. Bu seçenek belirli oyunların açılırken çökmesinin önüne geçmeye yardımcı olabilir.\n\nEmin değilseniz devre dışı bırakın.",
|
||||
"GraphicsBackendThreadingTooltip": "Grafik arka uç komutlarını ikinci bir iş parçacığında işletir.\n\nKendi multithreading desteği olmayan sürücülerde shader derlemeyi hızlandırıp performansı artırır. Multithreading desteği olan sürücülerde çok az daha iyi performans sağlar.\n\nEmin değilseniz Otomatik seçeneğine ayarlayın.",
|
||||
"GalThreadingTooltip": "Grafik arka uç komutlarını ikinci bir iş parçacığında işletir.\n\nKendi multithreading desteği olmayan sürücülerde shader derlemeyi hızlandırıp performansı artırır. Multithreading desteği olan sürücülerde çok az daha iyi performans sağlar.\n\nEmin değilseniz Otomatik seçeneğine ayarlayın.",
|
||||
"ShaderCacheToggleTooltip": "Saves a disk shader cache which reduces stuttering in subsequent runs.\n\nLeave ON if unsure.",
|
||||
"ShaderCacheToggleTooltip": "Sonraki çalışmalarda takılmaları engelleyen bir gölgelendirici disk önbelleğine kaydeder.",
|
||||
"ResolutionScaleTooltip": "Uygulanabilir grafik hedeflerine uygulanan çözünürlük ölçeği",
|
||||
"ResolutionScaleEntryTooltip": "Küsüratlı çözünürlük ölçeği, 1.5 gibi. Küsüratlı ölçekler hata oluşturmaya ve çökmeye daha yatkındır.",
|
||||
"AnisotropyTooltip": "Eşyönsüz doku süzmesi seviyesi (Oyun tarafından istenen değeri kullanmak için Otomatik seçeneğine ayarlayın)",
|
||||
@ -486,16 +490,16 @@
|
||||
"ControllerSettingsStickRange": "Menzil:",
|
||||
"DialogStopEmulationTitle": "Ryujinx - Emülasyonu Durdur",
|
||||
"DialogStopEmulationMessage": "Emülasyonu durdurmak istediğinizden emin misiniz?",
|
||||
"SettingsTabCpu": "CPU",
|
||||
"SettingsTabCpu": "İşlemci",
|
||||
"SettingsTabAudio": "Ses",
|
||||
"SettingsTabNetwork": "Ağ",
|
||||
"SettingsTabNetworkConnection": "Ağ Bağlantısı",
|
||||
"SettingsTabCpuCache": "CPU Cache",
|
||||
"SettingsTabCpuCache": "İşlemci Belleği",
|
||||
"SettingsTabCpuMemory": "CPU Hafızası",
|
||||
"DialogUpdaterFlatpakNotSupportedMessage": "Lütfen Ryujinx'i FlatHub aracılığıyla güncelleyin.",
|
||||
"UpdaterDisabledWarningTitle": "Güncelleyici Devre Dışı!",
|
||||
"GameListContextMenuOpenSdModsDirectory": "Atmosphere Mod Dizini",
|
||||
"GameListContextMenuOpenSdModsDirectoryToolTip": "Opens the alternative SD card Atmosphere directory which contains Application's Mods. Useful for mods that are packaged for real hardware.",
|
||||
"GameListContextMenuOpenSdModsDirectoryToolTip": "Uygulama Modlarını içeren alternatif SD kart Atmosfer dizinini açar. Gerçek donanım için paketlenmiş modlar için kullanışlıdır.",
|
||||
"ControllerSettingsRotate90": "Saat yönünde 90° Döndür",
|
||||
"IconSize": "Ikon Boyutu",
|
||||
"IconSizeTooltip": "Oyun ikonlarının boyutunu değiştirmeyi sağlar",
|
||||
@ -532,8 +536,8 @@
|
||||
"UpdaterExtracting": "Güncelleme Ayrıştırılıyor...",
|
||||
"UpdaterDownloading": "Güncelleme İndiriliyor...",
|
||||
"Game": "Oyun",
|
||||
"Docked": "Docked",
|
||||
"Handheld": "Handheld",
|
||||
"Docked": "Yerleştirildi",
|
||||
"Handheld": "El tipi",
|
||||
"ConnectionError": "Bağlantı Hatası.",
|
||||
"AboutPageDeveloperListMore": "{0} ve daha fazla...",
|
||||
"ApiError": "API Hatası.",
|
||||
@ -575,8 +579,36 @@
|
||||
"Discard": "Iskarta",
|
||||
"UserProfilesSetProfileImage": "Profil Resmi Ayarla",
|
||||
"UserProfileEmptyNameError": "İsim gerekli",
|
||||
"UserProfileNoImageError": "Profil resmi ayarlanmalıdır",
|
||||
"UserProfileNoImageError": "Profil resmi ayarlanmalıdır",
|
||||
"GameUpdateWindowHeading": "{0} için güncellemeler mevcut [{1}]",
|
||||
"SettingsTabHotkeysResScaleUpHotkey": "Çözünürlüğü artır:",
|
||||
"SettingsTabHotkeysResScaleDownHotkey": "Çözünürlüğü azalt:"
|
||||
"SettingsTabHotkeysResScaleDownHotkey": "Çözünürlüğü azalt:",
|
||||
"UserProfilesName": "İsim:",
|
||||
"UserProfilesUserId": "Kullanıcı Adı:",
|
||||
"SettingsTabGraphicsBackend": "Grafik Arka Ucu",
|
||||
"SettingsTabGraphicsBackendTooltip": "Kullanılacak Grafik Arka Uç",
|
||||
"SettingsEnableTextureRecompression": "Yeniden Doku Sıkıştırılmasını Aktif Et",
|
||||
"SettingsEnableTextureRecompressionTooltip": "4GB VRAM'in Altında Sistemler için önerilir.\n\nEmin değilseniz kapalı bırakın",
|
||||
"SettingsTabGraphicsPreferredGpu": "Kullanılan GPU",
|
||||
"SettingsTabGraphicsPreferredGpuTooltip": "Vulkan Grafik Arka Ucu ile kullanılacak Ekran Kartını Seçin.\n\nOpenGL'nin kullanacağı GPU'yu etkilemez.\n\n Emin değilseniz \"dGPU\" olarak işaretlenmiş GPU'ya ayarlayın. Eğer yoksa, dokunmadan bırakın.\n",
|
||||
"SettingsAppRequiredRestartMessage": "Ryujinx'i Yeniden Başlatma Gerekli",
|
||||
"SettingsGpuBackendRestartMessage": "Grafik Motoru ya da GPU ayarları değiştirildi. Bu işlemin uygulanması için yeniden başlatma gerekli.",
|
||||
"SettingsGpuBackendRestartSubMessage": "Şimdi yeniden başlatmak istiyor musunuz?",
|
||||
"RyujinxUpdaterMessage": "Ryujinx'i en son sürüme güncellemek ister misiniz?",
|
||||
"SettingsTabHotkeysVolumeUpHotkey": "Sesi Arttır:",
|
||||
"SettingsTabHotkeysVolumeDownHotkey": "Sesi Azalt:",
|
||||
"SettingsEnableMacroHLE": "Macro HLE'yi Aktifleştir",
|
||||
"SettingsEnableMacroHLETooltip": "GPU Macro kodunun yüksek seviye emülasyonu.\n\nPerformansı arttırır, ama bazı oyunlarda grafik hatalarına yol açabilir.\n\nEmin değilseniz AÇIK bırakın.",
|
||||
"VolumeShort": "Ses",
|
||||
"UserProfilesManageSaves": "Kayıtları Yönet",
|
||||
"DeleteUserSave": "Bu oyun için kullanıcı kaydını silmek istiyor musunuz?",
|
||||
"IrreversibleActionNote": "Bu eylem geri alınamaz.",
|
||||
"SaveManagerHeading": "{0} için Kayıt Dosyalarını Yönet",
|
||||
"SaveManagerTitle": "Kayıt Yöneticisi",
|
||||
"Name": "İsim",
|
||||
"Size": "Boyut",
|
||||
"Search": "Ara",
|
||||
"UserProfilesRecoverLostAccounts": "Kayıp Hesapları Kurtar",
|
||||
"Recover": "Kurtar",
|
||||
"UserProfilesRecoverHeading": "Aşağıdaki hesaplar için kayıtlar bulundu"
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user