Compare commits

..

54 Commits

Author SHA1 Message Date
41790aa743 Avalonia - Misc changes to UX (#3643)
* Change navbar from compact to default and force text overflow globally

* Fix settings window

* Fix right stick control alignment

* Initialize value and add logging for SDL IDs

* Fix alignment of setting text and improve borders

* Clean up padding and size of buttons on controller settings

* Fix right side trigger alignment and correct styling

* Revert axaml alignment

* Fix alignment of volume widget

* Fix timezone autocompletebox dropdown height

* MainWindow: Line up volume status bar item

* Remove margins and add padding to volume widget

* Make volume text localizable.

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

* use embedded window

* fix race condition on opengl Windows

* fix glx issues on prime nvidia

* fix mouse support win32

* clean up

* addressed review

* addressed review

* fix warnings

* fix sotware keyboard dialog

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

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

* remove double semi

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

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

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

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

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

* Ptc.InternalVersion = 3665

* Addressed PR feedback.

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

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

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

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

* A64: Remove catch-all Hint instruction

* T16: Handle unallocated hint instructions

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

* T32: Fill out other Hint instructions

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

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

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

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

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

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

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

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

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

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

* Remove unused variable

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

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

* PPTC version bump

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

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

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

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

May also affect LOD scaling in The Witcher 3.

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

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

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

* Remove public from interface

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

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

* Typo

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

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

* PPTC version

* Fix VQADD/VQSUB

* Improve MRC/MCR handling and exception messages

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

* Update CacheByRange

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

* An AMD exclusive

* Reword

* Change rules - stride conversion when attrs misalign

* Fix stupid mistake

* Fix background pipeline compile

* Improve a few things.

* Fix some feedback

* Address Feedback

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

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

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

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

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

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

* Ptc.InternalVersion = 3665

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

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

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

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

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

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

* Bsd: Return proper error code if RemoteEndPoint is null

* Remove whitespace from empty line

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

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

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

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

* Fix softlock when toggling vsync

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

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

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

* Extra formatting

* Lower case ASTC dimensions

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

* Implement TreeDictionary using IntrusiveRedBlackTree

* Implement IntervalTree using IntrusiveRedBlackTree

* Implement IntervalTree (on Ryujinx.Memory) using IntrusiveRedBlackTree

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

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

* Update de_DE.json

* Update de_DE.json

* Update de_DE.json

* Update de_DE.json

* Update de_DE.json

* Update de_DE.json

* Another one

* Update de_DE.json

* addressed reviews

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

* welp

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

* Update de_DE.json

* Update de_DE.json

quick update with the latest changes

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

* Update de_DE.json

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

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

* Update zh_CN.json

* Update zh_CN.json

* Update zh_CN.json

* Delete zh_CN.json

* fix crash

* Update zh_CN.json

* Update zh_CN.json

* Update zh_CN.json

* Update zh_CN.json

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

* Update MainWindow.axaml

* Create pl_PL.json

* Update pl_PL.json

* Update pl_PL.json

* Update pl_PL.json

* Update pl_PL.json

* PPTC wording changes

adding PPTC changes

Co-authored-by: Clara <moonbowjelly@gmail.com>
2022-08-26 19:24:59 +02:00
238 changed files with 8220 additions and 7493 deletions

View File

@ -1,6 +1,6 @@
--- ---
name: Bug Report name: Bug Report
about: Something doesn't work correctly in Ryujinx. about: Something doesn't work correctly in Ryujinx. Note that game-specific issues should be instead posted on the Game Compatibility List at https://github.com/Ryujinx/Ryujinx-Games-List, unless it is a provable regression.
#assignees: #assignees:
--- ---

View File

@ -1,4 +1,4 @@
using ARMeilleure.Diagnostics.EventSources; using ARMeilleure.Diagnostics;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -218,7 +218,7 @@ namespace ARMeilleure.Common
_pages.Add(page); _pages.Add(page);
AddressTableEventSource.Log.Allocated(size, leaf); TranslatorEventSource.Log.AddressTableAllocated(size, leaf);
return page; return page;
} }

View File

@ -251,6 +251,13 @@ namespace ARMeilleure.Decoders
return false; return false;
} }
// Compare and branch instructions are always conditional.
if (opCode.Instruction.Name == InstName.Cbz ||
opCode.Instruction.Name == InstName.Cbnz)
{
return false;
}
// Note: On ARM32, most instructions have conditional execution, // Note: On ARM32, most instructions have conditional execution,
// so there's no "Always" (unconditional) branch like on ARM64. // so there's no "Always" (unconditional) branch like on ARM64.
// We need to check if the condition is "Always" instead. // We need to check if the condition is "Always" instead.

View File

@ -151,7 +151,7 @@ namespace ARMeilleure.Decoders
public static bool VectorArgumentsInvalid(bool q, params int[] args) public static bool VectorArgumentsInvalid(bool q, params int[] args)
{ {
if (q) if (q)
{ {
for (int i = 0; i < args.Length; i++) for (int i = 0; i < args.Length; i++)
{ {

View File

@ -7,5 +7,8 @@
int Msb { get; } int Msb { get; }
int Lsb { get; } int Lsb { get; }
int SourceMask => (int)(0xFFFFFFFF >> (31 - Msb));
int DestMask => SourceMask & (int)(0xFFFFFFFF << Lsb);
} }
} }

View File

@ -0,0 +1,7 @@
namespace ARMeilleure.Decoders
{
interface IOpCode32AluImm16 : IOpCode32Alu
{
int Immediate { get; }
}
}

View File

@ -0,0 +1,11 @@
namespace ARMeilleure.Decoders
{
interface IOpCode32AluMla : IOpCode32AluReg
{
int Ra { get; }
bool NHigh { get; }
bool MHigh { get; }
bool R { get; }
}
}

View File

@ -0,0 +1,13 @@
namespace ARMeilleure.Decoders
{
interface IOpCode32AluUmull : IOpCode32, IOpCode32HasSetFlags
{
int RdLo { get; }
int RdHi { get; }
int Rn { get; }
int Rm { get; }
bool NHigh { get; }
bool MHigh { get; }
}
}

View File

@ -3,6 +3,7 @@ namespace ARMeilleure.Decoders
interface IOpCode32Mem : IOpCode32 interface IOpCode32Mem : IOpCode32
{ {
int Rt { get; } int Rt { get; }
int Rt2 => Rt | 1;
int Rn { get; } int Rn { get; }
bool WBack { get; } bool WBack { get; }

View File

@ -13,16 +13,13 @@ namespace ARMeilleure.Decoders
Cond = (Condition)((uint)opCode >> 28); Cond = (Condition)((uint)opCode >> 28);
} }
public bool IsThumb() public bool IsThumb { get; protected init; } = false;
{
return this is OpCodeT16 || this is OpCodeT32;
}
public uint GetPc() public uint GetPc()
{ {
// Due to backwards compatibility and legacy behavior of ARMv4 CPUs pipeline, // Due to backwards compatibility and legacy behavior of ARMv4 CPUs pipeline,
// the PC actually points 2 instructions ahead. // the PC actually points 2 instructions ahead.
if (IsThumb()) if (IsThumb)
{ {
// PC is ahead by 4 in thumb mode whether or not the current instruction // PC is ahead by 4 in thumb mode whether or not the current instruction
// is 16 or 32 bit. // is 16 or 32 bit.

View File

@ -6,12 +6,8 @@
public int Rn { get; } public int Rn { get; }
public int Msb { get; } public int Msb { get; }
public int Lsb { get; } public int Lsb { get; }
public int SourceMask => (int)(0xFFFFFFFF >> (31 - Msb));
public int DestMask => SourceMask & (int)(0xFFFFFFFF << Lsb);
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluBf(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluBf(inst, address, opCode);
public OpCode32AluBf(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32AluBf(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)

View File

@ -1,6 +1,6 @@
namespace ARMeilleure.Decoders namespace ARMeilleure.Decoders
{ {
class OpCode32AluImm16 : OpCode32Alu class OpCode32AluImm16 : OpCode32Alu, IOpCode32AluImm16
{ {
public int Immediate { get; } public int Immediate { get; }

View File

@ -1,6 +1,6 @@
namespace ARMeilleure.Decoders namespace ARMeilleure.Decoders
{ {
class OpCode32AluMla : OpCode32, IOpCode32AluReg class OpCode32AluMla : OpCode32, IOpCode32AluMla
{ {
public int Rn { get; } public int Rn { get; }
public int Rm { get; } public int Rm { get; }

View File

@ -1,6 +1,6 @@
namespace ARMeilleure.Decoders namespace ARMeilleure.Decoders
{ {
class OpCode32AluUmull : OpCode32, IOpCode32HasSetFlags class OpCode32AluUmull : OpCode32, IOpCode32AluUmull
{ {
public int RdLo { get; } public int RdLo { get; }
public int RdHi { get; } public int RdHi { get; }
@ -11,7 +11,6 @@
public bool MHigh { get; } public bool MHigh { get; }
public bool? SetFlags { get; } public bool? SetFlags { get; }
public DataOp DataOp { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluUmull(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluUmull(inst, address, opCode);
@ -26,7 +25,6 @@
MHigh = ((opCode >> 6) & 0x1) == 1; MHigh = ((opCode >> 6) & 0x1) == 1;
SetFlags = ((opCode >> 20) & 0x1) != 0; SetFlags = ((opCode >> 20) & 0x1) != 0;
DataOp = DataOp.Arithmetic;
} }
} }
} }

View File

@ -7,14 +7,15 @@
public bool F { get; protected set; } public bool F { get; protected set; }
public bool U { get; } public bool U { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32Simd(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32Simd(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32Simd(inst, address, opCode, true);
public OpCode32Simd(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32Simd(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
Size = (opCode >> 20) & 0x3; Size = (opCode >> 20) & 0x3;
Q = ((opCode >> 6) & 0x1) != 0; Q = ((opCode >> 6) & 0x1) != 0;
F = ((opCode >> 10) & 0x1) != 0; F = ((opCode >> 10) & 0x1) != 0;
U = ((opCode >> 24) & 0x1) != 0; U = ((opCode >> (isThumb ? 28 : 24)) & 0x1) != 0;
Opc = (opCode >> 7) & 0x3; Opc = (opCode >> 7) & 0x3;
RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64; RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;

View File

@ -47,6 +47,9 @@ namespace ARMeilleure.Decoders
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
public OpCode32SimdBase(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { } protected OpCode32SimdBase(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{
IsThumb = isThumb;
}
} }
} }

View File

@ -5,9 +5,10 @@
/// </summary> /// </summary>
class OpCode32SimdBinary : OpCode32SimdReg class OpCode32SimdBinary : OpCode32SimdReg
{ {
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdBinary(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdBinary(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdBinary(inst, address, opCode, true);
public OpCode32SimdBinary(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdBinary(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
Size = 3; Size = 3;

View File

@ -2,9 +2,10 @@
{ {
class OpCode32SimdCmpZ : OpCode32Simd class OpCode32SimdCmpZ : OpCode32Simd
{ {
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCmpZ(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCmpZ(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCmpZ(inst, address, opCode, true);
public OpCode32SimdCmpZ(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdCmpZ(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
Size = (opCode >> 18) & 0x3; Size = (opCode >> 18) & 0x3;

View File

@ -2,9 +2,10 @@
{ {
class OpCode32SimdCvtFI : OpCode32SimdS class OpCode32SimdCvtFI : OpCode32SimdS
{ {
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtFI(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtFI(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtFI(inst, address, opCode, true);
public OpCode32SimdCvtFI(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdCvtFI(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
Opc = (opCode >> 7) & 0x1; Opc = (opCode >> 7) & 0x1;

View File

@ -4,9 +4,10 @@
{ {
public int Index { get; } public int Index { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupElem(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupElem(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupElem(inst, address, opCode, true);
public OpCode32SimdDupElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdDupElem(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
var opc = (opCode >> 16) & 0xf; var opc = (opCode >> 16) & 0xf;

View File

@ -7,10 +7,13 @@
public int Rt { get; } public int Rt { get; }
public bool Q { get; } public bool Q { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupGP(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupGP(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupGP(inst, address, opCode, true);
public OpCode32SimdDupGP(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdDupGP(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{ {
IsThumb = isThumb;
Size = 2 - (((opCode >> 21) & 0x2) | ((opCode >> 5) & 0x1)); // B:E - 0 for 32, 16 then 8. Size = 2 - (((opCode >> 21) & 0x2) | ((opCode >> 5) & 0x1)); // B:E - 0 for 32, 16 then 8.
if (Size == -1) if (Size == -1)
{ {

View File

@ -4,9 +4,10 @@
{ {
public int Immediate { get; } public int Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdExt(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdExt(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdExt(inst, address, opCode, true);
public OpCode32SimdExt(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdExt(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
Immediate = (opCode >> 8) & 0xf; Immediate = (opCode >> 8) & 0xf;
Size = 0; Size = 0;

View File

@ -6,9 +6,10 @@
public long Immediate { get; } public long Immediate { get; }
public int Elems => GetBytesCount() >> Size; public int Elems => GetBytesCount() >> Size;
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm(inst, address, opCode, true);
public OpCode32SimdImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdImm(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
Vd = (opCode >> 12) & 0xf; Vd = (opCode >> 12) & 0xf;
Vd |= (opCode >> 18) & 0x10; Vd |= (opCode >> 18) & 0x10;
@ -22,7 +23,7 @@
imm = ((uint)opCode >> 0) & 0xf; imm = ((uint)opCode >> 0) & 0xf;
imm |= ((uint)opCode >> 12) & 0x70; imm |= ((uint)opCode >> 12) & 0x70;
imm |= ((uint)opCode >> 17) & 0x80; imm |= ((uint)opCode >> (isThumb ? 21 : 17)) & 0x80;
(Immediate, Size) = OpCodeSimdHelper.GetSimdImmediateAndSize(cMode, op, imm); (Immediate, Size) = OpCodeSimdHelper.GetSimdImmediateAndSize(cMode, op, imm);

View File

@ -7,10 +7,13 @@
public int Size { get; } public int Size { get; }
public int Elems { get; } public int Elems { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm44(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm44(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm44(inst, address, opCode, true);
public OpCode32SimdImm44(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdImm44(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{ {
IsThumb = isThumb;
Size = (opCode >> 8) & 0x3; Size = (opCode >> 8) & 0x3;
bool single = Size != 3; bool single = Size != 3;

View File

@ -4,9 +4,10 @@
{ {
public bool U { get; } public bool U { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdLong(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdLong(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdLong(inst, address, opCode, true);
public OpCode32SimdLong(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdLong(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
int imm3h = (opCode >> 19) & 0x7; int imm3h = (opCode >> 19) & 0x7;
@ -18,7 +19,7 @@
case 4: Size = 2; break; case 4: Size = 2; break;
} }
U = ((opCode >> 24) & 0x1) != 0; U = ((opCode >> (isThumb ? 28 : 24)) & 0x1) != 0;
RegisterSize = RegisterSize.Simd64; RegisterSize = RegisterSize.Simd64;

View File

@ -8,10 +8,13 @@
public bool Add { get; } public bool Add { get; }
public int Immediate { get; } public int Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemImm(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemImm(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemImm(inst, address, opCode, true);
public OpCode32SimdMemImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdMemImm(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{ {
IsThumb = isThumb;
Immediate = opCode & 0xff; Immediate = opCode & 0xff;
Rn = (opCode >> 16) & 0xf; Rn = (opCode >> 16) & 0xf;

View File

@ -12,10 +12,13 @@
public bool DoubleWidth { get; } public bool DoubleWidth { get; }
public bool Add { get; } public bool Add { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemMult(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemMult(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemMult(inst, address, opCode, true);
public OpCode32SimdMemMult(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdMemMult(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{ {
IsThumb = isThumb;
Rn = (opCode >> 16) & 0xf; Rn = (opCode >> 16) & 0xf;
bool isLoad = (opCode & (1 << 20)) != 0; bool isLoad = (opCode & (1 << 20)) != 0;

View File

@ -1,11 +1,10 @@
using ARMeilleure.State; using ARMeilleure.State;
using System;
namespace ARMeilleure.Decoders namespace ARMeilleure.Decoders
{ {
class OpCode32SimdMemPair : OpCode32, IOpCode32Simd class OpCode32SimdMemPair : OpCode32, IOpCode32Simd
{ {
private static int[] RegsMap = private static int[] _regsMap =
{ {
1, 1, 4, 2, 1, 1, 4, 2,
1, 1, 3, 1, 1, 1, 3, 1,
@ -24,10 +23,13 @@ namespace ARMeilleure.Decoders
public int Regs { get; } public int Regs { get; }
public int Increment { get; } public int Increment { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemPair(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemPair(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemPair(inst, address, opCode, true);
public OpCode32SimdMemPair(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdMemPair(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{ {
IsThumb = isThumb;
Vd = (opCode >> 12) & 0xf; Vd = (opCode >> 12) & 0xf;
Vd |= (opCode >> 18) & 0x10; Vd |= (opCode >> 18) & 0x10;
@ -40,9 +42,9 @@ namespace ARMeilleure.Decoders
WBack = Rm != RegisterAlias.Aarch32Pc; WBack = Rm != RegisterAlias.Aarch32Pc;
RegisterIndex = Rm != RegisterAlias.Aarch32Pc && Rm != RegisterAlias.Aarch32Sp; RegisterIndex = Rm != RegisterAlias.Aarch32Pc && Rm != RegisterAlias.Aarch32Sp;
Regs = RegsMap[(opCode >> 8) & 0xf]; Regs = _regsMap[(opCode >> 8) & 0xf];
Increment = Math.Min(Regs, ((opCode >> 8) & 0x1) + 1); Increment = ((opCode >> 8) & 0x1) + 1;
} }
} }
} }

View File

@ -15,10 +15,13 @@ namespace ARMeilleure.Decoders
public bool Replicate { get; } public bool Replicate { get; }
public int Increment { get; } public int Increment { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemSingle(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemSingle(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemSingle(inst, address, opCode, true);
public OpCode32SimdMemSingle(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdMemSingle(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{ {
IsThumb = isThumb;
Vd = (opCode >> 12) & 0xf; Vd = (opCode >> 12) & 0xf;
Vd |= (opCode >> 18) & 0x10; Vd |= (opCode >> 18) & 0x10;

View File

@ -11,10 +11,13 @@
public int Opc1 { get; } public int Opc1 { get; }
public int Opc2 { get; } public int Opc2 { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGp(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGp(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGp(inst, address, opCode, true);
public OpCode32SimdMovGp(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdMovGp(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{ {
IsThumb = isThumb;
// Which one is used is instruction dependant. // Which one is used is instruction dependant.
Op = (opCode >> 20) & 0x1; Op = (opCode >> 20) & 0x1;

View File

@ -9,10 +9,13 @@
public int Rt2 { get; } public int Rt2 { get; }
public int Op { get; } public int Op { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpDouble(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpDouble(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpDouble(inst, address, opCode, true);
public OpCode32SimdMovGpDouble(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdMovGpDouble(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{ {
IsThumb = isThumb;
// Which one is used is instruction dependant. // Which one is used is instruction dependant.
Op = (opCode >> 20) & 0x1; Op = (opCode >> 20) & 0x1;

View File

@ -11,10 +11,13 @@
public int Index { get; } public int Index { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpElem(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpElem(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpElem(inst, address, opCode, true);
public OpCode32SimdMovGpElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdMovGpElem(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{ {
IsThumb = isThumb;
Op = (opCode >> 20) & 0x1; Op = (opCode >> 20) & 0x1;
U = ((opCode >> 23) & 1) != 0; U = ((opCode >> 23) & 1) != 0;

View File

@ -0,0 +1,13 @@
namespace ARMeilleure.Decoders
{
class OpCode32SimdMovn : OpCode32Simd
{
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovn(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovn(inst, address, opCode, true);
public OpCode32SimdMovn(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Size = (opCode >> 18) & 0x3;
}
}
}

View File

@ -8,9 +8,10 @@
public int In => GetQuadwordSubindex(Vn) << (3 - Size); public int In => GetQuadwordSubindex(Vn) << (3 - Size);
public int Fn => GetQuadwordSubindex(Vn) << (1 - (Size & 1)); public int Fn => GetQuadwordSubindex(Vn) << (1 - (Size & 1));
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdReg(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdReg(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdReg(inst, address, opCode, true);
public OpCode32SimdReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdReg(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
Vn = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf); Vn = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf);

View File

@ -2,11 +2,12 @@
{ {
class OpCode32SimdRegElem : OpCode32SimdReg class OpCode32SimdRegElem : OpCode32SimdReg
{ {
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElem(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElem(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElem(inst, address, opCode, true);
public OpCode32SimdRegElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdRegElem(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
Q = ((opCode >> 24) & 0x1) != 0; Q = ((opCode >> (isThumb ? 28 : 24)) & 0x1) != 0;
F = ((opCode >> 8) & 0x1) != 0; F = ((opCode >> 8) & 0x1) != 0;
Size = (opCode >> 20) & 0x3; Size = (opCode >> 20) & 0x3;

View File

@ -2,9 +2,10 @@
{ {
class OpCode32SimdRegElemLong : OpCode32SimdRegElem class OpCode32SimdRegElemLong : OpCode32SimdRegElem
{ {
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElemLong(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElemLong(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElemLong(inst, address, opCode, true);
public OpCode32SimdRegElemLong(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdRegElemLong(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
Q = false; Q = false;
F = false; F = false;

View File

@ -4,9 +4,10 @@
{ {
public bool Polynomial { get; } public bool Polynomial { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegLong(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegLong(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegLong(inst, address, opCode, true);
public OpCode32SimdRegLong(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdRegLong(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
Q = false; Q = false;
RegisterSize = RegisterSize.Simd64; RegisterSize = RegisterSize.Simd64;

View File

@ -4,9 +4,10 @@
{ {
public int Vn { get; } public int Vn { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegS(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegS(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegS(inst, address, opCode, true);
public OpCode32SimdRegS(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdRegS(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
bool single = Size != 3; bool single = Size != 3;
if (single) if (single)

View File

@ -2,9 +2,10 @@
{ {
class OpCode32SimdRegWide : OpCode32SimdReg class OpCode32SimdRegWide : OpCode32SimdReg
{ {
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegWide(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegWide(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegWide(inst, address, opCode, true);
public OpCode32SimdRegWide(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdRegWide(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
Q = false; Q = false;
RegisterSize = RegisterSize.Simd64; RegisterSize = RegisterSize.Simd64;

View File

@ -2,9 +2,10 @@
{ {
class OpCode32SimdRev : OpCode32SimdCmpZ class OpCode32SimdRev : OpCode32SimdCmpZ
{ {
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRev(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRev(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRev(inst, address, opCode, true);
public OpCode32SimdRev(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdRev(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
if (Opc + Size >= 3) if (Opc + Size >= 3)
{ {

View File

@ -8,10 +8,13 @@
public int Opc2 { get; } // opc2 or RM (opc2<1:0>) [Vcvt, Vrint]. public int Opc2 { get; } // opc2 or RM (opc2<1:0>) [Vcvt, Vrint].
public int Size { get; protected set; } public int Size { get; protected set; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdS(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdS(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdS(inst, address, opCode, true);
public OpCode32SimdS(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdS(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{ {
IsThumb = isThumb;
Opc = (opCode >> 15) & 0x3; Opc = (opCode >> 15) & 0x3;
Opc2 = (opCode >> 16) & 0x7; Opc2 = (opCode >> 16) & 0x7;

View File

@ -4,9 +4,10 @@
{ {
public OpCode32SimdSelMode Cc { get; } public OpCode32SimdSelMode Cc { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSel(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSel(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSel(inst, address, opCode, true);
public OpCode32SimdSel(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdSel(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
Cc = (OpCode32SimdSelMode)((opCode >> 20) & 3); Cc = (OpCode32SimdSelMode)((opCode >> 20) & 3);
} }

View File

@ -4,9 +4,10 @@
{ {
public int Shift { get; } public int Shift { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImm(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImm(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImm(inst, address, opCode, true);
public OpCode32SimdShImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdShImm(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
int imm6 = (opCode >> 16) & 0x3f; int imm6 = (opCode >> 16) & 0x3f;
int limm6 = ((opCode >> 1) & 0x40) | imm6; int limm6 = ((opCode >> 1) & 0x40) | imm6;

View File

@ -4,9 +4,10 @@
{ {
public int Shift { get; } public int Shift { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmLong(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmLong(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmLong(inst, address, opCode, true);
public OpCode32SimdShImmLong(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdShImmLong(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
Q = false; Q = false;
RegisterSize = RegisterSize.Simd64; RegisterSize = RegisterSize.Simd64;

View File

@ -2,8 +2,9 @@
{ {
class OpCode32SimdShImmNarrow : OpCode32SimdShImm class OpCode32SimdShImmNarrow : OpCode32SimdShImm
{ {
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmNarrow(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmNarrow(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmNarrow(inst, address, opCode, true);
public OpCode32SimdShImmNarrow(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { } public OpCode32SimdShImmNarrow(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb) { }
} }
} }

View File

@ -5,10 +5,13 @@
public int Rt { get; } public int Rt { get; }
public int Sreg { get; } public int Sreg { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSpecial(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSpecial(inst, address, opCode, false);
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSpecial(inst, address, opCode, true);
public OpCode32SimdSpecial(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdSpecial(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
{ {
IsThumb = isThumb;
Rt = (opCode >> 12) & 0xf; Rt = (opCode >> 12) & 0xf;
Sreg = (opCode >> 16) & 0xf; Sreg = (opCode >> 16) & 0xf;
} }

View File

@ -2,9 +2,10 @@
{ {
class OpCode32SimdSqrte : OpCode32Simd class OpCode32SimdSqrte : OpCode32Simd
{ {
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSqrte(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSqrte(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSqrte(inst, address, opCode, true);
public OpCode32SimdSqrte(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdSqrte(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
Size = (opCode >> 18) & 0x1; Size = (opCode >> 18) & 0x1;
F = ((opCode >> 8) & 0x1) != 0; F = ((opCode >> 8) & 0x1) != 0;

View File

@ -4,9 +4,10 @@
{ {
public int Length { get; } public int Length { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdTbl(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdTbl(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdTbl(inst, address, opCode, true);
public OpCode32SimdTbl(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdTbl(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{ {
Length = (opCode >> 8) & 3; Length = (opCode >> 8) & 3;
Size = 0; Size = 0;

View File

@ -8,6 +8,7 @@ namespace ARMeilleure.Decoders
{ {
Cond = Condition.Al; Cond = Condition.Al;
IsThumb = true;
OpCodeSizeInBytes = 2; OpCodeSizeInBytes = 2;
} }
} }

View File

@ -4,14 +4,13 @@ namespace ARMeilleure.Decoders
{ {
public int Rd { get; } public int Rd { get; }
public bool Add => true;
public int Immediate { get; } public int Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16Adr(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16Adr(inst, address, opCode);
public OpCodeT16Adr(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeT16Adr(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Rd = (opCode >> 8) & 7; Rd = (opCode >> 8) & 7;
int imm = (opCode & 0xff) << 2; int imm = (opCode & 0xff) << 2;
Immediate = (int)(GetPc() & 0xfffffffc) + imm; Immediate = (int)(GetPc() & 0xfffffffc) + imm;

View File

@ -8,6 +8,7 @@
{ {
Cond = Condition.Al; Cond = Condition.Al;
IsThumb = true;
OpCodeSizeInBytes = 4; OpCodeSizeInBytes = 4;
} }
} }

View File

@ -0,0 +1,22 @@
namespace ARMeilleure.Decoders
{
class OpCodeT32AluBf : OpCodeT32, IOpCode32AluBf
{
public int Rd { get; }
public int Rn { get; }
public int Msb { get; }
public int Lsb { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluBf(inst, address, opCode);
public OpCodeT32AluBf(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rd = (opCode >> 8) & 0xf;
Rn = (opCode >> 16) & 0xf;
Msb = (opCode >> 0) & 0x1f;
Lsb = ((opCode >> 6) & 0x3) | ((opCode >> 10) & 0x1c);
}
}
}

View File

@ -0,0 +1,16 @@
namespace ARMeilleure.Decoders
{
class OpCodeT32AluImm12 : OpCodeT32Alu, IOpCode32AluImm
{
public int Immediate { get; }
public bool IsRotated => false;
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluImm12(inst, address, opCode);
public OpCodeT32AluImm12(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Immediate = (opCode & 0xff) | ((opCode >> 4) & 0x700) | ((opCode >> 15) & 0x800);
}
}
}

View File

@ -0,0 +1,29 @@
namespace ARMeilleure.Decoders
{
class OpCodeT32AluMla : OpCodeT32, IOpCode32AluMla
{
public int Rn { get; }
public int Rm { get; }
public int Ra { get; }
public int Rd { get; }
public bool NHigh { get; }
public bool MHigh { get; }
public bool R { get; }
public bool? SetFlags => false;
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluMla(inst, address, opCode);
public OpCodeT32AluMla(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rm = (opCode >> 0) & 0xf;
Rd = (opCode >> 8) & 0xf;
Ra = (opCode >> 12) & 0xf;
Rn = (opCode >> 16) & 0xf;
R = (opCode & (1 << 4)) != 0;
MHigh = ((opCode >> 4) & 0x1) == 1;
NHigh = ((opCode >> 5) & 0x1) == 1;
}
}
}

View File

@ -0,0 +1,14 @@
namespace ARMeilleure.Decoders
{
class OpCodeT32AluReg : OpCodeT32Alu, IOpCode32AluReg
{
public int Rm { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluReg(inst, address, opCode);
public OpCodeT32AluReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rm = (opCode >> 0) & 0xf;
}
}
}

View File

@ -0,0 +1,28 @@
namespace ARMeilleure.Decoders
{
class OpCodeT32AluUmull : OpCodeT32, IOpCode32AluUmull
{
public int RdLo { get; }
public int RdHi { get; }
public int Rn { get; }
public int Rm { get; }
public bool NHigh { get; }
public bool MHigh { get; }
public bool? SetFlags => false;
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluUmull(inst, address, opCode);
public OpCodeT32AluUmull(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rm = (opCode >> 0) & 0xf;
RdHi = (opCode >> 8) & 0xf;
RdLo = (opCode >> 12) & 0xf;
Rn = (opCode >> 16) & 0xf;
MHigh = ((opCode >> 4) & 0x1) == 1;
NHigh = ((opCode >> 5) & 0x1) == 1;
}
}
}

View File

@ -0,0 +1,18 @@
using ARMeilleure.State;
namespace ARMeilleure.Decoders
{
class OpCodeT32AluUx : OpCodeT32AluReg, IOpCode32AluUx
{
public int Rotate { get; }
public int RotateBits => Rotate * 8;
public bool Add => Rn != RegisterAlias.Aarch32Pc;
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluUx(inst, address, opCode);
public OpCodeT32AluUx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rotate = (opCode >> 4) & 0x3;
}
}
}

View File

@ -27,7 +27,7 @@ namespace ARMeilleure.Decoders
int i2 = j2 ^ s ^ 1; int i2 = j2 ^ s ^ 1;
int imm32 = imm11 | (imm10 << 11) | (i2 << 21) | (i1 << 22) | (s << 23); int imm32 = imm11 | (imm10 << 11) | (i2 << 21) | (i1 << 22) | (s << 23);
imm32 = (imm32 << 9) >> 8; imm32 = (imm32 << 8) >> 7;
Immediate = pc + imm32; Immediate = pc + imm32;
} }

View File

@ -23,7 +23,7 @@ namespace ARMeilleure.Decoders
Add = ((opCode >> 23) & 1) != 0; Add = ((opCode >> 23) & 1) != 0;
WBack = ((opCode >> 21) & 1) != 0; WBack = ((opCode >> 21) & 1) != 0;
Immediate = opCode & 0xff; Immediate = (opCode & 0xff) << 2;
IsLoad = ((opCode >> 20) & 1) != 0; IsLoad = ((opCode >> 20) & 1) != 0;
} }

View File

@ -4,6 +4,7 @@ namespace ARMeilleure.Decoders
{ {
public int Rd => 0; public int Rd => 0;
public int Rt { get; } public int Rt { get; }
public int Rt2 { get; }
public int Rn { get; } public int Rn { get; }
public bool WBack => false; public bool WBack => false;
@ -17,6 +18,7 @@ namespace ARMeilleure.Decoders
public OpCodeT32MemLdEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeT32MemLdEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Rt2 = (opCode >> 8) & 0xf;
Rt = (opCode >> 12) & 0xf; Rt = (opCode >> 12) & 0xf;
Rn = (opCode >> 16) & 0xf; Rn = (opCode >> 16) & 0xf;
} }

View File

@ -4,6 +4,7 @@ namespace ARMeilleure.Decoders
{ {
public int Rd { get; } public int Rd { get; }
public int Rt { get; } public int Rt { get; }
public int Rt2 { get; }
public int Rn { get; } public int Rn { get; }
public bool WBack => false; public bool WBack => false;
@ -18,6 +19,7 @@ namespace ARMeilleure.Decoders
public OpCodeT32MemStEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeT32MemStEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Rd = (opCode >> 0) & 0xf; Rd = (opCode >> 0) & 0xf;
Rt2 = (opCode >> 8) & 0xf;
Rt = (opCode >> 12) & 0xf; Rt = (opCode >> 12) & 0xf;
Rn = (opCode >> 16) & 0xf; Rn = (opCode >> 16) & 0xf;
} }

View File

@ -0,0 +1,16 @@
namespace ARMeilleure.Decoders
{
class OpCodeT32MovImm16 : OpCodeT32Alu, IOpCode32AluImm16
{
public int Immediate { get; }
public bool IsRotated => false;
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32MovImm16(inst, address, opCode);
public OpCodeT32MovImm16(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Immediate = (opCode & 0xff) | ((opCode >> 4) & 0x700) | ((opCode >> 15) & 0x800) | ((opCode >> 4) & 0xf000);
}
}
}

View File

@ -0,0 +1,19 @@
namespace ARMeilleure.Decoders
{
class OpCodeT32ShiftReg : OpCodeT32Alu, IOpCode32AluRsReg
{
public int Rm => Rn;
public int Rs { get; }
public ShiftType ShiftType { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32ShiftReg(inst, address, opCode);
public OpCodeT32ShiftReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rs = (opCode >> 0) & 0xf;
ShiftType = (ShiftType)((opCode >> 21) & 3);
}
}
}

View File

@ -0,0 +1,16 @@
namespace ARMeilleure.Decoders
{
class OpCodeT32Tb : OpCodeT32, IOpCode32BReg
{
public int Rm { get; }
public int Rn { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32Tb(inst, address, opCode);
public OpCodeT32Tb(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rm = (opCode >> 0) & 0xf;
Rn = (opCode >> 16) & 0xf;
}
}
}

View File

@ -93,6 +93,7 @@ namespace ARMeilleure.Decoders
SetA64("00011010110xxxxx010101xxxxxxxxxx", InstName.Crc32ch, InstEmit.Crc32ch, OpCodeAluBinary.Create); SetA64("00011010110xxxxx010101xxxxxxxxxx", InstName.Crc32ch, InstEmit.Crc32ch, OpCodeAluBinary.Create);
SetA64("00011010110xxxxx010110xxxxxxxxxx", InstName.Crc32cw, InstEmit.Crc32cw, OpCodeAluBinary.Create); SetA64("00011010110xxxxx010110xxxxxxxxxx", InstName.Crc32cw, InstEmit.Crc32cw, OpCodeAluBinary.Create);
SetA64("10011010110xxxxx010111xxxxxxxxxx", InstName.Crc32cx, InstEmit.Crc32cx, OpCodeAluBinary.Create); SetA64("10011010110xxxxx010111xxxxxxxxxx", InstName.Crc32cx, InstEmit.Crc32cx, OpCodeAluBinary.Create);
SetA64("11010101000000110010001010011111", InstName.Csdb, InstEmit.Csdb, OpCodeSystem.Create);
SetA64("x0011010100xxxxxxxxx00xxxxxxxxxx", InstName.Csel, InstEmit.Csel, OpCodeCsel.Create); SetA64("x0011010100xxxxxxxxx00xxxxxxxxxx", InstName.Csel, InstEmit.Csel, OpCodeCsel.Create);
SetA64("x0011010100xxxxxxxxx01xxxxxxxxxx", InstName.Csinc, InstEmit.Csinc, OpCodeCsel.Create); SetA64("x0011010100xxxxxxxxx01xxxxxxxxxx", InstName.Csinc, InstEmit.Csinc, OpCodeCsel.Create);
SetA64("x1011010100xxxxxxxxx00xxxxxxxxxx", InstName.Csinv, InstEmit.Csinv, OpCodeCsel.Create); SetA64("x1011010100xxxxxxxxx00xxxxxxxxxx", InstName.Csinv, InstEmit.Csinv, OpCodeCsel.Create);
@ -107,7 +108,6 @@ namespace ARMeilleure.Decoders
SetA64("11001010xx0xxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit.Eor, OpCodeAluRs.Create); SetA64("11001010xx0xxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit.Eor, OpCodeAluRs.Create);
SetA64("00010011100xxxxx0xxxxxxxxxxxxxxx", InstName.Extr, InstEmit.Extr, OpCodeAluRs.Create); SetA64("00010011100xxxxx0xxxxxxxxxxxxxxx", InstName.Extr, InstEmit.Extr, OpCodeAluRs.Create);
SetA64("10010011110xxxxxxxxxxxxxxxxxxxxx", InstName.Extr, InstEmit.Extr, OpCodeAluRs.Create); SetA64("10010011110xxxxxxxxxxxxxxxxxxxxx", InstName.Extr, InstEmit.Extr, OpCodeAluRs.Create);
SetA64("11010101000000110010xxxxxxx11111", InstName.Hint, InstEmit.Hint, OpCodeSystem.Create);
SetA64("11010101000000110011xxxx11011111", InstName.Isb, InstEmit.Isb, OpCodeSystem.Create); SetA64("11010101000000110011xxxx11011111", InstName.Isb, InstEmit.Isb, OpCodeSystem.Create);
SetA64("xx001000110xxxxx1xxxxxxxxxxxxxxx", InstName.Ldar, InstEmit.Ldar, OpCodeMemEx.Create); SetA64("xx001000110xxxxx1xxxxxxxxxxxxxxx", InstName.Ldar, InstEmit.Ldar, OpCodeMemEx.Create);
SetA64("1x001000011xxxxx1xxxxxxxxxxxxxxx", InstName.Ldaxp, InstEmit.Ldaxp, OpCodeMemEx.Create); SetA64("1x001000011xxxxx1xxxxxxxxxxxxxxx", InstName.Ldaxp, InstEmit.Ldaxp, OpCodeMemEx.Create);
@ -159,6 +159,8 @@ namespace ARMeilleure.Decoders
SetA64("00010011000xxxxx0xxxxxxxxxxxxxxx", InstName.Sbfm, InstEmit.Sbfm, OpCodeBfm.Create); SetA64("00010011000xxxxx0xxxxxxxxxxxxxxx", InstName.Sbfm, InstEmit.Sbfm, OpCodeBfm.Create);
SetA64("1001001101xxxxxxxxxxxxxxxxxxxxxx", InstName.Sbfm, InstEmit.Sbfm, OpCodeBfm.Create); SetA64("1001001101xxxxxxxxxxxxxxxxxxxxxx", InstName.Sbfm, InstEmit.Sbfm, OpCodeBfm.Create);
SetA64("x0011010110xxxxx000011xxxxxxxxxx", InstName.Sdiv, InstEmit.Sdiv, OpCodeAluBinary.Create); SetA64("x0011010110xxxxx000011xxxxxxxxxx", InstName.Sdiv, InstEmit.Sdiv, OpCodeAluBinary.Create);
SetA64("11010101000000110010000010011111", InstName.Sev, InstEmit.Nop, OpCodeSystem.Create);
SetA64("11010101000000110010000010111111", InstName.Sevl, InstEmit.Nop, OpCodeSystem.Create);
SetA64("10011011001xxxxx0xxxxxxxxxxxxxxx", InstName.Smaddl, InstEmit.Smaddl, OpCodeMul.Create); SetA64("10011011001xxxxx0xxxxxxxxxxxxxxx", InstName.Smaddl, InstEmit.Smaddl, OpCodeMul.Create);
SetA64("10011011001xxxxx1xxxxxxxxxxxxxxx", InstName.Smsubl, InstEmit.Smsubl, OpCodeMul.Create); SetA64("10011011001xxxxx1xxxxxxxxxxxxxxx", InstName.Smsubl, InstEmit.Smsubl, OpCodeMul.Create);
SetA64("10011011010xxxxx0xxxxxxxxxxxxxxx", InstName.Smulh, InstEmit.Smulh, OpCodeMul.Create); SetA64("10011011010xxxxx0xxxxxxxxxxxxxxx", InstName.Smulh, InstEmit.Smulh, OpCodeMul.Create);
@ -191,6 +193,9 @@ namespace ARMeilleure.Decoders
SetA64("10011011101xxxxx0xxxxxxxxxxxxxxx", InstName.Umaddl, InstEmit.Umaddl, OpCodeMul.Create); SetA64("10011011101xxxxx0xxxxxxxxxxxxxxx", InstName.Umaddl, InstEmit.Umaddl, OpCodeMul.Create);
SetA64("10011011101xxxxx1xxxxxxxxxxxxxxx", InstName.Umsubl, InstEmit.Umsubl, OpCodeMul.Create); SetA64("10011011101xxxxx1xxxxxxxxxxxxxxx", InstName.Umsubl, InstEmit.Umsubl, OpCodeMul.Create);
SetA64("10011011110xxxxx0xxxxxxxxxxxxxxx", InstName.Umulh, InstEmit.Umulh, OpCodeMul.Create); SetA64("10011011110xxxxx0xxxxxxxxxxxxxxx", InstName.Umulh, InstEmit.Umulh, OpCodeMul.Create);
SetA64("11010101000000110010000001011111", InstName.Wfe, InstEmit.Nop, OpCodeSystem.Create);
SetA64("11010101000000110010000001111111", InstName.Wfi, InstEmit.Nop, OpCodeSystem.Create);
SetA64("11010101000000110010000000111111", InstName.Yield, InstEmit.Nop, OpCodeSystem.Create);
// FP & SIMD // FP & SIMD
SetA64("0101111011100000101110xxxxxxxxxx", InstName.Abs_S, InstEmit.Abs_S, OpCodeSimd.Create); SetA64("0101111011100000101110xxxxxxxxxx", InstName.Abs_S, InstEmit.Abs_S, OpCodeSimd.Create);
@ -669,6 +674,17 @@ namespace ARMeilleure.Decoders
SetA32("<<<<0010001xxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCode32AluImm.Create); SetA32("<<<<0010001xxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCode32AluImm.Create);
SetA32("<<<<0000001xxxxxxxxxxxxxxxx0xxxx", InstName.Eor, InstEmit32.Eor, OpCode32AluRsImm.Create); SetA32("<<<<0000001xxxxxxxxxxxxxxxx0xxxx", InstName.Eor, InstEmit32.Eor, OpCode32AluRsImm.Create);
SetA32("<<<<0000001xxxxxxxxxxxxx0xx1xxxx", InstName.Eor, InstEmit32.Eor, OpCode32AluRsReg.Create); SetA32("<<<<0000001xxxxxxxxxxxxx0xx1xxxx", InstName.Eor, InstEmit32.Eor, OpCode32AluRsReg.Create);
SetA32("<<<<0011001000001111000000010000", InstName.Esb, InstEmit32.Nop, OpCode32.Create); // Error Synchronization Barrier (FEAT_RAS)
SetA32("<<<<001100100000111100000000011x", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
SetA32("<<<<0011001000001111000000001xxx", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
SetA32("<<<<0011001000001111000000010001", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
SetA32("<<<<0011001000001111000000010011", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
SetA32("<<<<0011001000001111000000010101", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
SetA32("<<<<001100100000111100000001011x", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
SetA32("<<<<0011001000001111000000011xxx", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
SetA32("<<<<00110010000011110000001xxxxx", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
SetA32("<<<<0011001000001111000001xxxxxx", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
SetA32("<<<<001100100000111100001xxxxxxx", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
SetA32("1111010101111111111100000110xxxx", InstName.Isb, InstEmit32.Nop, OpCode32.Create); SetA32("1111010101111111111100000110xxxx", InstName.Isb, InstEmit32.Nop, OpCode32.Create);
SetA32("<<<<00011001xxxxxxxx110010011111", InstName.Lda, InstEmit32.Lda, OpCode32MemLdEx.Create); SetA32("<<<<00011001xxxxxxxx110010011111", InstName.Lda, InstEmit32.Lda, OpCode32MemLdEx.Create);
SetA32("<<<<00011101xxxxxxxx110010011111", InstName.Ldab, InstEmit32.Ldab, OpCode32MemLdEx.Create); SetA32("<<<<00011101xxxxxxxx110010011111", InstName.Ldab, InstEmit32.Ldab, OpCode32MemLdEx.Create);
@ -727,11 +743,15 @@ namespace ARMeilleure.Decoders
SetA32("<<<<0010111xxxxxxxxxxxxxxxxxxxxx", InstName.Rsc, InstEmit32.Rsc, OpCode32AluImm.Create); SetA32("<<<<0010111xxxxxxxxxxxxxxxxxxxxx", InstName.Rsc, InstEmit32.Rsc, OpCode32AluImm.Create);
SetA32("<<<<0000111xxxxxxxxxxxxxxxx0xxxx", InstName.Rsc, InstEmit32.Rsc, OpCode32AluRsImm.Create); SetA32("<<<<0000111xxxxxxxxxxxxxxxx0xxxx", InstName.Rsc, InstEmit32.Rsc, OpCode32AluRsImm.Create);
SetA32("<<<<0000111xxxxxxxxxxxxx0xx1xxxx", InstName.Rsc, InstEmit32.Rsc, OpCode32AluRsReg.Create); SetA32("<<<<0000111xxxxxxxxxxxxx0xx1xxxx", InstName.Rsc, InstEmit32.Rsc, OpCode32AluRsReg.Create);
SetA32("<<<<01100001xxxxxxxx11111001xxxx", InstName.Sadd8, InstEmit32.Sadd8, OpCode32AluReg.Create);
SetA32("<<<<0010110xxxxxxxxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluImm.Create); SetA32("<<<<0010110xxxxxxxxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluImm.Create);
SetA32("<<<<0000110xxxxxxxxxxxxxxxx0xxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluRsImm.Create); SetA32("<<<<0000110xxxxxxxxxxxxxxxx0xxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluRsImm.Create);
SetA32("<<<<0000110xxxxxxxxxxxxx0xx1xxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluRsReg.Create); SetA32("<<<<0000110xxxxxxxxxxxxx0xx1xxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluRsReg.Create);
SetA32("<<<<0111101xxxxxxxxxxxxxx101xxxx", InstName.Sbfx, InstEmit32.Sbfx, OpCode32AluBf.Create); SetA32("<<<<0111101xxxxxxxxxxxxxx101xxxx", InstName.Sbfx, InstEmit32.Sbfx, OpCode32AluBf.Create);
SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, OpCode32AluMla.Create); SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, OpCode32AluMla.Create);
SetA32("<<<<01101000xxxxxxxx11111011xxxx", InstName.Sel, InstEmit32.Sel, OpCode32AluReg.Create);
SetA32("<<<<0011001000001111000000000100", InstName.Sev, InstEmit32.Nop, OpCode32.Create);
SetA32("<<<<0011001000001111000000000101", InstName.Sevl, InstEmit32.Nop, OpCode32.Create);
SetA32("<<<<01100011xxxxxxxx11111001xxxx", InstName.Shadd8, InstEmit32.Shadd8, OpCode32AluReg.Create); SetA32("<<<<01100011xxxxxxxx11111001xxxx", InstName.Shadd8, InstEmit32.Shadd8, OpCode32AluReg.Create);
SetA32("<<<<01100011xxxxxxxx11111111xxxx", InstName.Shsub8, InstEmit32.Shsub8, OpCode32AluReg.Create); SetA32("<<<<01100011xxxxxxxx11111111xxxx", InstName.Shsub8, InstEmit32.Shsub8, OpCode32AluReg.Create);
SetA32("<<<<00010000xxxxxxxxxxxx1xx0xxxx", InstName.Smla__, InstEmit32.Smla__, OpCode32AluMla.Create); SetA32("<<<<00010000xxxxxxxxxxxx1xx0xxxx", InstName.Smla__, InstEmit32.Smla__, OpCode32AluMla.Create);
@ -745,6 +765,7 @@ namespace ARMeilleure.Decoders
SetA32("<<<<00010010xxxx0000xxxx1x10xxxx", InstName.Smulw_, InstEmit32.Smulw_, OpCode32AluMla.Create); SetA32("<<<<00010010xxxx0000xxxx1x10xxxx", InstName.Smulw_, InstEmit32.Smulw_, OpCode32AluMla.Create);
SetA32("<<<<0110101xxxxxxxxxxxxxxx01xxxx", InstName.Ssat, InstEmit32.Ssat, OpCode32Sat.Create); SetA32("<<<<0110101xxxxxxxxxxxxxxx01xxxx", InstName.Ssat, InstEmit32.Ssat, OpCode32Sat.Create);
SetA32("<<<<01101010xxxxxxxx11110011xxxx", InstName.Ssat16, InstEmit32.Ssat16, OpCode32Sat16.Create); SetA32("<<<<01101010xxxxxxxx11110011xxxx", InstName.Ssat16, InstEmit32.Ssat16, OpCode32Sat16.Create);
SetA32("<<<<01100001xxxxxxxx11111111xxxx", InstName.Ssub8, InstEmit32.Ssub8, OpCode32AluReg.Create);
SetA32("<<<<00011000xxxx111111001001xxxx", InstName.Stl, InstEmit32.Stl, OpCode32MemStEx.Create); SetA32("<<<<00011000xxxx111111001001xxxx", InstName.Stl, InstEmit32.Stl, OpCode32MemStEx.Create);
SetA32("<<<<00011100xxxx111111001001xxxx", InstName.Stlb, InstEmit32.Stlb, OpCode32MemStEx.Create); SetA32("<<<<00011100xxxx111111001001xxxx", InstName.Stlb, InstEmit32.Stlb, OpCode32MemStEx.Create);
SetA32("<<<<00011000xxxxxxxx11101001xxxx", InstName.Stlex, InstEmit32.Stlex, OpCode32MemStEx.Create); SetA32("<<<<00011000xxxxxxxx11101001xxxx", InstName.Stlex, InstEmit32.Stlex, OpCode32MemStEx.Create);
@ -776,9 +797,11 @@ namespace ARMeilleure.Decoders
SetA32("<<<<00010011xxxx0000xxxxxxx0xxxx", InstName.Teq, InstEmit32.Teq, OpCode32AluRsImm.Create); SetA32("<<<<00010011xxxx0000xxxxxxx0xxxx", InstName.Teq, InstEmit32.Teq, OpCode32AluRsImm.Create);
SetA32("<<<<00010011xxxx0000xxxx0xx1xxxx", InstName.Teq, InstEmit32.Teq, OpCode32AluRsReg.Create); SetA32("<<<<00010011xxxx0000xxxx0xx1xxxx", InstName.Teq, InstEmit32.Teq, OpCode32AluRsReg.Create);
SetA32("<<<<0111111111111101111011111110", InstName.Trap, InstEmit32.Trap, OpCode32Exception.Create); SetA32("<<<<0111111111111101111011111110", InstName.Trap, InstEmit32.Trap, OpCode32Exception.Create);
SetA32("<<<<0011001000001111000000010010", InstName.Tsb, InstEmit32.Nop, OpCode32.Create); // Trace Synchronization Barrier (FEAT_TRF)
SetA32("<<<<00110001xxxx0000xxxxxxxxxxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluImm.Create); SetA32("<<<<00110001xxxx0000xxxxxxxxxxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluImm.Create);
SetA32("<<<<00010001xxxx0000xxxxxxx0xxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluRsImm.Create); SetA32("<<<<00010001xxxx0000xxxxxxx0xxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluRsImm.Create);
SetA32("<<<<00010001xxxx0000xxxx0xx1xxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluRsReg.Create); SetA32("<<<<00010001xxxx0000xxxx0xx1xxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluRsReg.Create);
SetA32("<<<<01100101xxxxxxxx11111001xxxx", InstName.Uadd8, InstEmit32.Uadd8, OpCode32AluReg.Create);
SetA32("<<<<0111111xxxxxxxxxxxxxx101xxxx", InstName.Ubfx, InstEmit32.Ubfx, OpCode32AluBf.Create); SetA32("<<<<0111111xxxxxxxxxxxxxx101xxxx", InstName.Ubfx, InstEmit32.Ubfx, OpCode32AluBf.Create);
SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, OpCode32AluMla.Create); SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, OpCode32AluMla.Create);
SetA32("<<<<01100111xxxxxxxx11111001xxxx", InstName.Uhadd8, InstEmit32.Uhadd8, OpCode32AluReg.Create); SetA32("<<<<01100111xxxxxxxx11111001xxxx", InstName.Uhadd8, InstEmit32.Uhadd8, OpCode32AluReg.Create);
@ -788,194 +811,237 @@ namespace ARMeilleure.Decoders
SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, OpCode32AluUmull.Create); SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, OpCode32AluUmull.Create);
SetA32("<<<<0110111xxxxxxxxxxxxxxx01xxxx", InstName.Usat, InstEmit32.Usat, OpCode32Sat.Create); SetA32("<<<<0110111xxxxxxxxxxxxxxx01xxxx", InstName.Usat, InstEmit32.Usat, OpCode32Sat.Create);
SetA32("<<<<01101110xxxxxxxx11110011xxxx", InstName.Usat16, InstEmit32.Usat16, OpCode32Sat16.Create); SetA32("<<<<01101110xxxxxxxx11110011xxxx", InstName.Usat16, InstEmit32.Usat16, OpCode32Sat16.Create);
SetA32("<<<<01100101xxxxxxxx11111111xxxx", InstName.Usub8, InstEmit32.Usub8, OpCode32AluReg.Create);
SetA32("<<<<01101110xxxxxxxxxx000111xxxx", InstName.Uxtb, InstEmit32.Uxtb, OpCode32AluUx.Create); SetA32("<<<<01101110xxxxxxxxxx000111xxxx", InstName.Uxtb, InstEmit32.Uxtb, OpCode32AluUx.Create);
SetA32("<<<<01101100xxxxxxxxxx000111xxxx", InstName.Uxtb16, InstEmit32.Uxtb16, OpCode32AluUx.Create); SetA32("<<<<01101100xxxxxxxxxx000111xxxx", InstName.Uxtb16, InstEmit32.Uxtb16, OpCode32AluUx.Create);
SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, OpCode32AluUx.Create); SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, OpCode32AluUx.Create);
SetA32("<<<<0011001000001111000000000010", InstName.Wfe, InstEmit32.Nop, OpCode32.Create);
SetA32("<<<<0011001000001111000000000011", InstName.Wfi, InstEmit32.Nop, OpCode32.Create);
SetA32("<<<<0011001000001111000000000001", InstName.Yield, InstEmit32.Nop, OpCode32.Create);
// FP & SIMD // VFP
SetA32("111100111x110000xxx0001101x0xxx0", InstName.Aesd_V, InstEmit32.Aesd_V, OpCode32Simd.Create); SetVfp("<<<<11101x110000xxxx101x11x0xxxx", InstName.Vabs, InstEmit32.Vabs_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetA32("111100111x110000xxx0001100x0xxx0", InstName.Aese_V, InstEmit32.Aese_V, OpCode32Simd.Create); SetVfp("<<<<11100x11xxxxxxxx101xx0x0xxxx", InstName.Vadd, InstEmit32.Vadd_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetA32("111100111x110000xxx0001111x0xxx0", InstName.Aesimc_V, InstEmit32.Aesimc_V, OpCode32Simd.Create); SetVfp("<<<<11101x11010xxxxx101x01x0xxxx", InstName.Vcmp, InstEmit32.Vcmp, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetA32("111100111x110000xxx0001110x0xxx0", InstName.Aesmc_V, InstEmit32.Aesmc_V, OpCode32Simd.Create); SetVfp("<<<<11101x11010xxxxx101x11x0xxxx", InstName.Vcmpe, InstEmit32.Vcmpe, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetA32("111100110x00xxx0xxx01100x1x0xxx0", InstName.Sha256h_V, InstEmit32.Sha256h_V, OpCode32SimdReg.Create); SetVfp("<<<<11101x110111xxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FD, OpCode32SimdS.Create, OpCode32SimdS.CreateT32); // FP 32 and 64, scalar.
SetA32("111100110x01xxx0xxx01100x1x0xxx0", InstName.Sha256h2_V, InstEmit32.Sha256h2_V, OpCode32SimdReg.Create); SetVfp("<<<<11101x11110xxxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create, OpCode32SimdCvtFI.CreateT32); // FP32 to int.
SetA32("111100111x111010xxx0001111x0xxx0", InstName.Sha256su0_V, InstEmit32.Sha256su0_V, OpCode32Simd.Create); SetVfp("<<<<11101x111000xxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create, OpCode32SimdCvtFI.CreateT32); // Int to FP32.
SetA32("111100110x10xxx0xxx01100x1x0xxx0", InstName.Sha256su1_V, InstEmit32.Sha256su1_V, OpCode32SimdReg.Create); SetVfp("111111101x1111xxxxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_RM, OpCode32SimdCvtFI.Create, OpCode32SimdCvtFI.CreateT32); // The many FP32 to int encodings (fp).
SetA32("1111001x0x<<xxxxxxxx0111xxx0xxxx", InstName.Vabd, InstEmit32.Vabd_I, OpCode32SimdReg.Create); SetVfp("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetA32("1111001x1x<<xxxxxxxx0111x0x0xxxx", InstName.Vabdl, InstEmit32.Vabdl_I, OpCode32SimdRegLong.Create); SetVfp("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, OpCode32SimdDupGP.Create, OpCode32SimdDupGP.CreateT32);
SetA32("<<<<11101x110000xxxx101x11x0xxxx", InstName.Vabs, InstEmit32.Vabs_S, OpCode32SimdS.Create); SetVfp("<<<<11101x10xxxxxxxx101xx0x0xxxx", InstName.Vfma, InstEmit32.Vfma_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetA32("111100111x11<<01xxxx00110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create); SetVfp("<<<<11101x10xxxxxxxx101xx1x0xxxx", InstName.Vfms, InstEmit32.Vfms_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetA32("111100111x111001xxxx01110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create); SetVfp("<<<<11101x01xxxxxxxx101xx1x0xxxx", InstName.Vfnma, InstEmit32.Vfnma_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetA32("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, OpCode32SimdReg.Create); SetVfp("<<<<11101x01xxxxxxxx101xx0x0xxxx", InstName.Vfnms, InstEmit32.Vfnms_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetA32("<<<<11100x11xxxxxxxx101xx0x0xxxx", InstName.Vadd, InstEmit32.Vadd_S, OpCode32SimdRegS.Create); SetVfp("<<<<11001x01xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
SetA32("111100100x00xxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, OpCode32SimdReg.Create); SetVfp("<<<<11001x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
SetA32("1111001x1x<<xxxxxxxx0000x0x0xxxx", InstName.Vaddl, InstEmit32.Vaddl_I, OpCode32SimdRegLong.Create); SetVfp("<<<<11010x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
SetA32("1111001x1x<<xxxxxxxx0001x0x0xxxx", InstName.Vaddw, InstEmit32.Vaddw_I, OpCode32SimdRegWide.Create); SetVfp("<<<<11001x01xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
SetA32("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, OpCode32SimdBinary.Create); SetVfp("<<<<11001x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
SetA32("111100100x01xxxxxxxx0001xxx1xxxx", InstName.Vbic, InstEmit32.Vbic_I, OpCode32SimdBinary.Create); SetVfp("<<<<11010x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
SetA32("1111001x1x000xxxxxxx<<x10x11xxxx", InstName.Vbic, InstEmit32.Vbic_II, OpCode32SimdImm.Create); SetVfp("<<<<1101xx01xxxxxxxx101xxxxxxxxx", InstName.Vldr, InstEmit32.Vldr, OpCode32SimdMemImm.Create, OpCode32SimdMemImm.CreateT32);
SetA32("111100110x11xxxxxxxx0001xxx1xxxx", InstName.Vbif, InstEmit32.Vbif, OpCode32SimdBinary.Create); SetVfp("111111101x00xxxxxxxx10>>x0x0xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetA32("111100110x10xxxxxxxx0001xxx1xxxx", InstName.Vbit, InstEmit32.Vbit, OpCode32SimdBinary.Create); SetVfp("111111101x00xxxxxxxx10>>x1x0xxxx", InstName.Vminnm, InstEmit32.Vminnm_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetA32("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, OpCode32SimdBinary.Create); SetVfp("<<<<11100x00xxxxxxxx101xx0x0xxxx", InstName.Vmla, InstEmit32.Vmla_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetA32("111100110x<<xxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, OpCode32SimdReg.Create); SetVfp("<<<<11100x00xxxxxxxx101xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetA32("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, OpCode32SimdReg.Create); SetVfp("<<<<11100xx0xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create, OpCode32SimdMovGpElem.CreateT32); // From gen purpose.
SetA32("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, OpCode32SimdCmpZ.Create); SetVfp("<<<<1110xxx1xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create, OpCode32SimdMovGpElem.CreateT32); // To gen purpose.
SetA32("1111001x0x<<xxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, OpCode32SimdReg.Create); SetVfp("<<<<1100010xxxxxxxxx101000x1xxxx", InstName.Vmov, InstEmit32.Vmov_G2, OpCode32SimdMovGpDouble.Create, OpCode32SimdMovGpDouble.CreateT32); // To/from gen purpose x2 and single precision x2.
SetA32("111100110x00xxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, OpCode32SimdReg.Create); SetVfp("<<<<1100010xxxxxxxxx101100x1xxxx", InstName.Vmov, InstEmit32.Vmov_GD, OpCode32SimdMovGpDouble.Create, OpCode32SimdMovGpDouble.CreateT32); // To/from gen purpose x2 and double precision.
SetA32("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, OpCode32SimdCmpZ.Create); SetVfp("<<<<1110000xxxxxxxxx1010x0010000", InstName.Vmov, InstEmit32.Vmov_GS, OpCode32SimdMovGp.Create, OpCode32SimdMovGp.CreateT32); // To/from gen purpose and single precision.
SetA32("1111001x0x<<xxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, OpCode32SimdReg.Create); SetVfp("<<<<11101x11xxxxxxxx101x0000xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm44.Create, OpCode32SimdImm44.CreateT32); // Scalar f16/32/64 based on size 01 10 11.
SetA32("111100110x10xxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, OpCode32SimdReg.Create); SetVfp("<<<<11101x110000xxxx101x01x0xxxx", InstName.Vmov, InstEmit32.Vmov_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetA32("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, OpCode32SimdCmpZ.Create); SetVfp("<<<<11101111xxxxxxxx101000010000", InstName.Vmrs, InstEmit32.Vmrs, OpCode32SimdSpecial.Create, OpCode32SimdSpecial.CreateT32);
SetA32("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, OpCode32SimdCmpZ.Create); SetVfp("<<<<11101110xxxxxxxx101000010000", InstName.Vmsr, InstEmit32.Vmsr, OpCode32SimdSpecial.Create, OpCode32SimdSpecial.CreateT32);
SetA32("111100111x11xx01xxxx0x100xx0xxxx", InstName.Vclt, InstEmit32.Vclt_Z, OpCode32SimdCmpZ.Create); SetVfp("<<<<11100x10xxxxxxxx101xx0x0xxxx", InstName.Vmul, InstEmit32.Vmul_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetA32("<<<<11101x11010xxxxx101x01x0xxxx", InstName.Vcmp, InstEmit32.Vcmp, OpCode32SimdS.Create); SetVfp("<<<<11101x110001xxxx101x01x0xxxx", InstName.Vneg, InstEmit32.Vneg_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetA32("<<<<11101x11010xxxxx101x11x0xxxx", InstName.Vcmpe, InstEmit32.Vcmpe, OpCode32SimdS.Create); SetVfp("<<<<11100x01xxxxxxxx101xx1x0xxxx", InstName.Vnmla, InstEmit32.Vnmla_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetA32("111100111x110000xxxx01010xx0xxxx", InstName.Vcnt, InstEmit32.Vcnt, OpCode32SimdCmpZ.Create); SetVfp("<<<<11100x01xxxxxxxx101xx0x0xxxx", InstName.Vnmls, InstEmit32.Vnmls_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetA32("<<<<11101x110111xxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FD, OpCode32SimdS.Create); // FP 32 and 64, scalar. SetVfp("<<<<11100x10xxxxxxxx101xx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetA32("<<<<11101x11110xxxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create); // FP32 to int. SetVfp("111111101x1110xxxxxx101x01x0xxxx", InstName.Vrint, InstEmit32.Vrint_RM, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetA32("<<<<11101x111000xxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create); // Int to FP32. SetVfp("<<<<11101x110110xxxx101x11x0xxxx", InstName.Vrint, InstEmit32.Vrint_Z, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetA32("111111101x1111xxxxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_RM, OpCode32SimdCvtFI.Create); // The many FP32 to int encodings (fp). SetVfp("<<<<11101x110111xxxx101x01x0xxxx", InstName.Vrintx, InstEmit32.Vrintx_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetA32("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, OpCode32SimdCmpZ.Create); // FP and integer, vector. SetVfp("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetA32("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, OpCode32SimdRegS.Create); SetVfp("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, OpCode32SimdSel.Create, OpCode32SimdSel.CreateT32);
SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, OpCode32SimdDupGP.Create); SetVfp("<<<<11001x00xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
SetA32("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, OpCode32SimdDupElem.Create); SetVfp("<<<<11001x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
SetA32("111100110x00xxxxxxxx0001xxx1xxxx", InstName.Veor, InstEmit32.Veor_I, OpCode32SimdBinary.Create); SetVfp("<<<<11010x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
SetA32("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, OpCode32SimdExt.Create); SetVfp("<<<<11001x00xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
SetA32("<<<<11101x10xxxxxxxx101xx0x0xxxx", InstName.Vfma, InstEmit32.Vfma_S, OpCode32SimdRegS.Create); SetVfp("<<<<11001x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
SetA32("111100100x00xxxxxxxx1100xxx1xxxx", InstName.Vfma, InstEmit32.Vfma_V, OpCode32SimdReg.Create); SetVfp("<<<<11010x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
SetA32("<<<<11101x10xxxxxxxx101xx1x0xxxx", InstName.Vfms, InstEmit32.Vfms_S, OpCode32SimdRegS.Create); SetVfp("<<<<1101xx00xxxxxxxx101xxxxxxxxx", InstName.Vstr, InstEmit32.Vstr, OpCode32SimdMemImm.Create, OpCode32SimdMemImm.CreateT32);
SetA32("111100100x10xxxxxxxx1100xxx1xxxx", InstName.Vfms, InstEmit32.Vfms_V, OpCode32SimdReg.Create); SetVfp("<<<<11100x11xxxxxxxx101xx1x0xxxx", InstName.Vsub, InstEmit32.Vsub_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetA32("<<<<11101x01xxxxxxxx101xx1x0xxxx", InstName.Vfnma, InstEmit32.Vfnma_S, OpCode32SimdRegS.Create);
SetA32("<<<<11101x01xxxxxxxx101xx0x0xxxx", InstName.Vfnms, InstEmit32.Vfnms_S, OpCode32SimdRegS.Create); // ASIMD
SetA32("1111001x0x<<xxxxxxxx0000xxx0xxxx", InstName.Vhadd, InstEmit32.Vhadd, OpCode32SimdReg.Create); SetAsimd("111100111x110000xxx0001101x0xxx0", InstName.Aesd_V, InstEmit32.Aesd_V, OpCode32Simd.Create, OpCode32Simd.CreateT32);
SetA32("111101001x10xxxxxxxxxx00xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create); SetAsimd("111100111x110000xxx0001100x0xxx0", InstName.Aese_V, InstEmit32.Aese_V, OpCode32Simd.Create, OpCode32Simd.CreateT32);
SetA32("111101000x10xxxxxxxx0111xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 1. SetAsimd("111100111x110000xxx0001111x0xxx0", InstName.Aesimc_V, InstEmit32.Aesimc_V, OpCode32Simd.Create, OpCode32Simd.CreateT32);
SetA32("111101000x10xxxxxxxx1010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 2. SetAsimd("111100111x110000xxx0001110x0xxx0", InstName.Aesmc_V, InstEmit32.Aesmc_V, OpCode32Simd.Create, OpCode32Simd.CreateT32);
SetA32("111101000x10xxxxxxxx0110xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 3. SetAsimd("111100110x00xxx0xxx01100x1x0xxx0", InstName.Sha256h_V, InstEmit32.Sha256h_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111101000x10xxxxxxxx0010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 4. SetAsimd("111100110x01xxx0xxx01100x1x0xxx0", InstName.Sha256h2_V, InstEmit32.Sha256h2_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111101001x10xxxxxxxxxx01xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create); SetAsimd("111100111x111010xxx0001111x0xxx0", InstName.Sha256su0_V, InstEmit32.Sha256su0_V, OpCode32Simd.Create, OpCode32Simd.CreateT32);
SetA32("111101000x10xxxxxxxx100xxxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create); // Regs = 1, inc = 1/2 (itype). SetAsimd("111100110x10xxx0xxx01100x1x0xxx0", InstName.Sha256su1_V, InstEmit32.Sha256su1_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111101000x10xxxxxxxx0011xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create); // Regs = 2, inc = 2. SetAsimd("1111001x0x<<xxxxxxxx0111xxx0xxxx", InstName.Vabd, InstEmit32.Vabd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111101001x10xxxxxxxxxx10xxxxxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create); SetAsimd("1111001x1x<<xxxxxxxx0111x0x0xxxx", InstName.Vabdl, InstEmit32.Vabdl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
SetA32("111101000x10xxxxxxxx010xxxxxxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype). SetAsimd("111100111x11<<01xxxx00110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetA32("111101001x10xxxxxxxxxx11xxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create); SetAsimd("111100111x111001xxxx01110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetA32("111101000x10xxxxxxxx000xxxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype). SetAsimd("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("<<<<11001x01xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create); SetAsimd("111100100x00xxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("<<<<11001x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create); SetAsimd("1111001x1x<<xxxxxxx00000x0x0xxxx", InstName.Vaddl, InstEmit32.Vaddl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
SetA32("<<<<11010x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create); SetAsimd("1111001x1x<<xxxxxxx00001x0x0xxxx", InstName.Vaddw, InstEmit32.Vaddw_I, OpCode32SimdRegWide.Create, OpCode32SimdRegWide.CreateT32);
SetA32("<<<<11001x01xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create); SetAsimd("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetA32("<<<<11001x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create); SetAsimd("111100100x01xxxxxxxx0001xxx1xxxx", InstName.Vbic, InstEmit32.Vbic_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetA32("<<<<11010x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create); SetAsimd("1111001x1x000xxxxxxx<<x10x11xxxx", InstName.Vbic, InstEmit32.Vbic_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
SetA32("<<<<1101xx01xxxxxxxx101xxxxxxxxx", InstName.Vldr, InstEmit32.Vldr, OpCode32SimdMemImm.Create); SetAsimd("111100110x11xxxxxxxx0001xxx1xxxx", InstName.Vbif, InstEmit32.Vbif, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetA32("1111001x0x<<xxxxxxxx0110xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_I, OpCode32SimdReg.Create); SetAsimd("111100110x10xxxxxxxx0001xxx1xxxx", InstName.Vbit, InstEmit32.Vbit, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetA32("111100100x00xxxxxxxx1111xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_V, OpCode32SimdReg.Create); SetAsimd("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetA32("1111001x0x<<xxxxxxxx0110xxx1xxxx", InstName.Vmin, InstEmit32.Vmin_I, OpCode32SimdReg.Create); SetAsimd("111100110x<<xxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111100100x10xxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, OpCode32SimdReg.Create); SetAsimd("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111111101x00xxxxxxxx10>>x0x0xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_S, OpCode32SimdRegS.Create); SetAsimd("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetA32("111100110x0xxxxxxxxx1111xxx1xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_V, OpCode32SimdReg.Create); SetAsimd("1111001x0x<<xxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111111101x00xxxxxxxx10>>x1x0xxxx", InstName.Vminnm, InstEmit32.Vminnm_S, OpCode32SimdRegS.Create); SetAsimd("111100110x00xxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111100110x1xxxxxxxxx1111xxx1xxxx", InstName.Vminnm, InstEmit32.Vminnm_V, OpCode32SimdReg.Create); SetAsimd("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetA32("1111001x1x<<xxxxxxxx000xx1x0xxxx", InstName.Vmla, InstEmit32.Vmla_1, OpCode32SimdRegElem.Create); SetAsimd("1111001x0x<<xxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111100100xxxxxxxxxxx1001xxx0xxxx", InstName.Vmla, InstEmit32.Vmla_I, OpCode32SimdReg.Create); SetAsimd("111100110x10xxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("<<<<11100x00xxxxxxxx101xx0x0xxxx", InstName.Vmla, InstEmit32.Vmla_S, OpCode32SimdRegS.Create); SetAsimd("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetA32("111100100x00xxxxxxxx1101xxx1xxxx", InstName.Vmla, InstEmit32.Vmla_V, OpCode32SimdReg.Create); SetAsimd("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetA32("1111001x1x<<xxxxxxxx010xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_1, OpCode32SimdRegElem.Create); SetAsimd("111100111x11xx01xxxx0x100xx0xxxx", InstName.Vclt, InstEmit32.Vclt_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetA32("<<<<11100x00xxxxxxxx101xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_S, OpCode32SimdRegS.Create); SetAsimd("111100111x110000xxxx01010xx0xxxx", InstName.Vcnt, InstEmit32.Vcnt, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetA32("111100100x10xxxxxxxx1101xxx1xxxx", InstName.Vmls, InstEmit32.Vmls_V, OpCode32SimdReg.Create); SetAsimd("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); // FP and integer, vector.
SetA32("111100110xxxxxxxxxxx1001xxx0xxxx", InstName.Vmls, InstEmit32.Vmls_I, OpCode32SimdReg.Create); SetAsimd("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, OpCode32SimdDupElem.Create, OpCode32SimdDupElem.CreateT32);
SetA32("1111001x1x<<xxxxxxx01010x0x0xxxx", InstName.Vmlsl, InstEmit32.Vmlsl_I, OpCode32SimdRegLong.Create); SetAsimd("111100110x00xxxxxxxx0001xxx1xxxx", InstName.Veor, InstEmit32.Veor_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetA32("<<<<11100xx0xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create); // From gen purpose. SetAsimd("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, OpCode32SimdExt.Create, OpCode32SimdExt.CreateT32);
SetA32("<<<<1110xxx1xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create); // To gen purpose. SetAsimd("111100100x00xxxxxxxx1100xxx1xxxx", InstName.Vfma, InstEmit32.Vfma_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("<<<<1100010xxxxxxxxx101000x1xxxx", InstName.Vmov, InstEmit32.Vmov_G2, OpCode32SimdMovGpDouble.Create); // To/from gen purpose x2 and single precision x2. SetAsimd("111100100x10xxxxxxxx1100xxx1xxxx", InstName.Vfms, InstEmit32.Vfms_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("<<<<1100010xxxxxxxxx101100x1xxxx", InstName.Vmov, InstEmit32.Vmov_GD, OpCode32SimdMovGpDouble.Create); // To/from gen purpose x2 and double precision. SetAsimd("1111001x0x<<xxxxxxxx0000xxx0xxxx", InstName.Vhadd, InstEmit32.Vhadd, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("<<<<1110000xxxxxxxxx1010x0010000", InstName.Vmov, InstEmit32.Vmov_GS, OpCode32SimdMovGp.Create); // To/from gen purpose and single precision. SetAsimd("111101001x10xxxxxxxx0000xxx0xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("1111001x1x000xxxxxxx0xx00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q vector I32. SetAsimd("111101001x10xxxxxxxx0100xx0xxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("<<<<11101x11xxxxxxxx101x0000xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm44.Create); // Scalar f16/32/64 based on size 01 10 11. SetAsimd("111101001x10xxxxxxxx1000x000xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("1111001x1x000xxxxxxx10x00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q I16. SetAsimd("111101001x10xxxxxxxx1000x011xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("1111001x1x000xxxxxxx11xx0x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q (dt - from cmode). SetAsimd("111101001x10xxxxxxxx110000x0xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("1111001x1x000xxxxxxx11100x11xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q I64. SetAsimd("111101001x10xxxxxxxx110001xxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("<<<<11101x110000xxxx101x01x0xxxx", InstName.Vmov, InstEmit32.Vmov_S, OpCode32SimdS.Create); SetAsimd("111101001x10xxxxxxxx110010xxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("1111001x1x001000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create); SetAsimd("111101000x10xxxxxxxx0111xx0xxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1.
SetA32("1111001x1x010000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create); SetAsimd("111101000x10xxxxxxxx1010xx<<xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2.
SetA32("1111001x1x100000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create); SetAsimd("111101000x10xxxxxxxx0110xx0xxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 3.
SetA32("111100111x11xx10xxxx001000x0xxx0", InstName.Vmovn, InstEmit32.Vmovn, OpCode32SimdCmpZ.Create); SetAsimd("111101000x10xxxxxxxx0010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 4.
SetA32("<<<<11101111xxxxxxxx101000010000", InstName.Vmrs, InstEmit32.Vmrs, OpCode32SimdSpecial.Create); SetAsimd("111101001x10xxxxxxxx0x01xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("<<<<11101110xxxxxxxx101000010000", InstName.Vmsr, InstEmit32.Vmsr, OpCode32SimdSpecial.Create); SetAsimd("111101001x10xxxxxxxx1001xx0xxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("1111001x1x<<xxxxxxxx100xx1x0xxxx", InstName.Vmul, InstEmit32.Vmul_1, OpCode32SimdRegElem.Create); SetAsimd("111101001x10xxxxxxxx1101<<xxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("111100100x<<xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create); SetAsimd("111101000x10xxxxxxxx100x<<0xxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype).
SetA32("111100110x00xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create); SetAsimd("111101000x10xxxxxxxx100x<<10xxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype).
SetA32("<<<<11100x10xxxxxxxx101xx0x0xxxx", InstName.Vmul, InstEmit32.Vmul_S, OpCode32SimdRegS.Create); SetAsimd("111101000x10xxxxxxxx0011<<xxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2, inc = 2.
SetA32("111100110x00xxxxxxxx1101xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_V, OpCode32SimdReg.Create); SetAsimd("111101001x10xxxxxxxx0x10xxx0xxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("1111001x1x<<xxxxxxx01010x1x0xxxx", InstName.Vmull, InstEmit32.Vmull_1, OpCode32SimdRegElemLong.Create); SetAsimd("111101001x10xxxxxxxx1010xx00xxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("1111001x1x<<xxxxxxx01100x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create); SetAsimd("111101001x10xxxxxxxx1110<<x0xxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("111100101xx0xxxxxxx01110x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create); // P8/P64 SetAsimd("111101000x10xxxxxxxx010x<<0xxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype).
SetA32("111100111x110000xxxx01011xx0xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, OpCode32SimdBinary.Create); SetAsimd("111101001x10xxxxxxxx0x11xxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("1111001x1x000xxxxxxx0xx00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create); // D/Q vector I32. SetAsimd("111101001x10xxxxxxxx1011xx<<xxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("1111001x1x000xxxxxxx10x00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create); SetAsimd("111101001x10xxxxxxxx1111<<x>xxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetA32("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create); SetAsimd("111101000x10xxxxxxxx000x<<xxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype).
SetA32("<<<<11101x110001xxxx101x01x0xxxx", InstName.Vneg, InstEmit32.Vneg_S, OpCode32SimdS.Create); SetAsimd("1111001x0x<<xxxxxxxx0110xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111100111x11<<01xxxx00111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create); SetAsimd("111100100x00xxxxxxxx1111xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111100111x111001xxxx01111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create); SetAsimd("1111001x0x<<xxxxxxxx0110xxx1xxxx", InstName.Vmin, InstEmit32.Vmin_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("<<<<11100x01xxxxxxxx101xx1x0xxxx", InstName.Vnmla, InstEmit32.Vnmla_S, OpCode32SimdRegS.Create); SetAsimd("111100100x10xxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("<<<<11100x01xxxxxxxx101xx0x0xxxx", InstName.Vnmls, InstEmit32.Vnmls_S, OpCode32SimdRegS.Create); SetAsimd("111100110x0xxxxxxxxx1111xxx1xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("<<<<11100x10xxxxxxxx101xx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, OpCode32SimdRegS.Create); SetAsimd("111100110x1xxxxxxxxx1111xxx1xxxx", InstName.Vminnm, InstEmit32.Vminnm_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111100100x11xxxxxxxx0001xxx1xxxx", InstName.Vorn, InstEmit32.Vorn_I, OpCode32SimdBinary.Create); SetAsimd("1111001x1x<<xxxxxxxx000xx1x0xxxx", InstName.Vmla, InstEmit32.Vmla_1, OpCode32SimdRegElem.Create, OpCode32SimdRegElem.CreateT32);
SetA32("111100100x10xxxxxxxx0001xxx1xxxx", InstName.Vorr, InstEmit32.Vorr_I, OpCode32SimdBinary.Create); SetAsimd("111100100xxxxxxxxxxx1001xxx0xxxx", InstName.Vmla, InstEmit32.Vmla_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("1111001x1x000xxxxxxx<<x10x01xxxx", InstName.Vorr, InstEmit32.Vorr_II, OpCode32SimdImm.Create); SetAsimd("111100100x00xxxxxxxx1101xxx1xxxx", InstName.Vmla, InstEmit32.Vmla_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, OpCode32SimdReg.Create); SetAsimd("1111001x1x<<xxxxxxx01000x0x0xxxx", InstName.Vmlal, InstEmit32.Vmlal_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
SetA32("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, OpCode32SimdReg.Create); SetAsimd("1111001x1x<<xxxxxxxx010xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_1, OpCode32SimdRegElem.Create, OpCode32SimdRegElem.CreateT32);
SetA32("1111001x0x<<xxxxxxxx1010x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_I, OpCode32SimdReg.Create); SetAsimd("111100100x10xxxxxxxx1101xxx1xxxx", InstName.Vmls, InstEmit32.Vmls_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111100110x00xxxxxxxx1111x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_V, OpCode32SimdReg.Create); SetAsimd("111100110xxxxxxxxxxx1001xxx0xxxx", InstName.Vmls, InstEmit32.Vmls_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("1111001x0x<<xxxxxxxx1010x0x1xxxx", InstName.Vpmin, InstEmit32.Vpmin_I, OpCode32SimdReg.Create); SetAsimd("1111001x1x<<xxxxxxx01010x0x0xxxx", InstName.Vmlsl, InstEmit32.Vmlsl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
SetA32("111100110x10xxxxxxxx1111x0x0xxxx", InstName.Vpmin, InstEmit32.Vpmin_V, OpCode32SimdReg.Create); SetAsimd("1111001x1x000xxxxxxx0xx00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q vector I32.
SetA32("1111001x1x>>>xxxxxxx100101x1xxx0", InstName.Vqrshrn, InstEmit32.Vqrshrn, OpCode32SimdShImmNarrow.Create); SetAsimd("1111001x1x000xxxxxxx10x00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q I16.
SetA32("111100111x>>>xxxxxxx100001x1xxx0", InstName.Vqrshrun, InstEmit32.Vqrshrun, OpCode32SimdShImmNarrow.Create); SetAsimd("1111001x1x000xxxxxxx11xx0x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q (dt - from cmode).
SetA32("1111001x1x>>>xxxxxxx100100x1xxx0", InstName.Vqshrn, InstEmit32.Vqshrn, OpCode32SimdShImmNarrow.Create); SetAsimd("1111001x1x000xxxxxxx11100x11xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q I64.
SetA32("111100111x111011xxxx010x0xx0xxxx", InstName.Vrecpe, InstEmit32.Vrecpe, OpCode32SimdSqrte.Create); SetAsimd("1111001x1x001000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create, OpCode32SimdLong.CreateT32);
SetA32("111100100x00xxxxxxxx1111xxx1xxxx", InstName.Vrecps, InstEmit32.Vrecps, OpCode32SimdReg.Create); SetAsimd("1111001x1x010000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create, OpCode32SimdLong.CreateT32);
SetA32("111100111x11xx00xxxx000<<xx0xxxx", InstName.Vrev, InstEmit32.Vrev, OpCode32SimdRev.Create); SetAsimd("1111001x1x100000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create, OpCode32SimdLong.CreateT32);
SetA32("111111101x1110xxxxxx101x01x0xxxx", InstName.Vrint, InstEmit32.Vrint_RM, OpCode32SimdS.Create); SetAsimd("111100111x11<<10xxxx001000x0xxx0", InstName.Vmovn, InstEmit32.Vmovn, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32);
SetA32("<<<<11101x110110xxxx101x11x0xxxx", InstName.Vrint, InstEmit32.Vrint_Z, OpCode32SimdS.Create); SetAsimd("1111001x1x<<xxxxxxxx100xx1x0xxxx", InstName.Vmul, InstEmit32.Vmul_1, OpCode32SimdRegElem.Create, OpCode32SimdRegElem.CreateT32);
SetA32("<<<<11101x110111xxxx101x01x0xxxx", InstName.Vrintx, InstEmit32.Vrintx_S, OpCode32SimdS.Create); SetAsimd("111100100x<<xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("1111001x1x>>>xxxxxxx0010>xx1xxxx", InstName.Vrshr, InstEmit32.Vrshr, OpCode32SimdShImm.Create); SetAsimd("111100110x00xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111100111x111011xxxx010x1xx0xxxx", InstName.Vrsqrte, InstEmit32.Vrsqrte, OpCode32SimdSqrte.Create); SetAsimd("111100110x00xxxxxxxx1101xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111100100x10xxxxxxxx1111xxx1xxxx", InstName.Vrsqrts, InstEmit32.Vrsqrts, OpCode32SimdReg.Create); SetAsimd("1111001x1x<<xxxxxxx01010x1x0xxxx", InstName.Vmull, InstEmit32.Vmull_1, OpCode32SimdRegElemLong.Create, OpCode32SimdRegElemLong.CreateT32);
SetA32("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, OpCode32SimdSel.Create); SetAsimd("1111001x1x<<xxxxxxx01100x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
SetA32("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, OpCode32SimdShImm.Create); SetAsimd("111100101xx0xxxxxxx01110x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32); // P8/P64
SetA32("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, OpCode32SimdReg.Create); SetAsimd("111100111x110000xxxx01011xx0xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetA32("1111001x1x>>>xxxxxxx101000x1xxxx", InstName.Vshll, InstEmit32.Vshll, OpCode32SimdShImmLong.Create); // A1 encoding. SetAsimd("1111001x1x000xxxxxxx0xx00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q vector I32.
SetA32("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, OpCode32SimdShImm.Create); SetAsimd("1111001x1x000xxxxxxx10x00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
SetA32("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, OpCode32SimdShImmNarrow.Create); SetAsimd("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
SetA32("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, OpCode32SimdS.Create); SetAsimd("111100111x11<<01xxxx00111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetA32("1111001x1x>>>xxxxxxx0001>xx1xxxx", InstName.Vsra, InstEmit32.Vsra, OpCode32SimdShImm.Create); SetAsimd("111100111x111001xxxx01111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetA32("111101001x00xxxxxxxx<<00xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create); SetAsimd("111100100x11xxxxxxxx0001xxx1xxxx", InstName.Vorn, InstEmit32.Vorn_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetA32("111101000x00xxxxxxxx0111xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 1. SetAsimd("111100100x10xxxxxxxx0001xxx1xxxx", InstName.Vorr, InstEmit32.Vorr_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetA32("111101000x00xxxxxxxx1010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 2. SetAsimd("1111001x1x000xxxxxxx<<x10x01xxxx", InstName.Vorr, InstEmit32.Vorr_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
SetA32("111101000x00xxxxxxxx0110xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 3. SetAsimd("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111101000x00xxxxxxxx0010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 4. SetAsimd("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111101001x00xxxxxxxx<<01xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemSingle.Create); SetAsimd("111100111x11<<00xxxx0010xxx0xxxx", InstName.Vpaddl, InstEmit32.Vpaddl, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetA32("111101000x00xxxxxxxx100xxxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create); // Regs = 1, inc = 1/2 (itype). SetAsimd("1111001x0x<<xxxxxxxx1010x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111101000x00xxxxxxxx0011xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create); // Regs = 2, inc = 2. SetAsimd("111100110x00xxxxxxxx1111x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111101001x00xxxxxxxx<<10xxxxxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemSingle.Create); SetAsimd("1111001x0x<<xxxxxxxx1010x0x1xxxx", InstName.Vpmin, InstEmit32.Vpmin_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111101000x00xxxxxxxx010xxxxxxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype). SetAsimd("111100110x10xxxxxxxx1111x0x0xxxx", InstName.Vpmin, InstEmit32.Vpmin_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111101001x00xxxxxxxx<<11xxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemSingle.Create); SetAsimd("1111001x0xxxxxxxxxxx0000xxx1xxxx", InstName.Vqadd, InstEmit32.Vqadd, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111101000x00xxxxxxxx000xxxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype). SetAsimd("111100100x01xxxxxxxx1011xxx0xxxx", InstName.Vqdmulh, InstEmit32.Vqdmulh, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("<<<<11001x00xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create); SetAsimd("111100100x10xxxxxxxx1011xxx0xxxx", InstName.Vqdmulh, InstEmit32.Vqdmulh, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("<<<<11001x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create); SetAsimd("111100111x11<<10xxxx00101xx0xxx0", InstName.Vqmovn, InstEmit32.Vqmovn, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32);
SetA32("<<<<11010x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create); SetAsimd("111100111x11<<10xxxx001001x0xxx0", InstName.Vqmovun, InstEmit32.Vqmovun, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32);
SetA32("<<<<11001x00xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create); SetAsimd("1111001x1x>>>xxxxxxx100101x1xxx0", InstName.Vqrshrn, InstEmit32.Vqrshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetA32("<<<<11001x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create); SetAsimd("111100111x>>>xxxxxxx100001x1xxx0", InstName.Vqrshrun, InstEmit32.Vqrshrun, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetA32("<<<<11010x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create); SetAsimd("1111001x1x>>>xxxxxxx100100x1xxx0", InstName.Vqshrn, InstEmit32.Vqshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetA32("<<<<1101xx00xxxxxxxx101xxxxxxxxx", InstName.Vstr, InstEmit32.Vstr, OpCode32SimdMemImm.Create); SetAsimd("111100111x>>>xxxxxxx100000x1xxx0", InstName.Vqshrun, InstEmit32.Vqshrun, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetA32("111100110xxxxxxxxxxx1000xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_I, OpCode32SimdReg.Create); SetAsimd("1111001x0xxxxxxxxxxx0010xxx1xxxx", InstName.Vqsub, InstEmit32.Vqsub, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("<<<<11100x11xxxxxxxx101xx1x0xxxx", InstName.Vsub, InstEmit32.Vsub_S, OpCode32SimdRegS.Create); SetAsimd("111100111x111011xxxx010x0xx0xxxx", InstName.Vrecpe, InstEmit32.Vrecpe, OpCode32SimdSqrte.Create, OpCode32SimdSqrte.CreateT32);
SetA32("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, OpCode32SimdReg.Create); SetAsimd("111100100x00xxxxxxxx1111xxx1xxxx", InstName.Vrecps, InstEmit32.Vrecps, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("1111001x1x<<xxxxxxxx0011x0x0xxxx", InstName.Vsubw, InstEmit32.Vsubw_I, OpCode32SimdRegWide.Create); SetAsimd("111100111x11xx00xxxx000<<xx0xxxx", InstName.Vrev, InstEmit32.Vrev, OpCode32SimdRev.Create, OpCode32SimdRev.CreateT32);
SetA32("111100111x11xxxxxxxx10xxxxx0xxxx", InstName.Vtbl, InstEmit32.Vtbl, OpCode32SimdTbl.Create); SetAsimd("1111001x0x<<xxxxxxxx0001xxx0xxxx", InstName.Vrhadd, InstEmit32.Vrhadd, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetA32("111100111x11<<10xxxx00001xx0xxxx", InstName.Vtrn, InstEmit32.Vtrn, OpCode32SimdCmpZ.Create); SetAsimd("111100111x111010xxxx01010xx0xxxx", InstName.Vrinta, InstEmit32.Vrinta_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetA32("111100100x<<xxxxxxxx1000xxx1xxxx", InstName.Vtst, InstEmit32.Vtst, OpCode32SimdReg.Create); SetAsimd("111100111x111010xxxx01101xx0xxxx", InstName.Vrintm, InstEmit32.Vrintm_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetA32("111100111x11<<10xxxx00010xx0xxxx", InstName.Vuzp, InstEmit32.Vuzp, OpCode32SimdCmpZ.Create); SetAsimd("111100111x111010xxxx01000xx0xxxx", InstName.Vrintn, InstEmit32.Vrintn_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetA32("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, OpCode32SimdCmpZ.Create); SetAsimd("111100111x111010xxxx01111xx0xxxx", InstName.Vrintp, InstEmit32.Vrintp_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx0010>xx1xxxx", InstName.Vrshr, InstEmit32.Vrshr, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("111100101x>>>xxxxxxx100001x1xxx0", InstName.Vrshrn, InstEmit32.Vrshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetAsimd("111100111x111011xxxx010x1xx0xxxx", InstName.Vrsqrte, InstEmit32.Vrsqrte, OpCode32SimdSqrte.Create, OpCode32SimdSqrte.CreateT32);
SetAsimd("111100100x10xxxxxxxx1111xxx1xxxx", InstName.Vrsqrts, InstEmit32.Vrsqrts, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx0011>xx1xxxx", InstName.Vrsra, InstEmit32.Vrsra, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx101000x1xxxx", InstName.Vshll, InstEmit32.Vshll, OpCode32SimdShImmLong.Create, OpCode32SimdShImmLong.CreateT32); // A1 encoding.
SetAsimd("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx0001>xx1xxxx", InstName.Vsra, InstEmit32.Vsra, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("111101001x00xxxxxxxx0000xxx0xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x00xxxxxxxx0100xx0xxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x00xxxxxxxx1000x000xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x00xxxxxxxx1000x011xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x00xxxxxxxx0111xx0xxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1.
SetAsimd("111101000x00xxxxxxxx1010xx<<xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2.
SetAsimd("111101000x00xxxxxxxx0110xx0xxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 3.
SetAsimd("111101000x00xxxxxxxx0010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 4.
SetAsimd("111101001x00xxxxxxxx0x01xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x00xxxxxxxx1001xx0xxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x00xxxxxxxx100x<<0xxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype).
SetAsimd("111101000x00xxxxxxxx100x<<10xxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype).
SetAsimd("111101000x00xxxxxxxx0011<<xxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2, inc = 2.
SetAsimd("111101001x00xxxxxxxx0x10xxx0xxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x00xxxxxxxx1010xx00xxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x00xxxxxxxx010x<<0xxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype).
SetAsimd("111101001x00xxxxxxxx0x11xxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x00xxxxxxxx1011xx<<xxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x00xxxxxxxx000x<<xxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype).
SetAsimd("111100110xxxxxxxxxxx1000xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x<<xxxxxxx00010x0x0xxxx", InstName.Vsubl, InstEmit32.Vsubl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
SetAsimd("1111001x1x<<xxxxxxx00011x0x0xxxx", InstName.Vsubw, InstEmit32.Vsubw_I, OpCode32SimdRegWide.Create, OpCode32SimdRegWide.CreateT32);
SetAsimd("111100111x11xxxxxxxx10xxxxx0xxxx", InstName.Vtbl, InstEmit32.Vtbl, OpCode32SimdTbl.Create, OpCode32SimdTbl.CreateT32);
SetAsimd("111100111x11<<10xxxx00001xx0xxxx", InstName.Vtrn, InstEmit32.Vtrn, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100100x<<xxxxxxxx1000xxx1xxxx", InstName.Vtst, InstEmit32.Vtst, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100111x11<<10xxxx00010xx0xxxx", InstName.Vuzp, InstEmit32.Vuzp, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
#endregion #endregion
#region "OpCode Table (AArch32, T16)" #region "OpCode Table (AArch32, T16)"
@ -1008,7 +1074,7 @@ namespace ARMeilleure.Decoders
SetT16("01000101xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT16AluRegHigh.Create); SetT16("01000101xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT16AluRegHigh.Create);
SetT16("01000110xxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16AluRegHigh.Create); SetT16("01000110xxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16AluRegHigh.Create);
SetT16("010001110xxxx000", InstName.Bx, InstEmit32.Bx, OpCodeT16BReg.Create); SetT16("010001110xxxx000", InstName.Bx, InstEmit32.Bx, OpCodeT16BReg.Create);
SetT16("010001111xxxx000", InstName.Blx, InstEmit32.Blx, OpCodeT16BReg.Create); SetT16("010001111xxxx000", InstName.Blx, InstEmit32.Blxr, OpCodeT16BReg.Create);
SetT16("01001xxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT16MemLit.Create); SetT16("01001xxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT16MemLit.Create);
SetT16("0101000xxxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT16MemReg.Create); SetT16("0101000xxxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT16MemReg.Create);
SetT16("0101001xxxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT16MemReg.Create); SetT16("0101001xxxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT16MemReg.Create);
@ -1041,7 +1107,14 @@ namespace ARMeilleure.Decoders
SetT16("1011101011xxxxxx", InstName.Revsh, InstEmit32.Revsh, OpCodeT16AluRegLow.Create); SetT16("1011101011xxxxxx", InstName.Revsh, InstEmit32.Revsh, OpCodeT16AluRegLow.Create);
SetT16("101110x1xxxxxxxx", InstName.Cbnz, InstEmit32.Cbnz, OpCodeT16BImmCmp.Create); SetT16("101110x1xxxxxxxx", InstName.Cbnz, InstEmit32.Cbnz, OpCodeT16BImmCmp.Create);
SetT16("1011110xxxxxxxxx", InstName.Pop, InstEmit32.Ldm, OpCodeT16MemStack.Create); SetT16("1011110xxxxxxxxx", InstName.Pop, InstEmit32.Ldm, OpCodeT16MemStack.Create);
SetT16("10111111xxxx0000", InstName.Nop, InstEmit32.Nop, OpCodeT16.Create); SetT16("1011111100000000", InstName.Nop, InstEmit32.Nop, OpCodeT16.Create);
SetT16("1011111100010000", InstName.Yield, InstEmit32.Nop, OpCodeT16.Create);
SetT16("1011111100100000", InstName.Wfe, InstEmit32.Nop, OpCodeT16.Create);
SetT16("1011111100110000", InstName.Wfi, InstEmit32.Nop, OpCodeT16.Create);
SetT16("1011111101000000", InstName.Sev, InstEmit32.Nop, OpCodeT16.Create);
SetT16("1011111101010000", InstName.Sevl, InstEmit32.Nop, OpCodeT16.Create);
SetT16("10111111011x0000", InstName.Hint, InstEmit32.Nop, OpCodeT16.Create); // Hint instruction
SetT16("101111111xxx0000", InstName.Hint, InstEmit32.Nop, OpCodeT16.Create); // Hint instruction
SetT16("10111111xxxx>>>>", InstName.It, InstEmit32.It, OpCodeT16IfThen.Create); SetT16("10111111xxxx>>>>", InstName.It, InstEmit32.It, OpCodeT16IfThen.Create);
SetT16("11000xxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT16MemMult.Create); SetT16("11000xxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT16MemMult.Create);
SetT16("11001xxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT16MemMult.Create); SetT16("11001xxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT16MemMult.Create);
@ -1056,74 +1129,166 @@ namespace ARMeilleure.Decoders
SetT32("11110x01010xxxxx0xxxxxxxxxxxxxxx", InstName.Adc, InstEmit32.Adc, OpCodeT32AluImm.Create); SetT32("11110x01010xxxxx0xxxxxxxxxxxxxxx", InstName.Adc, InstEmit32.Adc, OpCodeT32AluImm.Create);
SetT32("11101011000<xxxx0xxx<<<<xxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT32AluRsImm.Create); SetT32("11101011000<xxxx0xxx<<<<xxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT32AluRsImm.Create);
SetT32("11110x01000<xxxx0xxx<<<<xxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT32AluImm.Create); SetT32("11110x01000<xxxx0xxx<<<<xxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT32AluImm.Create);
SetT32("11110x100000xxxx0xxxxxxxxxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT32AluImm12.Create);
SetT32("11101010000<xxxx0xxx<<<<xxxxxxxx", InstName.And, InstEmit32.And, OpCodeT32AluRsImm.Create); SetT32("11101010000<xxxx0xxx<<<<xxxxxxxx", InstName.And, InstEmit32.And, OpCodeT32AluRsImm.Create);
SetT32("11110x00000<xxxx0xxx<<<<xxxxxxxx", InstName.And, InstEmit32.And, OpCodeT32AluImm.Create); SetT32("11110x00000<xxxx0xxx<<<<xxxxxxxx", InstName.And, InstEmit32.And, OpCodeT32AluImm.Create);
SetT32("11110x<<<xxxxxxx10x0xxxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT32BImm20.Create); SetT32("11110x<<<xxxxxxx10x0xxxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT32BImm20.Create);
SetT32("11110xxxxxxxxxxx10x1xxxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT32BImm24.Create); SetT32("11110xxxxxxxxxxx10x1xxxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT32BImm24.Create);
SetT32("11110011011011110xxxxxxxxx0xxxxx", InstName.Bfc, InstEmit32.Bfc, OpCodeT32AluBf.Create);
SetT32("111100110110<<<<0xxxxxxxxx0xxxxx", InstName.Bfi, InstEmit32.Bfi, OpCodeT32AluBf.Create);
SetT32("11101010001xxxxx0xxxxxxxxxxxxxxx", InstName.Bic, InstEmit32.Bic, OpCodeT32AluRsImm.Create); SetT32("11101010001xxxxx0xxxxxxxxxxxxxxx", InstName.Bic, InstEmit32.Bic, OpCodeT32AluRsImm.Create);
SetT32("11110x00001xxxxx0xxxxxxxxxxxxxxx", InstName.Bic, InstEmit32.Bic, OpCodeT32AluImm.Create); SetT32("11110x00001xxxxx0xxxxxxxxxxxxxxx", InstName.Bic, InstEmit32.Bic, OpCodeT32AluImm.Create);
SetT32("11110xxxxxxxxxxx11x1xxxxxxxxxxxx", InstName.Bl, InstEmit32.Bl, OpCodeT32BImm24.Create); SetT32("11110xxxxxxxxxxx11x1xxxxxxxxxxxx", InstName.Bl, InstEmit32.Bl, OpCodeT32BImm24.Create);
SetT32("11110xxxxxxxxxxx11x0xxxxxxxxxxx0", InstName.Blx, InstEmit32.Blx, OpCodeT32BImm24.Create); SetT32("11110xxxxxxxxxxx11x0xxxxxxxxxxx0", InstName.Blx, InstEmit32.Blx, OpCodeT32BImm24.Create);
SetT32("111110101011xxxx1111xxxx1000xxxx", InstName.Clz, InstEmit32.Clz, OpCodeT32AluReg.Create);
SetT32("111010110001xxxx0xxx1111xxxxxxxx", InstName.Cmn, InstEmit32.Cmn, OpCodeT32AluRsImm.Create); SetT32("111010110001xxxx0xxx1111xxxxxxxx", InstName.Cmn, InstEmit32.Cmn, OpCodeT32AluRsImm.Create);
SetT32("11110x010001xxxx0xxx1111xxxxxxxx", InstName.Cmn, InstEmit32.Cmn, OpCodeT32AluImm.Create); SetT32("11110x010001xxxx0xxx1111xxxxxxxx", InstName.Cmn, InstEmit32.Cmn, OpCodeT32AluImm.Create);
SetT32("111010111011xxxx0xxx1111xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT32AluRsImm.Create); SetT32("111010111011xxxx0xxx1111xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT32AluRsImm.Create);
SetT32("11110x011011xxxx0xxx1111xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT32AluImm.Create); SetT32("11110x011011xxxx0xxx1111xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT32AluImm.Create);
SetT32("11110011101011111000000000010100", InstName.Csdb, InstEmit32.Csdb, OpCodeT32.Create);
SetT32("11101010100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCodeT32AluRsImm.Create); SetT32("11101010100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCodeT32AluRsImm.Create);
SetT32("11110x00100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCodeT32AluImm.Create); SetT32("11110x00100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCodeT32AluImm.Create);
SetT32("11110011101011111000000000010000", InstName.Esb, InstEmit32.Nop, OpCodeT32.Create); // Error Synchronization Barrier (FEAT_RAS)
SetT32("1111001110101111100000000000011x", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
SetT32("11110011101011111000000000001xxx", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
SetT32("11110011101011111000000000010001", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
SetT32("11110011101011111000000000010011", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
SetT32("11110011101011111000000000010101", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
SetT32("1111001110101111100000000001011x", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
SetT32("11110011101011111000000000011xxx", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
SetT32("111100111010111110000000001xxxxx", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
SetT32("11110011101011111000000001xxxxxx", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
SetT32("1111001110101111100000001xxxxxxx", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
SetT32("111010001101xxxxxxxx111110101111", InstName.Lda, InstEmit32.Lda, OpCodeT32MemLdEx.Create);
SetT32("111010001101xxxxxxxx111110001111", InstName.Ldab, InstEmit32.Ldab, OpCodeT32MemLdEx.Create);
SetT32("111010001101xxxxxxxx111111101111", InstName.Ldaex, InstEmit32.Ldaex, OpCodeT32MemLdEx.Create); SetT32("111010001101xxxxxxxx111111101111", InstName.Ldaex, InstEmit32.Ldaex, OpCodeT32MemLdEx.Create);
SetT32("111010001101xxxxxxxx111111001111", InstName.Ldaexb, InstEmit32.Ldaexb, OpCodeT32MemLdEx.Create);
SetT32("111010001101xxxxxxxxxxxx11111111", InstName.Ldaexd, InstEmit32.Ldaexd, OpCodeT32MemLdEx.Create);
SetT32("111010001101xxxxxxxx111111011111", InstName.Ldaexh, InstEmit32.Ldaexh, OpCodeT32MemLdEx.Create);
SetT32("111010001101xxxxxxxx111110011111", InstName.Ldah, InstEmit32.Ldah, OpCodeT32MemLdEx.Create);
SetT32("1110100010x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT32MemMult.Create); SetT32("1110100010x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT32MemMult.Create);
SetT32("1110100100x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT32MemMult.Create); SetT32("1110100100x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT32MemMult.Create);
SetT32("111110000101xxxx<<<<10x1xxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm8.Create); SetT32("111110000101xxxxxxxx10x1xxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm8.Create);
SetT32("111110000101xxxx<<<<1100xxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm8.Create); SetT32("111110000101xxxxxxxx1100xxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm8.Create);
SetT32("111110000101xxxx<<<<11x1xxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm8.Create); SetT32("111110000101xxxxxxxx11x1xxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm8.Create);
SetT32("111110001101xxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm12.Create); SetT32("111110001101xxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm12.Create);
SetT32("111110000101<<<<xxxx000000xxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemRsImm.Create); SetT32("111110000101<<<<xxxx000000xxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemRsImm.Create);
SetT32("111110000001xxxx<<<<10x1xxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm8.Create); SetT32("111110000001xxxxxxxx10x1xxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm8.Create);
SetT32("111110000001xxxx<<<<1100xxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm8.Create); SetT32("111110000001xxxx<<<<1100xxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm8.Create);
SetT32("111110000001xxxx<<<<11x1xxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm8.Create); SetT32("111110000001xxxxxxxx11x1xxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm8.Create);
SetT32("111110001001xxxxxxxxxxxxxxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm12.Create); SetT32("111110001001xxxx<<<<xxxxxxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm12.Create);
SetT32("1110100>x1>1<<<<xxxxxxxxxxxxxxxx", InstName.Ldrd, InstEmit32.Ldrd, OpCodeT32MemImm8D.Create); SetT32("111110000001xxxx<<<<000000xxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemRsImm.Create);
SetT32("111110000011xxxx<<<<10x1xxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm8.Create); SetT32("11101000x111<<<<xxxxxxxxxxxxxxxx", InstName.Ldrd, InstEmit32.Ldrd, OpCodeT32MemImm8D.Create);
SetT32("11101001x1x1<<<<xxxxxxxxxxxxxxxx", InstName.Ldrd, InstEmit32.Ldrd, OpCodeT32MemImm8D.Create);
SetT32("111110000011xxxxxxxx10x1xxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm8.Create);
SetT32("111110000011xxxx<<<<1100xxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm8.Create); SetT32("111110000011xxxx<<<<1100xxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm8.Create);
SetT32("111110000011xxxx<<<<11x1xxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm8.Create); SetT32("111110000011xxxxxxxx11x1xxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm8.Create);
SetT32("111110001011xxxxxxxxxxxxxxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm12.Create); SetT32("111110001011xxxx<<<<xxxxxxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm12.Create);
SetT32("111110010001xxxx<<<<10x1xxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm8.Create); SetT32("111110000011xxxx<<<<000000xxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemRsImm.Create);
SetT32("111110010001xxxxxxxx10x1xxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm8.Create);
SetT32("111110010001xxxx<<<<1100xxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm8.Create); SetT32("111110010001xxxx<<<<1100xxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm8.Create);
SetT32("111110010001xxxx<<<<11x1xxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm8.Create); SetT32("111110010001xxxxxxxx11x1xxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm8.Create);
SetT32("111110011001xxxxxxxxxxxxxxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm12.Create); SetT32("111110011001xxxx<<<<xxxxxxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm12.Create);
SetT32("111110010011xxxx<<<<10x1xxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm8.Create); SetT32("111110010001xxxx<<<<000000xxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemRsImm.Create);
SetT32("111110010011xxxxxxxx10x1xxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm8.Create);
SetT32("111110010011xxxx<<<<1100xxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm8.Create); SetT32("111110010011xxxx<<<<1100xxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm8.Create);
SetT32("111110010011xxxx<<<<11x1xxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm8.Create); SetT32("111110010011xxxxxxxx11x1xxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm8.Create);
SetT32("111110011011xxxxxxxxxxxxxxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm12.Create); SetT32("111110011011xxxx<<<<xxxxxxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm12.Create);
SetT32("111110010011xxxx<<<<000000xxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemRsImm.Create);
SetT32("111110110000xxxx<<<<xxxx0000xxxx", InstName.Mla, InstEmit32.Mla, OpCodeT32AluMla.Create);
SetT32("111110110000xxxxxxxxxxxx0001xxxx", InstName.Mls, InstEmit32.Mls, OpCodeT32AluMla.Create);
SetT32("11101010010x11110xxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32AluRsImm.Create); SetT32("11101010010x11110xxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32AluRsImm.Create);
SetT32("111110100xxxxxxx1111xxxx0000xxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32ShiftReg.Create);
SetT32("11110x00010x11110xxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32AluImm.Create); SetT32("11110x00010x11110xxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32AluImm.Create);
SetT32("11110x100100xxxx0xxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32MovImm16.Create);
SetT32("11110x101100xxxx0xxxxxxxxxxxxxxx", InstName.Movt, InstEmit32.Movt, OpCodeT32MovImm16.Create);
SetT32("111110110000xxxx1111xxxx0000xxxx", InstName.Mul, InstEmit32.Mul, OpCodeT32AluMla.Create);
SetT32("11101010011x11110xxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCodeT32AluRsImm.Create); SetT32("11101010011x11110xxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCodeT32AluRsImm.Create);
SetT32("11110x00011x11110xxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCodeT32AluImm.Create); SetT32("11110x00011x11110xxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCodeT32AluImm.Create);
SetT32("11110011101011111000000000000000", InstName.Nop, InstEmit32.Nop, OpCodeT32.Create);
SetT32("11101010011x<<<<0xxxxxxxxxxxxxxx", InstName.Orn, InstEmit32.Orn, OpCodeT32AluRsImm.Create); SetT32("11101010011x<<<<0xxxxxxxxxxxxxxx", InstName.Orn, InstEmit32.Orn, OpCodeT32AluRsImm.Create);
SetT32("11110x00011x<<<<0xxxxxxxxxxxxxxx", InstName.Orn, InstEmit32.Orn, OpCodeT32AluImm.Create); SetT32("11110x00011x<<<<0xxxxxxxxxxxxxxx", InstName.Orn, InstEmit32.Orn, OpCodeT32AluImm.Create);
SetT32("11101010010x<<<<0xxxxxxxxxxxxxxx", InstName.Orr, InstEmit32.Orr, OpCodeT32AluRsImm.Create); SetT32("11101010010x<<<<0xxxxxxxxxxxxxxx", InstName.Orr, InstEmit32.Orr, OpCodeT32AluRsImm.Create);
SetT32("11110x00010x<<<<0xxxxxxxxxxxxxxx", InstName.Orr, InstEmit32.Orr, OpCodeT32AluImm.Create); SetT32("11110x00010x<<<<0xxxxxxxxxxxxxxx", InstName.Orr, InstEmit32.Orr, OpCodeT32AluImm.Create);
SetT32("1111100010x1xxxx1111xxxxxxxxxxxx", InstName.Pld, InstEmit32.Nop, OpCodeT32.Create);
SetT32("1111100000x1xxxx11111100xxxxxxxx", InstName.Pld, InstEmit32.Nop, OpCodeT32.Create);
SetT32("1111100000x1xxxx1111000000xxxxxx", InstName.Pld, InstEmit32.Nop, OpCodeT32.Create);
SetT32("11101011110xxxxx0xxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, OpCodeT32AluRsImm.Create); SetT32("11101011110xxxxx0xxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, OpCodeT32AluRsImm.Create);
SetT32("11110x01110xxxxx0xxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, OpCodeT32AluImm.Create); SetT32("11110x01110xxxxx0xxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, OpCodeT32AluImm.Create);
SetT32("111110101000xxxx1111xxxx0000xxxx", InstName.Sadd8, InstEmit32.Sadd8, OpCodeT32AluReg.Create);
SetT32("11101011011xxxxx0xxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCodeT32AluRsImm.Create); SetT32("11101011011xxxxx0xxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCodeT32AluRsImm.Create);
SetT32("11110x01011xxxxx0xxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCodeT32AluImm.Create); SetT32("11110x01011xxxxx0xxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCodeT32AluImm.Create);
SetT32("111100110100xxxx0xxxxxxxxx0xxxxx", InstName.Sbfx, InstEmit32.Sbfx, OpCodeT32AluBf.Create);
SetT32("111110111001xxxx1111xxxx1111xxxx", InstName.Sdiv, InstEmit32.Sdiv, OpCodeT32AluMla.Create);
SetT32("111110101010xxxx1111xxxx1000xxxx", InstName.Sel, InstEmit32.Sel, OpCodeT32AluReg.Create);
SetT32("111110101000xxxx1111xxxx0010xxxx", InstName.Shadd8, InstEmit32.Shadd8, OpCodeT32AluReg.Create);
SetT32("111110101100xxxx1111xxxx0010xxxx", InstName.Shsub8, InstEmit32.Shsub8, OpCodeT32AluReg.Create);
SetT32("11110011101011111000000000000100", InstName.Sev, InstEmit32.Nop, OpCodeT32.Create);
SetT32("11110011101011111000000000000101", InstName.Sevl, InstEmit32.Nop, OpCodeT32.Create);
SetT32("111110110001xxxx<<<<xxxx00xxxxxx", InstName.Smla__, InstEmit32.Smla__, OpCodeT32AluMla.Create);
SetT32("111110111100xxxxxxxxxxxx0000xxxx", InstName.Smlal, InstEmit32.Smlal, OpCodeT32AluUmull.Create);
SetT32("111110111100xxxxxxxxxxxx10xxxxxx", InstName.Smlal__, InstEmit32.Smlal__, OpCodeT32AluUmull.Create);
SetT32("111110110011xxxx<<<<xxxx000xxxxx", InstName.Smlaw_, InstEmit32.Smlaw_, OpCodeT32AluMla.Create);
SetT32("111110110101xxxx<<<<xxxx000xxxxx", InstName.Smmla, InstEmit32.Smmla, OpCodeT32AluMla.Create);
SetT32("111110110110xxxxxxxxxxxx000xxxxx", InstName.Smmls, InstEmit32.Smmls, OpCodeT32AluMla.Create);
SetT32("111110110001xxxx1111xxxx00xxxxxx", InstName.Smul__, InstEmit32.Smul__, OpCodeT32AluMla.Create);
SetT32("111110111000xxxxxxxxxxxx0000xxxx", InstName.Smull, InstEmit32.Smull, OpCodeT32AluUmull.Create);
SetT32("111110110011xxxx1111xxxx000xxxxx", InstName.Smulw_, InstEmit32.Smulw_, OpCodeT32AluMla.Create);
SetT32("111110101100xxxx1111xxxx0000xxxx", InstName.Ssub8, InstEmit32.Ssub8, OpCodeT32AluReg.Create);
SetT32("111010001100xxxxxxxx111110101111", InstName.Stl, InstEmit32.Stl, OpCodeT32MemStEx.Create);
SetT32("111010001100xxxxxxxx111110001111", InstName.Stlb, InstEmit32.Stlb, OpCodeT32MemStEx.Create);
SetT32("111010001100xxxxxxxx11111110xxxx", InstName.Stlex, InstEmit32.Stlex, OpCodeT32MemStEx.Create); SetT32("111010001100xxxxxxxx11111110xxxx", InstName.Stlex, InstEmit32.Stlex, OpCodeT32MemStEx.Create);
SetT32("111010001100xxxxxxxx11111100xxxx", InstName.Stlexb, InstEmit32.Stlexb, OpCodeT32MemStEx.Create);
SetT32("111010001100xxxxxxxxxxxx1111xxxx", InstName.Stlexd, InstEmit32.Stlexd, OpCodeT32MemStEx.Create);
SetT32("111010001100xxxxxxxx11111101xxxx", InstName.Stlexh, InstEmit32.Stlexh, OpCodeT32MemStEx.Create);
SetT32("111010001100xxxxxxxx111110011111", InstName.Stlh, InstEmit32.Stlh, OpCodeT32MemStEx.Create);
SetT32("1110100010x0xxxx0xxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT32MemMult.Create); SetT32("1110100010x0xxxx0xxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT32MemMult.Create);
SetT32("1110100100x0xxxx0xxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT32MemMult.Create); SetT32("1110100100x0xxxx0xxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT32MemMult.Create);
SetT32("111110000100xxxxxxxx1<<>xxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm8.Create); SetT32("111110000100<<<<xxxx10x1xxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm8.Create);
SetT32("111110001100xxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm12.Create); SetT32("111110000100<<<<xxxx1100xxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm8.Create);
SetT32("111110000100<<<<xxxx11x1xxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm8.Create);
SetT32("111110001100<<<<xxxxxxxxxxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm12.Create);
SetT32("111110000100<<<<xxxx000000xxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemRsImm.Create); SetT32("111110000100<<<<xxxx000000xxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemRsImm.Create);
SetT32("111110000000xxxxxxxx1<<>xxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm8.Create); SetT32("111110000000<<<<xxxx10x1xxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm8.Create);
SetT32("111110001000xxxxxxxxxxxxxxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm12.Create); SetT32("111110000000<<<<xxxx1100xxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm8.Create);
SetT32("1110100>x1>0<<<<xxxxxxxxxxxxxxxx", InstName.Strd, InstEmit32.Strd, OpCodeT32MemImm8D.Create); SetT32("111110000000<<<<xxxx11x1xxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm8.Create);
SetT32("111110000010xxxxxxxx1<<>xxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm8.Create); SetT32("111110001000<<<<xxxxxxxxxxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm12.Create);
SetT32("111110001010xxxxxxxxxxxxxxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm12.Create); SetT32("111110000000<<<<xxxx000000xxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemRsImm.Create);
SetT32("11101000x110<<<<xxxxxxxxxxxxxxxx", InstName.Strd, InstEmit32.Strd, OpCodeT32MemImm8D.Create);
SetT32("11101001x1x0<<<<xxxxxxxxxxxxxxxx", InstName.Strd, InstEmit32.Strd, OpCodeT32MemImm8D.Create);
SetT32("111110000010<<<<xxxx10x1xxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm8.Create);
SetT32("111110000010<<<<xxxx1100xxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm8.Create);
SetT32("111110000010<<<<xxxx11x1xxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm8.Create);
SetT32("111110001010<<<<xxxxxxxxxxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm12.Create);
SetT32("111110000010<<<<xxxx000000xxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemRsImm.Create);
SetT32("11101011101<xxxx0xxx<<<<xxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT32AluRsImm.Create); SetT32("11101011101<xxxx0xxx<<<<xxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT32AluRsImm.Create);
SetT32("11110x01101<xxxx0xxx<<<<xxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT32AluImm.Create); SetT32("11110x01101<xxxx0xxx<<<<xxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT32AluImm.Create);
SetT32("11110x101010xxxx0xxxxxxxxxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT32AluImm12.Create);
SetT32("111110100100xxxx1111xxxx10xxxxxx", InstName.Sxtb, InstEmit32.Sxtb, OpCodeT32AluUx.Create);
SetT32("111110100010xxxx1111xxxx10xxxxxx", InstName.Sxtb16, InstEmit32.Sxtb16, OpCodeT32AluUx.Create);
SetT32("111110100000xxxx1111xxxx10xxxxxx", InstName.Sxth, InstEmit32.Sxth, OpCodeT32AluUx.Create);
SetT32("111010001101xxxx111100000000xxxx", InstName.Tbb, InstEmit32.Tbb, OpCodeT32Tb.Create);
SetT32("111010001101xxxx111100000001xxxx", InstName.Tbh, InstEmit32.Tbh, OpCodeT32Tb.Create);
SetT32("111010101001xxxx0xxx1111xxxxxxxx", InstName.Teq, InstEmit32.Teq, OpCodeT32AluRsImm.Create); SetT32("111010101001xxxx0xxx1111xxxxxxxx", InstName.Teq, InstEmit32.Teq, OpCodeT32AluRsImm.Create);
SetT32("11110x001001xxxx0xxx1111xxxxxxxx", InstName.Teq, InstEmit32.Teq, OpCodeT32AluImm.Create); SetT32("11110x001001xxxx0xxx1111xxxxxxxx", InstName.Teq, InstEmit32.Teq, OpCodeT32AluImm.Create);
SetT32("11110011101011111000000000010010", InstName.Tsb, InstEmit32.Nop, OpCodeT32.Create); // Trace Synchronization Barrier (FEAT_TRF)
SetT32("111010100001xxxx0xxx1111xxxxxxxx", InstName.Tst, InstEmit32.Tst, OpCodeT32AluRsImm.Create); SetT32("111010100001xxxx0xxx1111xxxxxxxx", InstName.Tst, InstEmit32.Tst, OpCodeT32AluRsImm.Create);
SetT32("11110x000001xxxx0xxx1111xxxxxxxx", InstName.Tst, InstEmit32.Tst, OpCodeT32AluImm.Create); SetT32("11110x000001xxxx0xxx1111xxxxxxxx", InstName.Tst, InstEmit32.Tst, OpCodeT32AluImm.Create);
SetT32("111110101000xxxx1111xxxx0100xxxx", InstName.Uadd8, InstEmit32.Uadd8, OpCodeT32AluReg.Create);
SetT32("111100111100xxxx0xxxxxxxxx0xxxxx", InstName.Ubfx, InstEmit32.Ubfx, OpCodeT32AluBf.Create);
SetT32("111110111011xxxx1111xxxx1111xxxx", InstName.Udiv, InstEmit32.Udiv, OpCodeT32AluMla.Create);
SetT32("111110101000xxxx1111xxxx0110xxxx", InstName.Uhadd8, InstEmit32.Uhadd8, OpCodeT32AluReg.Create);
SetT32("111110101100xxxx1111xxxx0110xxxx", InstName.Uhsub8, InstEmit32.Uhsub8, OpCodeT32AluReg.Create);
SetT32("111110111110xxxxxxxxxxxx0110xxxx", InstName.Umaal, InstEmit32.Umaal, OpCodeT32AluUmull.Create);
SetT32("111110111110xxxxxxxxxxxx0000xxxx", InstName.Umlal, InstEmit32.Umlal, OpCodeT32AluUmull.Create);
SetT32("111110111010xxxxxxxxxxxx0000xxxx", InstName.Umull, InstEmit32.Umull, OpCodeT32AluUmull.Create);
SetT32("111110101100xxxx1111xxxx0100xxxx", InstName.Usub8, InstEmit32.Usub8, OpCodeT32AluReg.Create);
SetT32("111110100101xxxx1111xxxx10xxxxxx", InstName.Uxtb, InstEmit32.Uxtb, OpCodeT32AluUx.Create);
SetT32("111110100011xxxx1111xxxx10xxxxxx", InstName.Uxtb16, InstEmit32.Uxtb16, OpCodeT32AluUx.Create);
SetT32("111110100001xxxx1111xxxx10xxxxxx", InstName.Uxth, InstEmit32.Uxth, OpCodeT32AluUx.Create);
SetT32("11110011101011111000000000000010", InstName.Wfe, InstEmit32.Nop, OpCodeT32.Create);
SetT32("11110011101011111000000000000011", InstName.Wfi, InstEmit32.Nop, OpCodeT32.Create);
SetT32("11110011101011111000000000000001", InstName.Yield, InstEmit32.Nop, OpCodeT32.Create);
#endregion #endregion
FillFastLookupTable(InstA32FastLookup, AllInstA32, ToFastLookupIndexA); FillFastLookupTable(InstA32FastLookup, AllInstA32, ToFastLookupIndexA);
@ -1180,6 +1345,46 @@ namespace ARMeilleure.Decoders
Set(reversedEncoding, AllInstT32, new InstDescriptor(name, emitter), reversedMakeOp); Set(reversedEncoding, AllInstT32, new InstDescriptor(name, emitter), reversedMakeOp);
} }
private static void SetVfp(string encoding, InstName name, InstEmitter emitter, MakeOp makeOpA32, MakeOp makeOpT32)
{
SetA32(encoding, name, emitter, makeOpA32);
string thumbEncoding = encoding;
if (thumbEncoding.StartsWith("<<<<"))
{
thumbEncoding = "1110" + thumbEncoding.Substring(4);
}
SetT32(thumbEncoding, name, emitter, makeOpT32);
}
private static void SetAsimd(string encoding, InstName name, InstEmitter emitter, MakeOp makeOpA32, MakeOp makeOpT32)
{
SetA32(encoding, name, emitter, makeOpA32);
string thumbEncoding = encoding;
if (thumbEncoding.StartsWith("11110100"))
{
thumbEncoding = "11111001" + encoding.Substring(8);
}
else if (thumbEncoding.StartsWith("1111001x"))
{
thumbEncoding = "111x1111" + encoding.Substring(8);
}
else if (thumbEncoding.StartsWith("11110010"))
{
thumbEncoding = "11101111" + encoding.Substring(8);
}
else if (thumbEncoding.StartsWith("11110011"))
{
thumbEncoding = "11111111" + encoding.Substring(8);
}
else
{
throw new ArgumentException("Invalid ASIMD instruction encoding");
}
SetT32(thumbEncoding, name, emitter, makeOpT32);
}
private static void SetA64(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp) private static void SetA64(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
{ {
Set(encoding, AllInstA64, new InstDescriptor(name, emitter), makeOp); Set(encoding, AllInstA64, new InstDescriptor(name, emitter), makeOp);

View File

@ -1,51 +0,0 @@
using System.Diagnostics.Tracing;
namespace ARMeilleure.Diagnostics.EventSources
{
[EventSource(Name = "ARMeilleure")]
class AddressTableEventSource : EventSource
{
public static readonly AddressTableEventSource Log = new();
private ulong _size;
private ulong _leafSize;
private PollingCounter _sizeCounter;
private PollingCounter _leafSizeCounter;
public AddressTableEventSource()
{
_sizeCounter = new PollingCounter("addr-tab-alloc", this, () => _size / 1024d / 1024d)
{
DisplayName = "AddressTable Total Bytes Allocated",
DisplayUnits = "MB"
};
_leafSizeCounter = new PollingCounter("addr-tab-leaf-alloc", this, () => _leafSize / 1024d / 1024d)
{
DisplayName = "AddressTable Total Leaf Bytes Allocated",
DisplayUnits = "MB"
};
}
public void Allocated(int bytes, bool leaf)
{
_size += (uint)bytes;
if (leaf)
{
_leafSize += (uint)bytes;
}
}
protected override void Dispose(bool disposing)
{
_leafSizeCounter.Dispose();
_leafSizeCounter = null;
_sizeCounter.Dispose();
_sizeCounter = null;
base.Dispose(disposing);
}
}
}

View File

@ -0,0 +1,67 @@
using System.Diagnostics.Tracing;
using System.Threading;
namespace ARMeilleure.Diagnostics
{
[EventSource(Name = "ARMeilleure")]
class TranslatorEventSource : EventSource
{
public static readonly TranslatorEventSource Log = new();
private int _rejitQueue;
private ulong _funcTabSize;
private ulong _funcTabLeafSize;
private PollingCounter _rejitQueueCounter;
private PollingCounter _funcTabSizeCounter;
private PollingCounter _funcTabLeafSizeCounter;
public TranslatorEventSource()
{
_rejitQueueCounter = new PollingCounter("rejit-queue-length", this, () => _rejitQueue)
{
DisplayName = "Rejit Queue Length"
};
_funcTabSizeCounter = new PollingCounter("addr-tab-alloc", this, () => _funcTabSize / 1024d / 1024d)
{
DisplayName = "AddressTable Total Bytes Allocated",
DisplayUnits = "MB"
};
_funcTabLeafSizeCounter = new PollingCounter("addr-tab-leaf-alloc", this, () => _funcTabLeafSize / 1024d / 1024d)
{
DisplayName = "AddressTable Total Leaf Bytes Allocated",
DisplayUnits = "MB"
};
}
public void RejitQueueAdd(int count)
{
Interlocked.Add(ref _rejitQueue, count);
}
public void AddressTableAllocated(int bytes, bool leaf)
{
_funcTabSize += (uint)bytes;
if (leaf)
{
_funcTabLeafSize += (uint)bytes;
}
}
protected override void Dispose(bool disposing)
{
_rejitQueueCounter.Dispose();
_rejitQueueCounter = null;
_funcTabLeafSizeCounter.Dispose();
_funcTabLeafSizeCounter = null;
_funcTabSizeCounter.Dispose();
_funcTabSizeCounter = null;
base.Dispose(disposing);
}
}
}

View File

@ -74,7 +74,7 @@ namespace ARMeilleure.Instructions
public static void Bfc(ArmEmitterContext context) public static void Bfc(ArmEmitterContext context)
{ {
OpCode32AluBf op = (OpCode32AluBf)context.CurrOp; IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
Operand d = GetIntA32(context, op.Rd); Operand d = GetIntA32(context, op.Rd);
Operand res = context.BitwiseAnd(d, Const(~op.DestMask)); Operand res = context.BitwiseAnd(d, Const(~op.DestMask));
@ -84,7 +84,7 @@ namespace ARMeilleure.Instructions
public static void Bfi(ArmEmitterContext context) public static void Bfi(ArmEmitterContext context)
{ {
OpCode32AluBf op = (OpCode32AluBf)context.CurrOp; IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
Operand n = GetIntA32(context, op.Rn); Operand n = GetIntA32(context, op.Rn);
Operand d = GetIntA32(context, op.Rd); Operand d = GetIntA32(context, op.Rd);
@ -185,7 +185,7 @@ namespace ARMeilleure.Instructions
public static void Movt(ArmEmitterContext context) public static void Movt(ArmEmitterContext context)
{ {
OpCode32AluImm16 op = (OpCode32AluImm16)context.CurrOp; IOpCode32AluImm16 op = (IOpCode32AluImm16)context.CurrOp;
Operand d = GetIntA32(context, op.Rd); Operand d = GetIntA32(context, op.Rd);
Operand imm = Const(op.Immediate << 16); // Immeditate value as top halfword. Operand imm = Const(op.Immediate << 16); // Immeditate value as top halfword.
@ -363,6 +363,11 @@ namespace ARMeilleure.Instructions
EmitAluStore(context, res); EmitAluStore(context, res);
} }
public static void Sadd8(ArmEmitterContext context)
{
EmitAddSub8(context, add: true, unsigned: false);
}
public static void Sbc(ArmEmitterContext context) public static void Sbc(ArmEmitterContext context)
{ {
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp; IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
@ -389,7 +394,7 @@ namespace ARMeilleure.Instructions
public static void Sbfx(ArmEmitterContext context) public static void Sbfx(ArmEmitterContext context)
{ {
OpCode32AluBf op = (OpCode32AluBf)context.CurrOp; IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width. var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
@ -401,17 +406,38 @@ namespace ARMeilleure.Instructions
public static void Sdiv(ArmEmitterContext context) public static void Sdiv(ArmEmitterContext context)
{ {
EmitDiv(context, false); EmitDiv(context, unsigned: false);
}
public static void Sel(ArmEmitterContext context)
{
IOpCode32AluReg op = (IOpCode32AluReg)context.CurrOp;
Operand n = GetIntA32(context, op.Rn);
Operand m = GetIntA32(context, op.Rm);
Operand ge0 = context.ZeroExtend8(OperandType.I32, context.Negate(GetFlag(PState.GE0Flag)));
Operand ge1 = context.ZeroExtend8(OperandType.I32, context.Negate(GetFlag(PState.GE1Flag)));
Operand ge2 = context.ZeroExtend8(OperandType.I32, context.Negate(GetFlag(PState.GE2Flag)));
Operand ge3 = context.Negate(GetFlag(PState.GE3Flag));
Operand mask = context.BitwiseOr(ge0, context.ShiftLeft(ge1, Const(8)));
mask = context.BitwiseOr(mask, context.ShiftLeft(ge2, Const(16)));
mask = context.BitwiseOr(mask, context.ShiftLeft(ge3, Const(24)));
Operand res = context.BitwiseOr(context.BitwiseAnd(n, mask), context.BitwiseAnd(m, context.BitwiseNot(mask)));
SetIntA32(context, op.Rd, res);
} }
public static void Shadd8(ArmEmitterContext context) public static void Shadd8(ArmEmitterContext context)
{ {
EmitHadd8(context, false); EmitHadd8(context, unsigned: false);
} }
public static void Shsub8(ArmEmitterContext context) public static void Shsub8(ArmEmitterContext context)
{ {
EmitHsub8(context, false); EmitHsub8(context, unsigned: false);
} }
public static void Ssat(ArmEmitterContext context) public static void Ssat(ArmEmitterContext context)
@ -428,6 +454,11 @@ namespace ARMeilleure.Instructions
EmitSat16(context, -(1 << op.SatImm), (1 << op.SatImm) - 1); EmitSat16(context, -(1 << op.SatImm), (1 << op.SatImm) - 1);
} }
public static void Ssub8(ArmEmitterContext context)
{
EmitAddSub8(context, add: false, unsigned: false);
}
public static void Sub(ArmEmitterContext context) public static void Sub(ArmEmitterContext context)
{ {
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp; IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
@ -482,9 +513,14 @@ namespace ARMeilleure.Instructions
EmitNZFlagsCheck(context, res); EmitNZFlagsCheck(context, res);
} }
public static void Uadd8(ArmEmitterContext context)
{
EmitAddSub8(context, add: true, unsigned: true);
}
public static void Ubfx(ArmEmitterContext context) public static void Ubfx(ArmEmitterContext context)
{ {
OpCode32AluBf op = (OpCode32AluBf)context.CurrOp; IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width. var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
@ -496,17 +532,17 @@ namespace ARMeilleure.Instructions
public static void Udiv(ArmEmitterContext context) public static void Udiv(ArmEmitterContext context)
{ {
EmitDiv(context, true); EmitDiv(context, unsigned: true);
} }
public static void Uhadd8(ArmEmitterContext context) public static void Uhadd8(ArmEmitterContext context)
{ {
EmitHadd8(context, true); EmitHadd8(context, unsigned: true);
} }
public static void Uhsub8(ArmEmitterContext context) public static void Uhsub8(ArmEmitterContext context)
{ {
EmitHsub8(context, true); EmitHsub8(context, unsigned: true);
} }
public static void Usat(ArmEmitterContext context) public static void Usat(ArmEmitterContext context)
@ -523,6 +559,11 @@ namespace ARMeilleure.Instructions
EmitSat16(context, 0, (1 << op.SatImm) - 1); EmitSat16(context, 0, (1 << op.SatImm) - 1);
} }
public static void Usub8(ArmEmitterContext context)
{
EmitAddSub8(context, add: false, unsigned: true);
}
public static void Uxtb(ArmEmitterContext context) public static void Uxtb(ArmEmitterContext context)
{ {
EmitSignExtend(context, false, 8); EmitSignExtend(context, false, 8);
@ -678,9 +719,40 @@ namespace ARMeilleure.Instructions
context.MarkLabel(lblEnd); context.MarkLabel(lblEnd);
} }
private static void EmitAddSub8(ArmEmitterContext context, bool add, bool unsigned)
{
IOpCode32AluReg op = (IOpCode32AluReg)context.CurrOp;
Operand n = GetIntA32(context, op.Rn);
Operand m = GetIntA32(context, op.Rm);
Operand res = Const(0);
for (int byteSel = 0; byteSel < 4; byteSel++)
{
Operand shift = Const(byteSel * 8);
Operand nByte = context.ShiftRightUI(n, shift);
Operand mByte = context.ShiftRightUI(m, shift);
nByte = unsigned ? context.ZeroExtend8(OperandType.I32, nByte) : context.SignExtend8(OperandType.I32, nByte);
mByte = unsigned ? context.ZeroExtend8(OperandType.I32, mByte) : context.SignExtend8(OperandType.I32, mByte);
Operand resByte = add ? context.Add(nByte, mByte) : context.Subtract(nByte, mByte);
res = context.BitwiseOr(res, context.ShiftLeft(context.ZeroExtend8(OperandType.I32, resByte), shift));
SetFlag(context, PState.GE0Flag + byteSel, unsigned && add
? context.ShiftRightUI(resByte, Const(8))
: context.ShiftRightUI(context.BitwiseNot(resByte), Const(31)));
}
SetIntA32(context, op.Rd, res);
}
private static void EmitHadd8(ArmEmitterContext context, bool unsigned) private static void EmitHadd8(ArmEmitterContext context, bool unsigned)
{ {
OpCode32AluReg op = (OpCode32AluReg)context.CurrOp; IOpCode32AluReg op = (IOpCode32AluReg)context.CurrOp;
Operand m = GetIntA32(context, op.Rm); Operand m = GetIntA32(context, op.Rm);
Operand n = GetIntA32(context, op.Rn); Operand n = GetIntA32(context, op.Rn);
@ -710,7 +782,7 @@ namespace ARMeilleure.Instructions
private static void EmitHsub8(ArmEmitterContext context, bool unsigned) private static void EmitHsub8(ArmEmitterContext context, bool unsigned)
{ {
OpCode32AluReg op = (OpCode32AluReg)context.CurrOp; IOpCode32AluReg op = (IOpCode32AluReg)context.CurrOp;
Operand m = GetIntA32(context, op.Rm); Operand m = GetIntA32(context, op.Rm);
Operand n = GetIntA32(context, op.Rn); Operand n = GetIntA32(context, op.Rn);

View File

@ -128,7 +128,7 @@ namespace ARMeilleure.Instructions
{ {
Debug.Assert(value.Type == OperandType.I32); Debug.Assert(value.Type == OperandType.I32);
if (((OpCode32)context.CurrOp).IsThumb()) if (((OpCode32)context.CurrOp).IsThumb)
{ {
bool isReturn = IsA32Return(context); bool isReturn = IsA32Return(context);
if (!isReturn) if (!isReturn)
@ -205,7 +205,7 @@ namespace ARMeilleure.Instructions
return Const(op.Immediate); return Const(op.Immediate);
} }
case OpCode32AluImm16 op: return Const(op.Immediate); case IOpCode32AluImm16 op: return Const(op.Immediate);
case IOpCode32AluRsImm op: return GetMShiftedByImmediate(context, op, setCarry); case IOpCode32AluRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
case IOpCode32AluRsReg op: return GetMShiftedByReg(context, op, setCarry); case IOpCode32AluRsReg op: return GetMShiftedByReg(context, op, setCarry);

View File

@ -34,7 +34,7 @@ namespace ARMeilleure.Instructions
uint pc = op.GetPc(); uint pc = op.GetPc();
bool isThumb = ((OpCode32)context.CurrOp).IsThumb(); bool isThumb = ((OpCode32)context.CurrOp).IsThumb;
uint currentPc = isThumb uint currentPc = isThumb
? pc | 1 ? pc | 1
@ -61,7 +61,7 @@ namespace ARMeilleure.Instructions
Operand addr = context.Copy(GetIntA32(context, op.Rm)); Operand addr = context.Copy(GetIntA32(context, op.Rm));
Operand bitOne = context.BitwiseAnd(addr, Const(1)); Operand bitOne = context.BitwiseAnd(addr, Const(1));
bool isThumb = ((OpCode32)context.CurrOp).IsThumb(); bool isThumb = ((OpCode32)context.CurrOp).IsThumb;
uint currentPc = isThumb uint currentPc = isThumb
? (pc - 2) | 1 ? (pc - 2) | 1
@ -107,5 +107,30 @@ namespace ARMeilleure.Instructions
context.SetIfThenBlockState(op.IfThenBlockConds); context.SetIfThenBlockState(op.IfThenBlockConds);
} }
public static void Tbb(ArmEmitterContext context) => EmitTb(context, halfword: false);
public static void Tbh(ArmEmitterContext context) => EmitTb(context, halfword: true);
private static void EmitTb(ArmEmitterContext context, bool halfword)
{
OpCodeT32Tb op = (OpCodeT32Tb)context.CurrOp;
Operand halfwords;
if (halfword)
{
Operand address = context.Add(GetIntA32(context, op.Rn), context.ShiftLeft(GetIntA32(context, op.Rm), Const(1)));
halfwords = InstEmitMemoryHelper.EmitReadInt(context, address, 1);
}
else
{
Operand address = context.Add(GetIntA32(context, op.Rn), GetIntA32(context, op.Rm));
halfwords = InstEmitMemoryHelper.EmitReadIntAligned(context, address, 0);
}
Operand targetAddress = context.Add(Const((int)op.GetPc()), context.ShiftLeft(halfwords, Const(1)));
EmitVirtualJump(context, targetAddress, isReturn: false);
}
} }
} }

View File

@ -204,15 +204,15 @@ namespace ARMeilleure.Instructions
context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag)); context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
Load(op.Rt, 0, WordSizeLog2); Load(op.Rt, 0, WordSizeLog2);
Load(op.Rt | 1, 4, WordSizeLog2); Load(op.Rt2, 4, WordSizeLog2);
context.Branch(lblEnd); context.Branch(lblEnd);
context.MarkLabel(lblBigEndian); context.MarkLabel(lblBigEndian);
Load(op.Rt | 1, 0, WordSizeLog2); Load(op.Rt2, 0, WordSizeLog2);
Load(op.Rt, 4, WordSizeLog2); Load(op.Rt, 4, WordSizeLog2);
context.MarkLabel(lblEnd); context.MarkLabel(lblEnd);
} }
@ -237,15 +237,15 @@ namespace ARMeilleure.Instructions
context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag)); context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
Store(op.Rt, 0, WordSizeLog2); Store(op.Rt, 0, WordSizeLog2);
Store(op.Rt | 1, 4, WordSizeLog2); Store(op.Rt2, 4, WordSizeLog2);
context.Branch(lblEnd); context.Branch(lblEnd);
context.MarkLabel(lblBigEndian); context.MarkLabel(lblBigEndian);
Store(op.Rt | 1, 0, WordSizeLog2); Store(op.Rt2, 0, WordSizeLog2);
Store(op.Rt, 4, WordSizeLog2); Store(op.Rt, 4, WordSizeLog2);
context.MarkLabel(lblEnd); context.MarkLabel(lblEnd);
} }

View File

@ -26,6 +26,11 @@ namespace ARMeilleure.Instructions
EmitClearExclusive(context); EmitClearExclusive(context);
} }
public static void Csdb(ArmEmitterContext context)
{
// Execute as no-op.
}
public static void Dmb(ArmEmitterContext context) => EmitBarrier(context); public static void Dmb(ArmEmitterContext context) => EmitBarrier(context);
public static void Dsb(ArmEmitterContext context) => EmitBarrier(context); public static void Dsb(ArmEmitterContext context) => EmitBarrier(context);

View File

@ -172,13 +172,13 @@ namespace ARMeilleure.Instructions
context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag)); context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
SetIntA32(context, op.Rt, valueLow); SetIntA32(context, op.Rt, valueLow);
SetIntA32(context, op.Rt | 1, valueHigh); SetIntA32(context, op.Rt2, valueHigh);
context.Branch(lblEnd); context.Branch(lblEnd);
context.MarkLabel(lblBigEndian); context.MarkLabel(lblBigEndian);
SetIntA32(context, op.Rt | 1, valueLow); SetIntA32(context, op.Rt2, valueLow);
SetIntA32(context, op.Rt, valueHigh); SetIntA32(context, op.Rt, valueHigh);
context.MarkLabel(lblEnd); context.MarkLabel(lblEnd);
@ -195,7 +195,7 @@ namespace ARMeilleure.Instructions
// Split the result into 2 words (based on endianness) // Split the result into 2 words (based on endianness)
Operand lo = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt)); Operand lo = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt));
Operand hi = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt | 1)); Operand hi = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt2));
Operand lblBigEndian = Label(); Operand lblBigEndian = Label();
Operand lblEnd = Label(); Operand lblEnd = Label();

View File

@ -123,6 +123,41 @@ namespace ARMeilleure.Instructions
context.CurrOp is OpCodeSimdMemSs); context.CurrOp is OpCodeSimdMemSs);
} }
public static Operand EmitReadInt(ArmEmitterContext context, Operand address, int size)
{
Operand temp = context.AllocateLocal(size == 3 ? OperandType.I64 : OperandType.I32);
Operand lblSlowPath = Label();
Operand lblEnd = Label();
Operand physAddr = EmitPtPointerLoad(context, address, lblSlowPath, write: false, size);
Operand value = default;
switch (size)
{
case 0: value = context.Load8 (physAddr); break;
case 1: value = context.Load16(physAddr); break;
case 2: value = context.Load (OperandType.I32, physAddr); break;
case 3: value = context.Load (OperandType.I64, physAddr); break;
}
context.Copy(temp, value);
if (!context.Memory.Type.IsHostMapped())
{
context.Branch(lblEnd);
context.MarkLabel(lblSlowPath, BasicBlockFrequency.Cold);
context.Copy(temp, EmitReadIntFallback(context, address, size));
context.MarkLabel(lblEnd);
}
return temp;
}
private static void EmitReadInt(ArmEmitterContext context, Operand address, int rt, int size) private static void EmitReadInt(ArmEmitterContext context, Operand address, int rt, int size)
{ {
Operand lblSlowPath = Label(); Operand lblSlowPath = Label();
@ -419,6 +454,11 @@ namespace ARMeilleure.Instructions
} }
private static void EmitReadIntFallback(ArmEmitterContext context, Operand address, int rt, int size) private static void EmitReadIntFallback(ArmEmitterContext context, Operand address, int rt, int size)
{
SetInt(context, rt, EmitReadIntFallback(context, address, size));
}
private static Operand EmitReadIntFallback(ArmEmitterContext context, Operand address, int size)
{ {
MethodInfo info = null; MethodInfo info = null;
@ -430,7 +470,7 @@ namespace ARMeilleure.Instructions
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)); break; case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)); break;
} }
SetInt(context, rt, context.Call(info, address)); return context.Call(info, address);
} }
private static void EmitReadVectorFallback( private static void EmitReadVectorFallback(

View File

@ -25,7 +25,7 @@ namespace ARMeilleure.Instructions
public static void Mla(ArmEmitterContext context) public static void Mla(ArmEmitterContext context)
{ {
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp; IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
Operand n = GetAluN(context); Operand n = GetAluN(context);
Operand m = GetAluM(context); Operand m = GetAluM(context);
@ -43,7 +43,7 @@ namespace ARMeilleure.Instructions
public static void Mls(ArmEmitterContext context) public static void Mls(ArmEmitterContext context)
{ {
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp; IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
Operand n = GetAluN(context); Operand n = GetAluN(context);
Operand m = GetAluM(context); Operand m = GetAluM(context);
@ -71,7 +71,7 @@ namespace ARMeilleure.Instructions
private static void EmitSmmul(ArmEmitterContext context, MullFlags flags) private static void EmitSmmul(ArmEmitterContext context, MullFlags flags)
{ {
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp; IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
Operand n = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rn)); Operand n = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rn));
Operand m = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rm)); Operand m = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rm));
@ -99,7 +99,7 @@ namespace ARMeilleure.Instructions
public static void Smla__(ArmEmitterContext context) public static void Smla__(ArmEmitterContext context)
{ {
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp; IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
Operand n = GetIntA32(context, op.Rn); Operand n = GetIntA32(context, op.Rn);
Operand m = GetIntA32(context, op.Rm); Operand m = GetIntA32(context, op.Rm);
@ -142,7 +142,7 @@ namespace ARMeilleure.Instructions
public static void Smlal__(ArmEmitterContext context) public static void Smlal__(ArmEmitterContext context)
{ {
OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp; IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
Operand n = GetIntA32(context, op.Rn); Operand n = GetIntA32(context, op.Rn);
Operand m = GetIntA32(context, op.Rm); Operand m = GetIntA32(context, op.Rm);
@ -180,7 +180,7 @@ namespace ARMeilleure.Instructions
public static void Smlaw_(ArmEmitterContext context) public static void Smlaw_(ArmEmitterContext context)
{ {
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp; IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
Operand n = GetIntA32(context, op.Rn); Operand n = GetIntA32(context, op.Rn);
Operand m = GetIntA32(context, op.Rm); Operand m = GetIntA32(context, op.Rm);
@ -210,7 +210,7 @@ namespace ARMeilleure.Instructions
public static void Smul__(ArmEmitterContext context) public static void Smul__(ArmEmitterContext context)
{ {
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp; IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
Operand n = GetIntA32(context, op.Rn); Operand n = GetIntA32(context, op.Rn);
Operand m = GetIntA32(context, op.Rm); Operand m = GetIntA32(context, op.Rm);
@ -240,7 +240,7 @@ namespace ARMeilleure.Instructions
public static void Smull(ArmEmitterContext context) public static void Smull(ArmEmitterContext context)
{ {
OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp; IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
Operand n = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rn)); Operand n = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rn));
Operand m = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rm)); Operand m = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rm));
@ -261,7 +261,7 @@ namespace ARMeilleure.Instructions
public static void Smulw_(ArmEmitterContext context) public static void Smulw_(ArmEmitterContext context)
{ {
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp; IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
Operand n = GetIntA32(context, op.Rn); Operand n = GetIntA32(context, op.Rn);
Operand m = GetIntA32(context, op.Rm); Operand m = GetIntA32(context, op.Rm);
@ -285,7 +285,7 @@ namespace ARMeilleure.Instructions
public static void Umaal(ArmEmitterContext context) public static void Umaal(ArmEmitterContext context)
{ {
OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp; IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
Operand n = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rn)); Operand n = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rn));
Operand m = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rm)); Operand m = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rm));
@ -310,7 +310,7 @@ namespace ARMeilleure.Instructions
public static void Umull(ArmEmitterContext context) public static void Umull(ArmEmitterContext context)
{ {
OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp; IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
Operand n = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rn)); Operand n = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rn));
Operand m = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rm)); Operand m = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rm));
@ -331,7 +331,7 @@ namespace ARMeilleure.Instructions
private static void EmitMlal(ArmEmitterContext context, bool signed) private static void EmitMlal(ArmEmitterContext context, bool signed)
{ {
OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp; IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
Operand n = GetIntA32(context, op.Rn); Operand n = GetIntA32(context, op.Rn);
Operand m = GetIntA32(context, op.Rm); Operand m = GetIntA32(context, op.Rm);

View File

@ -777,6 +777,13 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Vmlal_I(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
EmitVectorTernaryLongOpI32(context, (d, n, m) => context.Add(d, context.Multiply(n, m)), !op.U);
}
public static void Vmls_S(ArmEmitterContext context) public static void Vmls_S(ArmEmitterContext context)
{ {
if (Optimizations.FastFP && Optimizations.UseSse2) if (Optimizations.FastFP && Optimizations.UseSse2)
@ -992,6 +999,13 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Vpaddl(ArmEmitterContext context)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
EmitVectorPairwiseLongOpI32(context, (op1, op2) => context.Add(op1, op2), (op.Opc & 1) == 0);
}
public static void Vpmax_V(ArmEmitterContext context) public static void Vpmax_V(ArmEmitterContext context)
{ {
if (Optimizations.FastFP && Optimizations.UseSse2) if (Optimizations.FastFP && Optimizations.UseSse2)
@ -1014,7 +1028,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitVectorPairwiseOpI32(context, (op1, op2) => EmitVectorPairwiseOpI32(context, (op1, op2) =>
{ {
Operand greater = op.U ? context.ICompareGreaterUI(op1, op2) : context.ICompareGreater(op1, op2); Operand greater = op.U ? context.ICompareGreaterUI(op1, op2) : context.ICompareGreater(op1, op2);
return context.ConditionalSelect(greater, op1, op2); return context.ConditionalSelect(greater, op1, op2);
@ -1052,6 +1066,62 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Vqadd(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
EmitSaturatingAddSubBinaryOp(context, add: true, !op.U);
}
public static void Vqdmulh(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
int eSize = 8 << op.Size;
EmitVectorBinaryOpI32(context, (op1, op2) =>
{
if (op.Size == 2)
{
op1 = context.SignExtend32(OperandType.I64, op1);
op2 = context.SignExtend32(OperandType.I64, op2);
}
Operand res = context.Multiply(op1, op2);
res = context.ShiftRightSI(res, Const(eSize - 1));
res = EmitSatQ(context, res, eSize, signedSrc: true, signedDst: true);
if (op.Size == 2)
{
res = context.ConvertI64ToI32(res);
}
return res;
}, signed: true);
}
public static void Vqmovn(ArmEmitterContext context)
{
OpCode32SimdMovn op = (OpCode32SimdMovn)context.CurrOp;
bool signed = !op.Q;
EmitVectorUnaryNarrowOp32(context, (op1) => EmitSatQ(context, op1, 8 << op.Size, signed, signed), signed);
}
public static void Vqmovun(ArmEmitterContext context)
{
OpCode32SimdMovn op = (OpCode32SimdMovn)context.CurrOp;
EmitVectorUnaryNarrowOp32(context, (op1) => EmitSatQ(context, op1, 8 << op.Size, signedSrc: true, signedDst: false), signed: true);
}
public static void Vqsub(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
EmitSaturatingAddSubBinaryOp(context, add: false, !op.U);
}
public static void Vrev(ArmEmitterContext context) public static void Vrev(ArmEmitterContext context)
{ {
OpCode32SimdRev op = (OpCode32SimdRev)context.CurrOp; OpCode32SimdRev op = (OpCode32SimdRev)context.CurrOp;
@ -1202,6 +1272,30 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Vrhadd(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
EmitVectorBinaryOpI32(context, (op1, op2) =>
{
if (op.Size == 2)
{
op1 = context.ZeroExtend32(OperandType.I64, op1);
op2 = context.ZeroExtend32(OperandType.I64, op2);
}
Operand res = context.Add(context.Add(op1, op2), Const(op1.Type, 1L));
res = context.ShiftRightUI(res, Const(1));
if (op.Size == 2)
{
res = context.ConvertI64ToI32(res);
}
return res;
}, !op.U);
}
public static void Vrsqrte(ArmEmitterContext context) public static void Vrsqrte(ArmEmitterContext context)
{ {
OpCode32SimdSqrte op = (OpCode32SimdSqrte)context.CurrOp; OpCode32SimdSqrte op = (OpCode32SimdSqrte)context.CurrOp;
@ -1349,6 +1443,13 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Vsubl_I(ArmEmitterContext context)
{
OpCode32SimdRegLong op = (OpCode32SimdRegLong)context.CurrOp;
EmitVectorBinaryLongOpI32(context, (op1, op2) => context.Subtract(op1, op2), !op.U);
}
public static void Vsubw_I(ArmEmitterContext context) public static void Vsubw_I(ArmEmitterContext context)
{ {
OpCode32SimdRegWide op = (OpCode32SimdRegWide)context.CurrOp; OpCode32SimdRegWide op = (OpCode32SimdRegWide)context.CurrOp;
@ -1356,6 +1457,46 @@ namespace ARMeilleure.Instructions
EmitVectorBinaryWideOpI32(context, (op1, op2) => context.Subtract(op1, op2), !op.U); EmitVectorBinaryWideOpI32(context, (op1, op2) => context.Subtract(op1, op2), !op.U);
} }
private static void EmitSaturatingAddSubBinaryOp(ArmEmitterContext context, bool add, bool signed)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
EmitVectorBinaryOpI32(context, (ne, me) =>
{
if (op.Size <= 2)
{
if (op.Size == 2)
{
ne = signed ? context.SignExtend32(OperandType.I64, ne) : context.ZeroExtend32(OperandType.I64, ne);
me = signed ? context.SignExtend32(OperandType.I64, me) : context.ZeroExtend32(OperandType.I64, me);
}
Operand res = add ? context.Add(ne, me) : context.Subtract(ne, me);
res = EmitSatQ(context, res, 8 << op.Size, signedSrc: true, signed);
if (op.Size == 2)
{
res = context.ConvertI64ToI32(res);
}
return res;
}
else if (add) /* if (op.Size == 3) */
{
return signed
? EmitBinarySignedSatQAdd(context, ne, me)
: EmitBinaryUnsignedSatQAdd(context, ne, me);
}
else /* if (sub) */
{
return signed
? EmitBinarySignedSatQSub(context, ne, me)
: EmitBinaryUnsignedSatQSub(context, ne, me);
}
}, signed);
}
private static void EmitSse41MaxMinNumOpF32(ArmEmitterContext context, bool isMaxNum, bool scalar) private static void EmitSse41MaxMinNumOpF32(ArmEmitterContext context, bool isMaxNum, bool scalar)
{ {
IOpCode32Simd op = (IOpCode32Simd)context.CurrOp; IOpCode32Simd op = (IOpCode32Simd)context.CurrOp;

View File

@ -323,6 +323,60 @@ namespace ARMeilleure.Instructions
} }
} }
// VRINTA (vector).
public static void Vrinta_V(ArmEmitterContext context)
{
EmitVectorUnaryOpF32(context, (m) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, m));
}
// VRINTM (vector).
public static void Vrintm_V(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
EmitVectorUnaryOpSimd32(context, (m) =>
{
return context.AddIntrinsic(Intrinsic.X86Roundps, m, Const(X86GetRoundControl(FPRoundingMode.TowardsMinusInfinity)));
});
}
else
{
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(Math.Floor), m));
}
}
// VRINTN (vector).
public static void Vrintn_V(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
EmitVectorUnaryOpSimd32(context, (m) =>
{
return context.AddIntrinsic(Intrinsic.X86Roundps, m, Const(X86GetRoundControl(FPRoundingMode.ToNearest)));
});
}
else
{
EmitVectorUnaryOpF32(context, (m) => EmitRoundMathCall(context, MidpointRounding.ToEven, m));
}
}
// VRINTP (vector).
public static void Vrintp_V(ArmEmitterContext context)
{
if (Optimizations.UseSse2)
{
EmitVectorUnaryOpSimd32(context, (m) =>
{
return context.AddIntrinsic(Intrinsic.X86Roundps, m, Const(X86GetRoundControl(FPRoundingMode.TowardsPlusInfinity)));
});
}
else
{
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(Math.Ceiling), m));
}
}
// VRINTZ (floating-point). // VRINTZ (floating-point).
public static void Vrint_Z(ArmEmitterContext context) public static void Vrint_Z(ArmEmitterContext context)
{ {

View File

@ -1281,7 +1281,7 @@ namespace ARMeilleure.Instructions
public static void EmitSseOrAvxExitFtzAndDazModesOpF(ArmEmitterContext context, Operand isTrue = default) public static void EmitSseOrAvxExitFtzAndDazModesOpF(ArmEmitterContext context, Operand isTrue = default)
{ {
isTrue = isTrue == default isTrue = isTrue == default
? context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz))) ? context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)))
: isTrue; : isTrue;
@ -1352,7 +1352,7 @@ namespace ARMeilleure.Instructions
if (op.Size <= 2) if (op.Size <= 2)
{ {
de = EmitSatQ(context, emit(ne), op.Size, signedSrc: true, signedDst: true); de = EmitSignedSrcSatQ(context, emit(ne), op.Size, signedDst: true);
} }
else /* if (op.Size == 3) */ else /* if (op.Size == 3) */
{ {
@ -1419,15 +1419,18 @@ namespace ARMeilleure.Instructions
{ {
Operand temp = add ? context.Add(ne, me) : context.Subtract(ne, me); Operand temp = add ? context.Add(ne, me) : context.Subtract(ne, me);
de = EmitSatQ(context, temp, op.Size, signedSrc: true, signedDst: signed); de = EmitSignedSrcSatQ(context, temp, op.Size, signedDst: signed);
} }
else if (add) /* if (op.Size == 3) */ else /* if (op.Size == 3) */
{ {
de = EmitBinarySatQAdd(context, ne, me, signed); if (add)
} {
else /* if (sub) */ de = signed ? EmitBinarySignedSatQAdd(context, ne, me) : EmitBinaryUnsignedSatQAdd(context, ne, me);
{ }
de = EmitBinarySatQSub(context, ne, me, signed); else /* if (sub) */
{
de = signed ? EmitBinarySignedSatQSub(context, ne, me) : EmitBinaryUnsignedSatQSub(context, ne, me);
}
} }
res = EmitVectorInsert(context, res, de, index, op.Size); res = EmitVectorInsert(context, res, de, index, op.Size);
@ -1445,11 +1448,11 @@ namespace ARMeilleure.Instructions
{ {
Operand temp = context.Add(ne, me); Operand temp = context.Add(ne, me);
de = EmitSatQ(context, temp, op.Size, signedSrc: true, signedDst: signed); de = EmitSignedSrcSatQ(context, temp, op.Size, signedDst: signed);
} }
else /* if (op.Size == 3) */ else /* if (op.Size == 3) */
{ {
de = EmitBinarySatQAccumulate(context, ne, me, signed); de = signed ? EmitBinarySignedSatQAcc(context, ne, me) : EmitBinaryUnsignedSatQAcc(context, ne, me);
} }
res = EmitVectorInsert(context, res, de, index, op.Size); res = EmitVectorInsert(context, res, de, index, op.Size);
@ -1475,7 +1478,7 @@ namespace ARMeilleure.Instructions
me = EmitVectorExtract(context, ((OpCodeSimdReg)op).Rm, index, op.Size, signed); me = EmitVectorExtract(context, ((OpCodeSimdReg)op).Rm, index, op.Size, signed);
} }
Operand de = EmitSatQ(context, emit(ne, me), op.Size, true, signed); Operand de = EmitSignedSrcSatQ(context, emit(ne, me), op.Size, signedDst: signed);
res = EmitVectorInsert(context, res, de, index, op.Size); res = EmitVectorInsert(context, res, de, index, op.Size);
} }
@ -1520,7 +1523,9 @@ namespace ARMeilleure.Instructions
{ {
Operand ne = EmitVectorExtract(context, op.Rn, index, op.Size + 1, signedSrc); Operand ne = EmitVectorExtract(context, op.Rn, index, op.Size + 1, signedSrc);
Operand temp = EmitSatQ(context, ne, op.Size, signedSrc, signedDst); Operand temp = signedSrc
? EmitSignedSrcSatQ(context, ne, op.Size, signedDst)
: EmitUnsignedSrcSatQ(context, ne, op.Size, signedDst);
res = EmitVectorInsert(context, res, temp, part + index, op.Size); res = EmitVectorInsert(context, res, temp, part + index, op.Size);
} }
@ -1528,74 +1533,314 @@ namespace ARMeilleure.Instructions
context.Copy(d, res); context.Copy(d, res);
} }
// TSrc (16bit, 32bit, 64bit; signed, unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned). // long SignedSignSatQ(long op, int size);
public static Operand EmitSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedSrc, bool signedDst) public static Operand EmitSignedSignSatQ(ArmEmitterContext context, Operand op, int size)
{ {
if ((uint)sizeDst > 2u) int eSize = 8 << size;
{
throw new ArgumentOutOfRangeException(nameof(sizeDst));
}
MethodInfo info; Debug.Assert(op.Type == OperandType.I64);
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
if (signedSrc) Operand lbl1 = Label();
{ Operand lblEnd = Label();
info = signedDst
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedSrcSignedDstSatQ))
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedSrcUnsignedDstSatQ));
}
else
{
info = signedDst
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedSrcSignedDstSatQ))
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedSrcUnsignedDstSatQ));
}
return context.Call(info, op, Const(sizeDst)); Operand zeroL = Const(0L);
Operand maxT = Const((1L << (eSize - 1)) - 1L);
Operand minT = Const(-(1L << (eSize - 1)));
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroL);
context.BranchIf(lbl1, op, zeroL, Comparison.LessOrEqual);
context.Copy(res, maxT);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lbl1);
context.BranchIf(lblEnd, op, zeroL, Comparison.GreaterOrEqual);
context.Copy(res, minT);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
} }
// TSrc (64bit) == TDst (64bit); signed. // private static ulong UnsignedSignSatQ(ulong op, int size);
public static Operand EmitUnarySignedSatQAbsOrNeg(ArmEmitterContext context, Operand op) public static Operand EmitUnsignedSignSatQ(ArmEmitterContext context, Operand op, int size)
{ {
Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size."); int eSize = 8 << size;
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnarySignedSatQAbsOrNeg)), op); Debug.Assert(op.Type == OperandType.I64);
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
Operand lblEnd = Label();
Operand zeroUL = Const(0UL);
Operand maxT = Const(ulong.MaxValue >> (64 - eSize));
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroUL);
context.BranchIf(lblEnd, op, zeroUL, Comparison.LessOrEqualUI);
context.Copy(res, maxT);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
} }
// TSrcs (64bit) == TDst (64bit); signed, unsigned. // TSrc (16bit, 32bit, 64bit; signed) > TDst (8bit, 16bit, 32bit; signed, unsigned).
public static Operand EmitBinarySatQAdd(ArmEmitterContext context, Operand op1, Operand op2, bool signed) // long SignedSrcSignedDstSatQ(long op, int size); ulong SignedSrcUnsignedDstSatQ(long op, int size);
public static Operand EmitSignedSrcSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedDst)
{ {
Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size."); int eSizeDst = 8 << sizeDst;
MethodInfo info = signed Debug.Assert(op.Type == OperandType.I64);
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQAdd)) Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32);
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQAdd));
return context.Call(info, op1, op2); Operand lbl1 = Label();
Operand lblEnd = Label();
Operand maxT = signedDst ? Const((1L << (eSizeDst - 1)) - 1L) : Const((1UL << eSizeDst) - 1UL);
Operand minT = signedDst ? Const(-(1L << (eSizeDst - 1))) : Const(0UL);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
context.BranchIf(lbl1, op, maxT, Comparison.LessOrEqual);
context.Copy(res, maxT);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lbl1);
context.BranchIf(lblEnd, op, minT, Comparison.GreaterOrEqual);
context.Copy(res, minT);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
} }
// TSrcs (64bit) == TDst (64bit); signed, unsigned. // TSrc (16bit, 32bit, 64bit; unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned).
public static Operand EmitBinarySatQSub(ArmEmitterContext context, Operand op1, Operand op2, bool signed) // long UnsignedSrcSignedDstSatQ(ulong op, int size); ulong UnsignedSrcUnsignedDstSatQ(ulong op, int size);
public static Operand EmitUnsignedSrcSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedDst)
{ {
Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size."); int eSizeDst = 8 << sizeDst;
MethodInfo info = signed Debug.Assert(op.Type == OperandType.I64);
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQSub)) Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32);
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQSub));
return context.Call(info, op1, op2); Operand lblEnd = Label();
Operand maxT = signedDst ? Const((1L << (eSizeDst - 1)) - 1L) : Const((1UL << eSizeDst) - 1UL);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
context.BranchIf(lblEnd, op, maxT, Comparison.LessOrEqualUI);
context.Copy(res, maxT);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
} }
// TSrcs (64bit) == TDst (64bit); signed, unsigned. // long UnarySignedSatQAbsOrNeg(long op);
public static Operand EmitBinarySatQAccumulate(ArmEmitterContext context, Operand op1, Operand op2, bool signed) private static Operand EmitUnarySignedSatQAbsOrNeg(ArmEmitterContext context, Operand op)
{ {
Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size."); Debug.Assert(op.Type == OperandType.I64);
MethodInfo info = signed Operand lblEnd = Label();
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQAcc))
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQAcc));
return context.Call(info, op1, op2); Operand minL = Const(long.MinValue);
Operand maxL = Const(long.MaxValue);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
context.BranchIf(lblEnd, op, minL, Comparison.NotEqual);
context.Copy(res, maxL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
}
// long BinarySignedSatQAdd(long op1, long op2);
public static Operand EmitBinarySignedSatQAdd(ArmEmitterContext context, Operand op1, Operand op2)
{
Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64);
Operand lblEnd = Label();
Operand minL = Const(long.MinValue);
Operand maxL = Const(long.MaxValue);
Operand zeroL = Const(0L);
Operand add = context.Add(op1, op2);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
Operand left = context.BitwiseNot(context.BitwiseExclusiveOr(op1, op2));
Operand right = context.BitwiseExclusiveOr(op1, add);
context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zeroL, Comparison.GreaterOrEqual);
Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
}
// ulong BinaryUnsignedSatQAdd(ulong op1, ulong op2);
public static Operand EmitBinaryUnsignedSatQAdd(ArmEmitterContext context, Operand op1, Operand op2)
{
Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64);
Operand lblEnd = Label();
Operand maxUL = Const(ulong.MaxValue);
Operand add = context.Add(op1, op2);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
context.Copy(res, maxUL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
}
// long BinarySignedSatQSub(long op1, long op2);
public static Operand EmitBinarySignedSatQSub(ArmEmitterContext context, Operand op1, Operand op2)
{
Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64);
Operand lblEnd = Label();
Operand minL = Const(long.MinValue);
Operand maxL = Const(long.MaxValue);
Operand zeroL = Const(0L);
Operand sub = context.Subtract(op1, op2);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), sub);
Operand left = context.BitwiseExclusiveOr(op1, op2);
Operand right = context.BitwiseExclusiveOr(op1, sub);
context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zeroL, Comparison.GreaterOrEqual);
Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
}
// ulong BinaryUnsignedSatQSub(ulong op1, ulong op2);
public static Operand EmitBinaryUnsignedSatQSub(ArmEmitterContext context, Operand op1, Operand op2)
{
Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64);
Operand lblEnd = Label();
Operand zeroL = Const(0L);
Operand sub = context.Subtract(op1, op2);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), sub);
context.BranchIf(lblEnd, op1, op2, Comparison.GreaterOrEqualUI);
context.Copy(res, zeroL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
}
// long BinarySignedSatQAcc(ulong op1, long op2);
private static Operand EmitBinarySignedSatQAcc(ArmEmitterContext context, Operand op1, Operand op2)
{
Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64);
Operand lbl1 = Label();
Operand lbl2 = Label();
Operand lblEnd = Label();
Operand maxL = Const(long.MaxValue);
Operand zeroL = Const(0L);
Operand add = context.Add(op1, op2);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
context.BranchIf(lbl1, op1, maxL, Comparison.GreaterUI);
Operand notOp2AndRes = context.BitwiseAnd(context.BitwiseNot(op2), add);
context.BranchIf(lblEnd, notOp2AndRes, zeroL, Comparison.GreaterOrEqual);
context.Copy(res, maxL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lbl1);
context.BranchIf(lbl2, op2, zeroL, Comparison.Less);
context.Copy(res, maxL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lbl2);
context.BranchIf(lblEnd, add, maxL, Comparison.LessOrEqualUI);
context.Copy(res, maxL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
}
// ulong BinaryUnsignedSatQAcc(long op1, ulong op2);
private static Operand EmitBinaryUnsignedSatQAcc(ArmEmitterContext context, Operand op1, Operand op2)
{
Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64);
Operand lbl1 = Label();
Operand lblEnd = Label();
Operand maxUL = Const(ulong.MaxValue);
Operand maxL = Const(long.MaxValue);
Operand zeroL = Const(0L);
Operand add = context.Add(op1, op2);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
context.BranchIf(lbl1, op1, zeroL, Comparison.Less);
context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
context.Copy(res, maxUL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lbl1);
context.BranchIf(lblEnd, op2, maxL, Comparison.GreaterUI);
context.BranchIf(lblEnd, add, zeroL, Comparison.GreaterOrEqual);
context.Copy(res, zeroL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
} }
public static Operand EmitFloatAbs(ArmEmitterContext context, Operand value, bool single, bool vector) public static Operand EmitFloatAbs(ArmEmitterContext context, Operand value, bool single, bool vector)

View File

@ -219,6 +219,25 @@ namespace ARMeilleure.Instructions
// Integer // Integer
public static void EmitVectorUnaryAccumulateOpI32(ArmEmitterContext context, Func1I emit, bool signed)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
Operand res = GetVecA32(op.Qd);
int elems = op.GetBytesCount() >> op.Size;
for (int index = 0; index < elems; index++)
{
Operand de = EmitVectorExtract32(context, op.Qd, op.Id + index, op.Size, signed);
Operand me = EmitVectorExtract32(context, op.Qm, op.Im + index, op.Size, signed);
res = EmitVectorInsert(context, res, context.Add(de, emit(me)), op.Id + index, op.Size);
}
context.Copy(GetVecA32(op.Qd), res);
}
public static void EmitVectorUnaryOpI32(ArmEmitterContext context, Func1I emit, bool signed) public static void EmitVectorUnaryOpI32(ArmEmitterContext context, Func1I emit, bool signed)
{ {
OpCode32Simd op = (OpCode32Simd)context.CurrOp; OpCode32Simd op = (OpCode32Simd)context.CurrOp;
@ -385,6 +404,18 @@ namespace ARMeilleure.Instructions
EmitVectorUnaryOpI32(context, emit, true); EmitVectorUnaryOpI32(context, emit, true);
} }
public static void EmitVectorUnaryOpSx32(ArmEmitterContext context, Func1I emit, bool accumulate)
{
if (accumulate)
{
EmitVectorUnaryAccumulateOpI32(context, emit, true);
}
else
{
EmitVectorUnaryOpI32(context, emit, true);
}
}
public static void EmitVectorBinaryOpSx32(ArmEmitterContext context, Func2I emit) public static void EmitVectorBinaryOpSx32(ArmEmitterContext context, Func2I emit)
{ {
EmitVectorBinaryOpI32(context, emit, true); EmitVectorBinaryOpI32(context, emit, true);
@ -400,6 +431,18 @@ namespace ARMeilleure.Instructions
EmitVectorUnaryOpI32(context, emit, false); EmitVectorUnaryOpI32(context, emit, false);
} }
public static void EmitVectorUnaryOpZx32(ArmEmitterContext context, Func1I emit, bool accumulate)
{
if (accumulate)
{
EmitVectorUnaryAccumulateOpI32(context, emit, false);
}
else
{
EmitVectorUnaryOpI32(context, emit, false);
}
}
public static void EmitVectorBinaryOpZx32(ArmEmitterContext context, Func2I emit) public static void EmitVectorBinaryOpZx32(ArmEmitterContext context, Func2I emit)
{ {
EmitVectorBinaryOpI32(context, emit, false); EmitVectorBinaryOpI32(context, emit, false);
@ -592,6 +635,34 @@ namespace ARMeilleure.Instructions
context.Copy(GetVecA32(op.Qd), res); context.Copy(GetVecA32(op.Qd), res);
} }
public static void EmitVectorPairwiseLongOpI32(ArmEmitterContext context, Func2I emit, bool signed)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
int elems = (op.Q ? 16 : 8) >> op.Size;
int pairs = elems >> 1;
int id = (op.Vd & 1) * pairs;
Operand res = GetVecA32(op.Qd);
for (int index = 0; index < pairs; index++)
{
int pairIndex = index << 1;
Operand m1 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex, op.Size, signed);
Operand m2 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex + 1, op.Size, signed);
if (op.Size == 2)
{
m1 = signed ? context.SignExtend32(OperandType.I64, m1) : context.ZeroExtend32(OperandType.I64, m1);
m2 = signed ? context.SignExtend32(OperandType.I64, m2) : context.ZeroExtend32(OperandType.I64, m2);
}
res = EmitVectorInsert(context, res, emit(m1, m2), id + index, op.Size + 1);
}
context.Copy(GetVecA32(op.Qd), res);
}
// Narrow // Narrow
public static void EmitVectorUnaryNarrowOp32(ArmEmitterContext context, Func1I emit, bool signed = false) public static void EmitVectorUnaryNarrowOp32(ArmEmitterContext context, Func1I emit, bool signed = false)

View File

@ -67,7 +67,7 @@ namespace ARMeilleure.Instructions
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
// Write an element from a double simd register. // Accesses an element from a double simd register.
Operand address = context.Add(n, Const(offset)); Operand address = context.Add(n, Const(offset));
if (eBytes == 8) if (eBytes == 8)
{ {
@ -131,6 +131,7 @@ namespace ARMeilleure.Instructions
{ {
OpCode32SimdMemPair op = (OpCode32SimdMemPair)context.CurrOp; OpCode32SimdMemPair op = (OpCode32SimdMemPair)context.CurrOp;
int increment = count > 1 ? op.Increment : 1;
int eBytes = 1 << op.Size; int eBytes = 1 << op.Size;
Operand n = context.Copy(GetIntA32(context, op.Rn)); Operand n = context.Copy(GetIntA32(context, op.Rn));
@ -144,7 +145,7 @@ namespace ARMeilleure.Instructions
int elemD = d + reg; int elemD = d + reg;
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
// Write an element from a double simd register // Accesses an element from a double simd register,
// add ebytes for each element. // add ebytes for each element.
Operand address = context.Add(n, Const(offset)); Operand address = context.Add(n, Const(offset));
int index = ((elemD & 1) << (3 - op.Size)) + elem; int index = ((elemD & 1) << (3 - op.Size)) + elem;
@ -161,7 +162,6 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
if (load) if (load)
{ {
EmitLoadSimd(context, address, GetVecA32(elemD >> 1), elemD >> 1, index, op.Size); EmitLoadSimd(context, address, GetVecA32(elemD >> 1), elemD >> 1, index, op.Size);
@ -173,7 +173,7 @@ namespace ARMeilleure.Instructions
} }
offset += eBytes; offset += eBytes;
elemD += op.Increment; elemD += increment;
} }
} }
} }

View File

@ -188,23 +188,7 @@ namespace ARMeilleure.Instructions
public static void Sqrshl_V(ArmEmitterContext context) public static void Sqrshl_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Round | ShlRegFlags.Saturating);
Operand res = context.VectorZero();
int elems = op.GetBytesCount() >> op.Size;
for (int index = 0; index < elems; index++)
{
Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)), ne, me, Const(1), Const(op.Size));
res = EmitVectorInsert(context, res, e, index, op.Size);
}
context.Copy(GetVec(op.Rd), res);
} }
public static void Sqrshrn_S(ArmEmitterContext context) public static void Sqrshrn_S(ArmEmitterContext context)
@ -229,23 +213,7 @@ namespace ARMeilleure.Instructions
public static void Sqshl_V(ArmEmitterContext context) public static void Sqshl_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Saturating);
Operand res = context.VectorZero();
int elems = op.GetBytesCount() >> op.Size;
for (int index = 0; index < elems; index++)
{
Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)), ne, me, Const(0), Const(op.Size));
res = EmitVectorInsert(context, res, e, index, op.Size);
}
context.Copy(GetVec(op.Rd), res);
} }
public static void Sqshrn_S(ArmEmitterContext context) public static void Sqshrn_S(ArmEmitterContext context)
@ -280,23 +248,7 @@ namespace ARMeilleure.Instructions
public static void Srshl_V(ArmEmitterContext context) public static void Srshl_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Round);
Operand res = context.VectorZero();
int elems = op.GetBytesCount() >> op.Size;
for (int index = 0; index < elems; index++)
{
Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlReg)), ne, me, Const(1), Const(op.Size));
res = EmitVectorInsert(context, res, e, index, op.Size);
}
context.Copy(GetVec(op.Rd), res);
} }
public static void Srshr_S(ArmEmitterContext context) public static void Srshr_S(ArmEmitterContext context)
@ -393,12 +345,12 @@ namespace ARMeilleure.Instructions
public static void Sshl_S(ArmEmitterContext context) public static void Sshl_S(ArmEmitterContext context)
{ {
EmitSshlOrUshl(context, signed: true, scalar: true); EmitShlRegOp(context, ShlRegFlags.Scalar | ShlRegFlags.Signed);
} }
public static void Sshl_V(ArmEmitterContext context) public static void Sshl_V(ArmEmitterContext context)
{ {
EmitSshlOrUshl(context, signed: true, scalar: false); EmitShlRegOp(context, ShlRegFlags.Signed);
} }
public static void Sshll_V(ArmEmitterContext context) public static void Sshll_V(ArmEmitterContext context)
@ -506,23 +458,7 @@ namespace ARMeilleure.Instructions
public static void Uqrshl_V(ArmEmitterContext context) public static void Uqrshl_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; EmitShlRegOp(context, ShlRegFlags.Round | ShlRegFlags.Saturating);
Operand res = context.VectorZero();
int elems = op.GetBytesCount() >> op.Size;
for (int index = 0; index < elems; index++)
{
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)), ne, me, Const(1), Const(op.Size));
res = EmitVectorInsert(context, res, e, index, op.Size);
}
context.Copy(GetVec(op.Rd), res);
} }
public static void Uqrshrn_S(ArmEmitterContext context) public static void Uqrshrn_S(ArmEmitterContext context)
@ -537,23 +473,7 @@ namespace ARMeilleure.Instructions
public static void Uqshl_V(ArmEmitterContext context) public static void Uqshl_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; EmitShlRegOp(context, ShlRegFlags.Saturating);
Operand res = context.VectorZero();
int elems = op.GetBytesCount() >> op.Size;
for (int index = 0; index < elems; index++)
{
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)), ne, me, Const(0), Const(op.Size));
res = EmitVectorInsert(context, res, e, index, op.Size);
}
context.Copy(GetVec(op.Rd), res);
} }
public static void Uqshrn_S(ArmEmitterContext context) public static void Uqshrn_S(ArmEmitterContext context)
@ -568,23 +488,7 @@ namespace ARMeilleure.Instructions
public static void Urshl_V(ArmEmitterContext context) public static void Urshl_V(ArmEmitterContext context)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; EmitShlRegOp(context, ShlRegFlags.Round);
Operand res = context.VectorZero();
int elems = op.GetBytesCount() >> op.Size;
for (int index = 0; index < elems; index++)
{
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlReg)), ne, me, Const(1), Const(op.Size));
res = EmitVectorInsert(context, res, e, index, op.Size);
}
context.Copy(GetVec(op.Rd), res);
} }
public static void Urshr_S(ArmEmitterContext context) public static void Urshr_S(ArmEmitterContext context)
@ -677,12 +581,12 @@ namespace ARMeilleure.Instructions
public static void Ushl_S(ArmEmitterContext context) public static void Ushl_S(ArmEmitterContext context)
{ {
EmitSshlOrUshl(context, signed: false, scalar: true); EmitShlRegOp(context, ShlRegFlags.Scalar);
} }
public static void Ushl_V(ArmEmitterContext context) public static void Ushl_V(ArmEmitterContext context)
{ {
EmitSshlOrUshl(context, signed: false, scalar: false); EmitShlRegOp(context, ShlRegFlags.None);
} }
public static void Ushll_V(ArmEmitterContext context) public static void Ushll_V(ArmEmitterContext context)
@ -872,43 +776,6 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
private static Operand EmitShlRegOp(ArmEmitterContext context, Operand op, Operand shiftLsB, int size, bool signed)
{
Debug.Assert(op.Type == OperandType.I64);
Debug.Assert(shiftLsB.Type == OperandType.I32);
Debug.Assert((uint)size < 4u);
Operand negShiftLsB = context.Negate(shiftLsB);
Operand isInRange = context.BitwiseAnd(
context.ICompareLess(shiftLsB, Const(8 << size)),
context.ICompareLess(negShiftLsB, Const(8 << size)));
Operand isPositive = context.ICompareGreaterOrEqual(shiftLsB, Const(0));
Operand shl = context.ShiftLeft(op, shiftLsB);
Operand sarOrShr = signed
? context.ShiftRightSI(op, negShiftLsB)
: context.ShiftRightUI(op, negShiftLsB);
Operand res = context.ConditionalSelect(isPositive, shl, sarOrShr);
if (signed)
{
Operand isPositive2 = context.ICompareGreaterOrEqual(op, Const(0L));
Operand res2 = context.ConditionalSelect(isPositive2, Const(0L), Const(-1L));
res2 = context.ConditionalSelect(isPositive, Const(0L), res2);
return context.ConditionalSelect(isInRange, res, res2);
}
else
{
return context.ConditionalSelect(isInRange, res, Const(0UL));
}
}
private static void EmitVectorShrImmNarrowOpZx(ArmEmitterContext context, bool round) private static void EmitVectorShrImmNarrowOpZx(ArmEmitterContext context, bool round)
{ {
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@ -1004,7 +871,7 @@ namespace ARMeilleure.Instructions
e = EmitShrImm64(context, e, signedSrc, roundConst, shift); // shift <= 32 e = EmitShrImm64(context, e, signedSrc, roundConst, shift); // shift <= 32
} }
e = EmitSatQ(context, e, op.Size, signedSrc, signedDst); e = signedSrc ? EmitSignedSrcSatQ(context, e, op.Size, signedDst) : EmitUnsignedSrcSatQ(context, e, op.Size, signedDst);
res = EmitVectorInsert(context, res, e, part + index, op.Size); res = EmitVectorInsert(context, res, e, part + index, op.Size);
} }
@ -1168,8 +1035,23 @@ namespace ARMeilleure.Instructions
} }
} }
private static void EmitSshlOrUshl(ArmEmitterContext context, bool signed, bool scalar) [Flags]
private enum ShlRegFlags
{ {
None = 0,
Scalar = 1 << 0,
Signed = 1 << 1,
Round = 1 << 2,
Saturating = 1 << 3
}
private static void EmitShlRegOp(ArmEmitterContext context, ShlRegFlags flags = ShlRegFlags.None)
{
bool scalar = flags.HasFlag(ShlRegFlags.Scalar);
bool signed = flags.HasFlag(ShlRegFlags.Signed);
bool round = flags.HasFlag(ShlRegFlags.Round);
bool saturating = flags.HasFlag(ShlRegFlags.Saturating);
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
Operand res = context.VectorZero(); Operand res = context.VectorZero();
@ -1178,15 +1060,225 @@ namespace ARMeilleure.Instructions
for (int index = 0; index < elems; index++) for (int index = 0; index < elems; index++)
{ {
Operand ne = EmitVectorExtract (context, op.Rn, index, op.Size, signed); Operand ne = EmitVectorExtract(context, op.Rn, index, op.Size, signed);
Operand me = EmitVectorExtractSx(context, op.Rm, index << op.Size, 0); Operand me = EmitVectorExtractSx(context, op.Rm, index << op.Size, size: 0);
Operand e = EmitShlRegOp(context, ne, context.ConvertI64ToI32(me), op.Size, signed); Operand e = !saturating
? EmitShlReg(context, ne, context.ConvertI64ToI32(me), round, op.Size, signed)
: EmitShlRegSatQ(context, ne, context.ConvertI64ToI32(me), round, op.Size, signed);
res = EmitVectorInsert(context, res, e, index, op.Size); res = EmitVectorInsert(context, res, e, index, op.Size);
} }
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
// long SignedShlReg(long op, int shiftLsB, bool round, int size);
// ulong UnsignedShlReg(ulong op, int shiftLsB, bool round, int size);
private static Operand EmitShlReg(ArmEmitterContext context, Operand op, Operand shiftLsB, bool round, int size, bool signed)
{
int eSize = 8 << size;
Debug.Assert(op.Type == OperandType.I64);
Debug.Assert(shiftLsB.Type == OperandType.I32);
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
Operand lbl1 = Label();
Operand lblEnd = Label();
Operand eSizeOp = Const(eSize);
Operand zero = Const(0);
Operand zeroL = Const(0L);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
context.BranchIf(lbl1, shiftLsB, zero, Comparison.GreaterOrEqual);
context.Copy(res, signed
? EmitSignedShrReg(context, op, context.Negate(shiftLsB), round, eSize)
: EmitUnsignedShrReg(context, op, context.Negate(shiftLsB), round, eSize));
context.Branch(lblEnd);
context.MarkLabel(lbl1);
context.BranchIf(lblEnd, shiftLsB, zero, Comparison.LessOrEqual);
Operand shl = context.ShiftLeft(op, shiftLsB);
Operand isGreaterOrEqual = context.ICompareGreaterOrEqual(shiftLsB, eSizeOp);
context.Copy(res, context.ConditionalSelect(isGreaterOrEqual, zeroL, shl));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
}
// long SignedShlRegSatQ(long op, int shiftLsB, bool round, int size);
// ulong UnsignedShlRegSatQ(ulong op, int shiftLsB, bool round, int size);
private static Operand EmitShlRegSatQ(ArmEmitterContext context, Operand op, Operand shiftLsB, bool round, int size, bool signed)
{
int eSize = 8 << size;
Debug.Assert(op.Type == OperandType.I64);
Debug.Assert(shiftLsB.Type == OperandType.I32);
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
Operand lbl1 = Label();
Operand lbl2 = Label();
Operand lblEnd = Label();
Operand eSizeOp = Const(eSize);
Operand zero = Const(0);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
context.BranchIf(lbl1, shiftLsB, zero, Comparison.GreaterOrEqual);
context.Copy(res, signed
? EmitSignedShrReg(context, op, context.Negate(shiftLsB), round, eSize)
: EmitUnsignedShrReg(context, op, context.Negate(shiftLsB), round, eSize));
context.Branch(lblEnd);
context.MarkLabel(lbl1);
context.BranchIf(lblEnd, shiftLsB, zero, Comparison.LessOrEqual);
context.BranchIf(lbl2, shiftLsB, eSizeOp, Comparison.Less);
context.Copy(res, signed
? EmitSignedSignSatQ(context, op, size)
: EmitUnsignedSignSatQ(context, op, size));
context.Branch(lblEnd);
context.MarkLabel(lbl2);
Operand shl = context.ShiftLeft(op, shiftLsB);
if (eSize == 64)
{
Operand sarOrShr = signed
? context.ShiftRightSI(shl, shiftLsB)
: context.ShiftRightUI(shl, shiftLsB);
context.Copy(res, shl);
context.BranchIf(lblEnd, sarOrShr, op, Comparison.Equal);
context.Copy(res, signed
? EmitSignedSignSatQ(context, op, size)
: EmitUnsignedSignSatQ(context, op, size));
}
else
{
context.Copy(res, signed
? EmitSignedSrcSatQ(context, shl, size, signedDst: true)
: EmitUnsignedSrcSatQ(context, shl, size, signedDst: false));
}
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
}
// shift := [1, 128]; eSize := {8, 16, 32, 64}.
// long SignedShrReg(long op, int shift, bool round, int eSize);
private static Operand EmitSignedShrReg(ArmEmitterContext context, Operand op, Operand shift, bool round, int eSize)
{
if (round)
{
Operand lblEnd = Label();
Operand eSizeOp = Const(eSize);
Operand zeroL = Const(0L);
Operand one = Const(1);
Operand oneL = Const(1L);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroL);
context.BranchIf(lblEnd, shift, eSizeOp, Comparison.GreaterOrEqual);
Operand roundConst = context.ShiftLeft(oneL, context.Subtract(shift, one));
Operand add = context.Add(op, roundConst);
Operand sar = context.ShiftRightSI(add, shift);
if (eSize == 64)
{
Operand shr = context.ShiftRightUI(add, shift);
Operand left = context.BitwiseAnd(context.Negate(op), context.BitwiseExclusiveOr(op, add));
Operand isLess = context.ICompareLess(left, zeroL);
context.Copy(res, context.ConditionalSelect(isLess, shr, sar));
}
else
{
context.Copy(res, sar);
}
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
}
else
{
Operand lblEnd = Label();
Operand eSizeOp = Const(eSize);
Operand zeroL = Const(0L);
Operand negOneL = Const(-1L);
Operand sar = context.ShiftRightSI(op, shift);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), sar);
context.BranchIf(lblEnd, shift, eSizeOp, Comparison.Less);
Operand isLess = context.ICompareLess(op, zeroL);
context.Copy(res, context.ConditionalSelect(isLess, negOneL, zeroL));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
}
}
// shift := [1, 128]; eSize := {8, 16, 32, 64}.
// ulong UnsignedShrReg(ulong op, int shift, bool round, int eSize);
private static Operand EmitUnsignedShrReg(ArmEmitterContext context, Operand op, Operand shift, bool round, int eSize)
{
if (round)
{
Operand lblEnd = Label();
Operand zeroUL = Const(0UL);
Operand one = Const(1);
Operand oneUL = Const(1UL);
Operand eSizeMaxOp = Const(64);
Operand oneShl63UL = Const(1UL << 63);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroUL);
context.BranchIf(lblEnd, shift, eSizeMaxOp, Comparison.Greater);
Operand roundConst = context.ShiftLeft(oneUL, context.Subtract(shift, one));
Operand add = context.Add(op, roundConst);
Operand shr = context.ShiftRightUI(add, shift);
Operand isEqual = context.ICompareEqual(shift, eSizeMaxOp);
context.Copy(res, context.ConditionalSelect(isEqual, zeroUL, shr));
if (eSize == 64)
{
context.BranchIf(lblEnd, add, op, Comparison.GreaterOrEqualUI);
Operand right = context.BitwiseOr(shr, context.ShiftRightUI(oneShl63UL, context.Subtract(shift, one)));
context.Copy(res, context.ConditionalSelect(isEqual, oneUL, right));
}
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
}
else
{
Operand lblEnd = Label();
Operand eSizeOp = Const(eSize);
Operand zeroUL = Const(0UL);
Operand shr = context.ShiftRightUI(op, shift);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), shr);
context.BranchIf(lblEnd, shift, eSizeOp, Comparison.Less);
context.Copy(res, zeroUL);
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
}
}
} }
} }

View File

@ -33,64 +33,24 @@ namespace ARMeilleure.Instructions
EmitShrImmSaturatingNarrowOp(context, op.U ? ShrImmSaturatingNarrowFlags.VectorZxZx : ShrImmSaturatingNarrowFlags.VectorSxSx); EmitShrImmSaturatingNarrowOp(context, op.U ? ShrImmSaturatingNarrowFlags.VectorZxZx : ShrImmSaturatingNarrowFlags.VectorSxSx);
} }
public static void Vqshrun(ArmEmitterContext context)
{
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxZx);
}
public static void Vrshr(ArmEmitterContext context) public static void Vrshr(ArmEmitterContext context)
{ {
OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp; EmitRoundShrImmOp(context, accumulate: false);
int shift = GetImmShr(op); }
long roundConst = 1L << (shift - 1);
if (op.U) public static void Vrshrn(ArmEmitterContext context)
{ {
if (op.Size < 2) EmitRoundShrImmNarrowOp(context, signed: false);
{ }
EmitVectorUnaryOpZx32(context, (op1) =>
{
op1 = context.Add(op1, Const(op1.Type, roundConst));
return context.ShiftRightUI(op1, Const(shift)); public static void Vrsra(ArmEmitterContext context)
}); {
} EmitRoundShrImmOp(context, accumulate: true);
else if (op.Size == 2)
{
EmitVectorUnaryOpZx32(context, (op1) =>
{
op1 = context.ZeroExtend32(OperandType.I64, op1);
op1 = context.Add(op1, Const(op1.Type, roundConst));
return context.ConvertI64ToI32(context.ShiftRightUI(op1, Const(shift)));
});
}
else /* if (op.Size == 3) */
{
EmitVectorUnaryOpZx32(context, (op1) => EmitShrImm64(context, op1, signed: false, roundConst, shift));
}
}
else
{
if (op.Size < 2)
{
EmitVectorUnaryOpSx32(context, (op1) =>
{
op1 = context.Add(op1, Const(op1.Type, roundConst));
return context.ShiftRightSI(op1, Const(shift));
});
}
else if (op.Size == 2)
{
EmitVectorUnaryOpSx32(context, (op1) =>
{
op1 = context.SignExtend32(OperandType.I64, op1);
op1 = context.Add(op1, Const(op1.Type, roundConst));
return context.ConvertI64ToI32(context.ShiftRightSI(op1, Const(shift)));
});
}
else /* if (op.Size == 3) */
{
EmitVectorUnaryOpZx32(context, (op1) => EmitShrImm64(context, op1, signed: true, roundConst, shift));
}
}
} }
public static void Vshl(ArmEmitterContext context) public static void Vshl(ArmEmitterContext context)
@ -191,6 +151,89 @@ namespace ARMeilleure.Instructions
} }
} }
public static void EmitRoundShrImmOp(ArmEmitterContext context, bool accumulate)
{
OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;
int shift = GetImmShr(op);
long roundConst = 1L << (shift - 1);
if (op.U)
{
if (op.Size < 2)
{
EmitVectorUnaryOpZx32(context, (op1) =>
{
op1 = context.Add(op1, Const(op1.Type, roundConst));
return context.ShiftRightUI(op1, Const(shift));
}, accumulate);
}
else if (op.Size == 2)
{
EmitVectorUnaryOpZx32(context, (op1) =>
{
op1 = context.ZeroExtend32(OperandType.I64, op1);
op1 = context.Add(op1, Const(op1.Type, roundConst));
return context.ConvertI64ToI32(context.ShiftRightUI(op1, Const(shift)));
}, accumulate);
}
else /* if (op.Size == 3) */
{
EmitVectorUnaryOpZx32(context, (op1) => EmitShrImm64(context, op1, signed: false, roundConst, shift), accumulate);
}
}
else
{
if (op.Size < 2)
{
EmitVectorUnaryOpSx32(context, (op1) =>
{
op1 = context.Add(op1, Const(op1.Type, roundConst));
return context.ShiftRightSI(op1, Const(shift));
}, accumulate);
}
else if (op.Size == 2)
{
EmitVectorUnaryOpSx32(context, (op1) =>
{
op1 = context.SignExtend32(OperandType.I64, op1);
op1 = context.Add(op1, Const(op1.Type, roundConst));
return context.ConvertI64ToI32(context.ShiftRightSI(op1, Const(shift)));
}, accumulate);
}
else /* if (op.Size == 3) */
{
EmitVectorUnaryOpZx32(context, (op1) => EmitShrImm64(context, op1, signed: true, roundConst, shift), accumulate);
}
}
}
private static void EmitRoundShrImmNarrowOp(ArmEmitterContext context, bool signed)
{
OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;
int shift = GetImmShr(op);
long roundConst = 1L << (shift - 1);
EmitVectorUnaryNarrowOp32(context, (op1) =>
{
if (op.Size <= 1)
{
op1 = context.Add(op1, Const(op1.Type, roundConst));
op1 = signed ? context.ShiftRightSI(op1, Const(shift)) : context.ShiftRightUI(op1, Const(shift));
}
else /* if (op.Size == 2 && round) */
{
op1 = EmitShrImm64(context, op1, signed, roundConst, shift); // shift <= 32
}
return op1;
}, signed);
}
private static Operand EmitShlRegOp(ArmEmitterContext context, Operand op, Operand shiftLsB, int size, bool unsigned) private static Operand EmitShlRegOp(ArmEmitterContext context, Operand op, Operand shiftLsB, int size, bool unsigned)
{ {
if (shiftLsB.Type == OperandType.I64) if (shiftLsB.Type == OperandType.I64)
@ -289,7 +332,7 @@ namespace ARMeilleure.Instructions
op1 = EmitShrImm64(context, op1, signedSrc, roundConst, shift); // shift <= 32 op1 = EmitShrImm64(context, op1, signedSrc, roundConst, shift); // shift <= 32
} }
return EmitSatQ(context, op1, 8 << op.Size, signedDst); return EmitSatQ(context, op1, 8 << op.Size, signedSrc, signedDst);
}, signedSrc); }, signedSrc);
} }
@ -313,15 +356,20 @@ namespace ARMeilleure.Instructions
return context.Call(info, value, Const(roundConst), Const(shift)); return context.Call(info, value, Const(roundConst), Const(shift));
} }
private static Operand EmitSatQ(ArmEmitterContext context, Operand value, int eSize, bool signed) private static Operand EmitSatQ(ArmEmitterContext context, Operand value, int eSize, bool signedSrc, bool signedDst)
{ {
Debug.Assert(eSize <= 32); Debug.Assert(eSize <= 32);
long intMin = signed ? -(1L << (eSize - 1)) : 0; long intMin = signedDst ? -(1L << (eSize - 1)) : 0;
long intMax = signed ? (1L << (eSize - 1)) - 1 : (1L << eSize) - 1; long intMax = signedDst ? (1L << (eSize - 1)) - 1 : (1L << eSize) - 1;
Operand gt = context.ICompareGreater(value, Const(value.Type, intMax)); Operand gt = signedSrc
Operand lt = context.ICompareLess(value, Const(value.Type, intMin)); ? context.ICompareGreater(value, Const(value.Type, intMax))
: context.ICompareGreaterUI(value, Const(value.Type, intMax));
Operand lt = signedSrc
? context.ICompareLess(value, Const(value.Type, intMin))
: context.ICompareLessUI(value, Const(value.Type, intMin));
value = context.ConditionalSelect(gt, Const(value.Type, intMax), value); value = context.ConditionalSelect(gt, Const(value.Type, intMax), value);
value = context.ConditionalSelect(lt, Const(value.Type, intMin), value); value = context.ConditionalSelect(lt, Const(value.Type, intMin), value);

View File

@ -15,11 +15,6 @@ namespace ARMeilleure.Instructions
private const int DczSizeLog2 = 4; // Log2 size in words private const int DczSizeLog2 = 4; // Log2 size in words
public const int DczSizeInBytes = 4 << DczSizeLog2; public const int DczSizeInBytes = 4 << DczSizeLog2;
public static void Hint(ArmEmitterContext context)
{
// Execute as no-op.
}
public static void Isb(ArmEmitterContext context) public static void Isb(ArmEmitterContext context)
{ {
// Execute as no-op. // Execute as no-op.

View File

@ -16,18 +16,13 @@ namespace ARMeilleure.Instructions
{ {
OpCode32System op = (OpCode32System)context.CurrOp; OpCode32System op = (OpCode32System)context.CurrOp;
if (op.Coproc != 15) if (op.Coproc != 15 || op.Opc1 != 0)
{ {
InstEmit.Und(context); InstEmit.Und(context);
return; return;
} }
if (op.Opc1 != 0)
{
throw new NotImplementedException($"Unknown MRC Opc1 0x{op.Opc1:X16} at 0x{op.Address:X16}.");
}
MethodInfo info; MethodInfo info;
switch (op.CRn) switch (op.CRn)
@ -35,7 +30,7 @@ namespace ARMeilleure.Instructions
case 13: // Process and Thread Info. case 13: // Process and Thread Info.
if (op.CRm != 0) if (op.CRm != 0)
{ {
throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}."); throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
} }
switch (op.Opc2) switch (op.Opc2)
@ -44,7 +39,7 @@ namespace ARMeilleure.Instructions
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032)); break; info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032)); break;
default: default:
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}."); throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
} }
break; break;
@ -59,11 +54,11 @@ namespace ARMeilleure.Instructions
return; // No-op. return; // No-op.
default: default:
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}."); throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16} (0x{op.RawOpCode:X}).");
} }
default: default:
throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}."); throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16} (0x{op.RawOpCode:X}).");
} }
default: default:
@ -77,18 +72,13 @@ namespace ARMeilleure.Instructions
{ {
OpCode32System op = (OpCode32System)context.CurrOp; OpCode32System op = (OpCode32System)context.CurrOp;
if (op.Coproc != 15) if (op.Coproc != 15 || op.Opc1 != 0)
{ {
InstEmit.Und(context); InstEmit.Und(context);
return; return;
} }
if (op.Opc1 != 0)
{
throw new NotImplementedException($"Unknown MRC Opc1 0x{op.Opc1:X16} at 0x{op.Address:X16}.");
}
MethodInfo info; MethodInfo info;
switch (op.CRn) switch (op.CRn)
@ -96,7 +86,7 @@ namespace ARMeilleure.Instructions
case 13: // Process and Thread Info. case 13: // Process and Thread Info.
if (op.CRm != 0) if (op.CRm != 0)
{ {
throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}."); throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
} }
switch (op.Opc2) switch (op.Opc2)
@ -108,13 +98,13 @@ namespace ARMeilleure.Instructions
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidr32)); break; info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidr32)); break;
default: default:
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}."); throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
} }
break; break;
default: default:
throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X8} at 0x{op.Address:X16}."); throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
} }
if (op.Rt == RegisterAlias.Aarch32Pc) if (op.Rt == RegisterAlias.Aarch32Pc)
@ -154,13 +144,13 @@ namespace ARMeilleure.Instructions
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)); break; info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)); break;
default: default:
throw new NotImplementedException($"Unknown MRRC Opc1 0x{opc:X16} at 0x{op.Address:X16}."); throw new NotImplementedException($"Unknown MRRC Opc1 0x{opc:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
} }
break; break;
default: default:
throw new NotImplementedException($"Unknown MRRC 0x{op.RawOpCode:X8} at 0x{op.Address:X16}."); throw new NotImplementedException($"Unknown MRRC 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
} }
Operand result = context.Call(info); Operand result = context.Call(info);
@ -265,7 +255,7 @@ namespace ARMeilleure.Instructions
case 0b1000: // FPEXC case 0b1000: // FPEXC
throw new NotImplementedException("Supervisor Only"); throw new NotImplementedException("Supervisor Only");
default: default:
throw new NotImplementedException($"Unknown VMRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}."); throw new NotImplementedException($"Unknown VMRS 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
} }
} }
@ -288,7 +278,7 @@ namespace ARMeilleure.Instructions
case 0b1000: // FPEXC case 0b1000: // FPEXC
throw new NotImplementedException("Supervisor Only"); throw new NotImplementedException("Supervisor Only");
default: default:
throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}."); throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
} }
} }

View File

@ -45,6 +45,7 @@ namespace ARMeilleure.Instructions
Dsb, Dsb,
Eon, Eon,
Eor, Eor,
Esb,
Extr, Extr,
Hint, Hint,
Isb, Isb,
@ -81,6 +82,9 @@ namespace ARMeilleure.Instructions
Sbcs, Sbcs,
Sbfm, Sbfm,
Sdiv, Sdiv,
Sel,
Sev,
Sevl,
Shsub8, Shsub8,
Smaddl, Smaddl,
Smsubl, Smsubl,
@ -104,12 +108,16 @@ namespace ARMeilleure.Instructions
Sys, Sys,
Tbnz, Tbnz,
Tbz, Tbz,
Tsb,
Ubfm, Ubfm,
Udiv, Udiv,
Umaddl, Umaddl,
Umsubl, Umsubl,
Umulh, Umulh,
Und, Und,
Wfe,
Wfi,
Yield,
// FP & SIMD (AArch64) // FP & SIMD (AArch64)
Abs_S, Abs_S,
@ -519,6 +527,7 @@ namespace ARMeilleure.Instructions
Revsh, Revsh,
Rsb, Rsb,
Rsc, Rsc,
Sadd8,
Sbfx, Sbfx,
Shadd8, Shadd8,
Smla__, Smla__,
@ -529,6 +538,7 @@ namespace ARMeilleure.Instructions
Smmls, Smmls,
Smul__, Smul__,
Smmul, Smmul,
Ssub8,
Stl, Stl,
Stlb, Stlb,
Stlex, Stlex,
@ -545,9 +555,12 @@ namespace ARMeilleure.Instructions
Strexh, Strexh,
Strh, Strh,
Sxtb16, Sxtb16,
Tbb,
Tbh,
Teq, Teq,
Trap, Trap,
Tst, Tst,
Uadd8,
Ubfx, Ubfx,
Uhadd8, Uhadd8,
Uhsub8, Uhsub8,
@ -556,6 +569,7 @@ namespace ARMeilleure.Instructions
Umull, Umull,
Usat, Usat,
Usat16, Usat16,
Usub8,
Uxtb, Uxtb,
Uxtb16, Uxtb16,
Uxth, Uxth,
@ -601,6 +615,7 @@ namespace ARMeilleure.Instructions
Vmin, Vmin,
Vminnm, Vminnm,
Vmla, Vmla,
Vmlal,
Vmls, Vmls,
Vmlsl, Vmlsl,
Vmov, Vmov,
@ -618,15 +633,28 @@ namespace ARMeilleure.Instructions
Vorn, Vorn,
Vorr, Vorr,
Vpadd, Vpadd,
Vpaddl,
Vpmax, Vpmax,
Vpmin, Vpmin,
Vqadd,
Vqdmulh,
Vqmovn,
Vqmovun,
Vqrshrn, Vqrshrn,
Vqrshrun, Vqrshrun,
Vqshrn, Vqshrn,
Vqshrun,
Vqsub,
Vrev, Vrev,
Vrhadd,
Vrint, Vrint,
Vrinta,
Vrintm,
Vrintn,
Vrintp,
Vrintx, Vrintx,
Vrshr, Vrshr,
Vrshrn,
Vsel, Vsel,
Vshl, Vshl,
Vshll, Vshll,
@ -643,8 +671,10 @@ namespace ARMeilleure.Instructions
Vrecps, Vrecps,
Vrsqrte, Vrsqrte,
Vrsqrts, Vrsqrts,
Vrsra,
Vsra, Vsra,
Vsub, Vsub,
Vsubl,
Vsubw, Vsubw,
Vtbl, Vtbl,
Vtrn, Vtrn,

View File

@ -5,287 +5,6 @@ namespace ARMeilleure.Instructions
{ {
static class SoftFallback static class SoftFallback
{ {
#region "ShlReg"
public static long SignedShlReg(long value, long shift, bool round, int size)
{
int eSize = 8 << size;
int shiftLsB = (sbyte)shift;
if (shiftLsB < 0)
{
return SignedShrReg(value, -shiftLsB, round, eSize);
}
else if (shiftLsB > 0)
{
if (shiftLsB >= eSize)
{
return 0L;
}
return value << shiftLsB;
}
else /* if (shiftLsB == 0) */
{
return value;
}
}
public static ulong UnsignedShlReg(ulong value, ulong shift, bool round, int size)
{
int eSize = 8 << size;
int shiftLsB = (sbyte)shift;
if (shiftLsB < 0)
{
return UnsignedShrReg(value, -shiftLsB, round, eSize);
}
else if (shiftLsB > 0)
{
if (shiftLsB >= eSize)
{
return 0UL;
}
return value << shiftLsB;
}
else /* if (shiftLsB == 0) */
{
return value;
}
}
public static long SignedShlRegSatQ(long value, long shift, bool round, int size)
{
ExecutionContext context = NativeInterface.GetContext();
int eSize = 8 << size;
int shiftLsB = (sbyte)shift;
if (shiftLsB < 0)
{
return SignedShrReg(value, -shiftLsB, round, eSize);
}
else if (shiftLsB > 0)
{
if (shiftLsB >= eSize)
{
return SignedSignSatQ(value, eSize, context);
}
if (eSize == 64)
{
long shl = value << shiftLsB;
long shr = shl >> shiftLsB;
if (shr != value)
{
return SignedSignSatQ(value, eSize, context);
}
else /* if (shr == value) */
{
return shl;
}
}
else /* if (eSize != 64) */
{
return SignedSrcSignedDstSatQ(value << shiftLsB, size);
}
}
else /* if (shiftLsB == 0) */
{
return value;
}
}
public static ulong UnsignedShlRegSatQ(ulong value, ulong shift, bool round, int size)
{
ExecutionContext context = NativeInterface.GetContext();
int eSize = 8 << size;
int shiftLsB = (sbyte)shift;
if (shiftLsB < 0)
{
return UnsignedShrReg(value, -shiftLsB, round, eSize);
}
else if (shiftLsB > 0)
{
if (shiftLsB >= eSize)
{
return UnsignedSignSatQ(value, eSize, context);
}
if (eSize == 64)
{
ulong shl = value << shiftLsB;
ulong shr = shl >> shiftLsB;
if (shr != value)
{
return UnsignedSignSatQ(value, eSize, context);
}
else /* if (shr == value) */
{
return shl;
}
}
else /* if (eSize != 64) */
{
return UnsignedSrcUnsignedDstSatQ(value << shiftLsB, size);
}
}
else /* if (shiftLsB == 0) */
{
return value;
}
}
private static long SignedShrReg(long value, int shift, bool round, int eSize) // shift := [1, 128]; eSize := {8, 16, 32, 64}.
{
if (round)
{
if (shift >= eSize)
{
return 0L;
}
long roundConst = 1L << (shift - 1);
long add = value + roundConst;
if (eSize == 64)
{
if ((~value & (value ^ add)) < 0L)
{
return (long)((ulong)add >> shift);
}
else
{
return add >> shift;
}
}
else /* if (eSize != 64) */
{
return add >> shift;
}
}
else /* if (!round) */
{
if (shift >= eSize)
{
if (value < 0L)
{
return -1L;
}
else /* if (value >= 0L) */
{
return 0L;
}
}
return value >> shift;
}
}
private static ulong UnsignedShrReg(ulong value, int shift, bool round, int eSize) // shift := [1, 128]; eSize := {8, 16, 32, 64}.
{
if (round)
{
if (shift > 64)
{
return 0UL;
}
ulong roundConst = 1UL << (shift - 1);
ulong add = value + roundConst;
if (eSize == 64)
{
if ((add < value) && (add < roundConst))
{
if (shift == 64)
{
return 1UL;
}
return (add >> shift) | (0x8000000000000000UL >> (shift - 1));
}
else
{
if (shift == 64)
{
return 0UL;
}
return add >> shift;
}
}
else /* if (eSize != 64) */
{
if (shift == 64)
{
return 0UL;
}
return add >> shift;
}
}
else /* if (!round) */
{
if (shift >= eSize)
{
return 0UL;
}
return value >> shift;
}
}
private static long SignedSignSatQ(long op, int eSize, ExecutionContext context) // eSize := {8, 16, 32, 64}.
{
long tMaxValue = (1L << (eSize - 1)) - 1L;
long tMinValue = -(1L << (eSize - 1));
if (op > 0L)
{
context.Fpsr |= FPSR.Qc;
return tMaxValue;
}
else if (op < 0L)
{
context.Fpsr |= FPSR.Qc;
return tMinValue;
}
else
{
return 0L;
}
}
private static ulong UnsignedSignSatQ(ulong op, int eSize, ExecutionContext context) // eSize := {8, 16, 32, 64}.
{
ulong tMaxValue = ulong.MaxValue >> (64 - eSize);
if (op > 0UL)
{
context.Fpsr |= FPSR.Qc;
return tMaxValue;
}
else
{
return 0UL;
}
}
#endregion
#region "ShrImm64" #region "ShrImm64"
public static long SignedShrImm64(long value, long roundConst, int shift) public static long SignedShrImm64(long value, long roundConst, int shift)
{ {
@ -508,304 +227,6 @@ namespace ARMeilleure.Instructions
} }
#endregion #endregion
#region "Saturating"
public static long SignedSrcSignedDstSatQ(long op, int size)
{
ExecutionContext context = NativeInterface.GetContext();
int eSize = 8 << size;
long tMaxValue = (1L << (eSize - 1)) - 1L;
long tMinValue = -(1L << (eSize - 1));
if (op > tMaxValue)
{
context.Fpsr |= FPSR.Qc;
return tMaxValue;
}
else if (op < tMinValue)
{
context.Fpsr |= FPSR.Qc;
return tMinValue;
}
else
{
return op;
}
}
public static ulong SignedSrcUnsignedDstSatQ(long op, int size)
{
ExecutionContext context = NativeInterface.GetContext();
int eSize = 8 << size;
ulong tMaxValue = (1UL << eSize) - 1UL;
ulong tMinValue = 0UL;
if (op > (long)tMaxValue)
{
context.Fpsr |= FPSR.Qc;
return tMaxValue;
}
else if (op < (long)tMinValue)
{
context.Fpsr |= FPSR.Qc;
return tMinValue;
}
else
{
return (ulong)op;
}
}
public static long UnsignedSrcSignedDstSatQ(ulong op, int size)
{
ExecutionContext context = NativeInterface.GetContext();
int eSize = 8 << size;
long tMaxValue = (1L << (eSize - 1)) - 1L;
if (op > (ulong)tMaxValue)
{
context.Fpsr |= FPSR.Qc;
return tMaxValue;
}
else
{
return (long)op;
}
}
public static ulong UnsignedSrcUnsignedDstSatQ(ulong op, int size)
{
ExecutionContext context = NativeInterface.GetContext();
int eSize = 8 << size;
ulong tMaxValue = (1UL << eSize) - 1UL;
if (op > tMaxValue)
{
context.Fpsr |= FPSR.Qc;
return tMaxValue;
}
else
{
return op;
}
}
public static long UnarySignedSatQAbsOrNeg(long op)
{
ExecutionContext context = NativeInterface.GetContext();
if (op == long.MinValue)
{
context.Fpsr |= FPSR.Qc;
return long.MaxValue;
}
else
{
return op;
}
}
public static long BinarySignedSatQAdd(long op1, long op2)
{
ExecutionContext context = NativeInterface.GetContext();
long add = op1 + op2;
if ((~(op1 ^ op2) & (op1 ^ add)) < 0L)
{
context.Fpsr |= FPSR.Qc;
if (op1 < 0L)
{
return long.MinValue;
}
else
{
return long.MaxValue;
}
}
else
{
return add;
}
}
public static ulong BinaryUnsignedSatQAdd(ulong op1, ulong op2)
{
ExecutionContext context = NativeInterface.GetContext();
ulong add = op1 + op2;
if ((add < op1) && (add < op2))
{
context.Fpsr |= FPSR.Qc;
return ulong.MaxValue;
}
else
{
return add;
}
}
public static long BinarySignedSatQSub(long op1, long op2)
{
ExecutionContext context = NativeInterface.GetContext();
long sub = op1 - op2;
if (((op1 ^ op2) & (op1 ^ sub)) < 0L)
{
context.Fpsr |= FPSR.Qc;
if (op1 < 0L)
{
return long.MinValue;
}
else
{
return long.MaxValue;
}
}
else
{
return sub;
}
}
public static ulong BinaryUnsignedSatQSub(ulong op1, ulong op2)
{
ExecutionContext context = NativeInterface.GetContext();
ulong sub = op1 - op2;
if (op1 < op2)
{
context.Fpsr |= FPSR.Qc;
return ulong.MinValue;
}
else
{
return sub;
}
}
public static long BinarySignedSatQAcc(ulong op1, long op2)
{
ExecutionContext context = NativeInterface.GetContext();
if (op1 <= (ulong)long.MaxValue)
{
// op1 from ulong.MinValue to (ulong)long.MaxValue
// op2 from long.MinValue to long.MaxValue
long add = (long)op1 + op2;
if ((~op2 & add) < 0L)
{
context.Fpsr |= FPSR.Qc;
return long.MaxValue;
}
else
{
return add;
}
}
else if (op2 >= 0L)
{
// op1 from (ulong)long.MaxValue + 1UL to ulong.MaxValue
// op2 from (long)ulong.MinValue to long.MaxValue
context.Fpsr |= FPSR.Qc;
return long.MaxValue;
}
else
{
// op1 from (ulong)long.MaxValue + 1UL to ulong.MaxValue
// op2 from long.MinValue to (long)ulong.MinValue - 1L
ulong add = op1 + (ulong)op2;
if (add > (ulong)long.MaxValue)
{
context.Fpsr |= FPSR.Qc;
return long.MaxValue;
}
else
{
return (long)add;
}
}
}
public static ulong BinaryUnsignedSatQAcc(long op1, ulong op2)
{
ExecutionContext context = NativeInterface.GetContext();
if (op1 >= 0L)
{
// op1 from (long)ulong.MinValue to long.MaxValue
// op2 from ulong.MinValue to ulong.MaxValue
ulong add = (ulong)op1 + op2;
if ((add < (ulong)op1) && (add < op2))
{
context.Fpsr |= FPSR.Qc;
return ulong.MaxValue;
}
else
{
return add;
}
}
else if (op2 > (ulong)long.MaxValue)
{
// op1 from long.MinValue to (long)ulong.MinValue - 1L
// op2 from (ulong)long.MaxValue + 1UL to ulong.MaxValue
return (ulong)op1 + op2;
}
else
{
// op1 from long.MinValue to (long)ulong.MinValue - 1L
// op2 from ulong.MinValue to (ulong)long.MaxValue
long add = op1 + (long)op2;
if (add < (long)ulong.MinValue)
{
context.Fpsr |= FPSR.Qc;
return ulong.MinValue;
}
else
{
return (ulong)add;
}
}
}
#endregion
#region "Count" #region "Count"
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.). public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{ {

View File

@ -4,6 +4,10 @@ namespace ARMeilleure.State
{ {
TFlag = 5, TFlag = 5,
EFlag = 9, EFlag = 9,
GE0Flag = 16,
GE1Flag = 17,
GE2Flag = 18,
GE3Flag = 19,
QFlag = 27, QFlag = 27,
VFlag = 28, VFlag = 28,
CFlag = 29, CFlag = 29,

View File

@ -127,7 +127,7 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpcr))); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpcr)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr))); // A32 only. SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsr))); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsr)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc))); // A32 only. SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0))); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032))); // A32 only. SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking))); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking)));
@ -140,12 +140,6 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64))); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128))); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQAcc)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQAdd)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQSub)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQAcc)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQAdd)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQSub)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingSigns))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingSigns)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingZeros))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingZeros)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32b))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32b)));
@ -185,11 +179,7 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart2))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart2)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlReg)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShrImm64))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShrImm64)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedSrcSignedDstSatQ)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedSrcUnsignedDstSatQ)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl3))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl3)));
@ -198,12 +188,7 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnarySignedSatQAbsOrNeg)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlReg)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShrImm64))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShrImm64)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedSrcSignedDstSatQ)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedSrcUnsignedDstSatQ)));
SetDelegateInfo(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert))); SetDelegateInfo(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)));
SetDelegateInfo(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert))); SetDelegateInfo(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)));

View File

@ -19,8 +19,6 @@ namespace ARMeilleure.Translation
public int Count => _count; public int Count => _count;
public IntervalTree() { }
#region Public Methods #region Public Methods
/// <summary> /// <summary>

View File

@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 3585; //! To be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 3700; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0"; private const string ActualDir = "0";
private const string BackupDir = "1"; private const string BackupDir = "1";

View File

@ -44,15 +44,11 @@ namespace ARMeilleure.Translation
private readonly IJitMemoryAllocator _allocator; private readonly IJitMemoryAllocator _allocator;
private readonly ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>> _oldFuncs; private readonly ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>> _oldFuncs;
private readonly ConcurrentDictionary<ulong, object> _backgroundSet;
private readonly ConcurrentStack<RejitRequest> _backgroundStack;
private readonly AutoResetEvent _backgroundTranslatorEvent;
private readonly ReaderWriterLock _backgroundTranslatorLock;
internal TranslatorCache<TranslatedFunction> Functions { get; } internal TranslatorCache<TranslatedFunction> Functions { get; }
internal AddressTable<ulong> FunctionTable { get; } internal AddressTable<ulong> FunctionTable { get; }
internal EntryTable<uint> CountTable { get; } internal EntryTable<uint> CountTable { get; }
internal TranslatorStubs Stubs { get; } internal TranslatorStubs Stubs { get; }
internal TranslatorQueue Queue { get; }
internal IMemoryManager Memory { get; } internal IMemoryManager Memory { get; }
private volatile int _threadCount; private volatile int _threadCount;
@ -67,10 +63,7 @@ namespace ARMeilleure.Translation
_oldFuncs = new ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>>(); _oldFuncs = new ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>>();
_backgroundSet = new ConcurrentDictionary<ulong, object>(); Queue = new TranslatorQueue();
_backgroundStack = new ConcurrentStack<RejitRequest>();
_backgroundTranslatorEvent = new AutoResetEvent(false);
_backgroundTranslatorLock = new ReaderWriterLock();
JitCache.Initialize(allocator); JitCache.Initialize(allocator);
@ -87,43 +80,6 @@ namespace ARMeilleure.Translation
} }
} }
private void TranslateStackedSubs()
{
while (_threadCount != 0)
{
_backgroundTranslatorLock.AcquireReaderLock(Timeout.Infinite);
if (_backgroundStack.TryPop(out RejitRequest request) &&
_backgroundSet.TryRemove(request.Address, out _))
{
TranslatedFunction func = Translate(request.Address, request.Mode, highCq: true);
Functions.AddOrUpdate(request.Address, func.GuestSize, func, (key, oldFunc) =>
{
EnqueueForDeletion(key, oldFunc);
return func;
});
if (PtcProfiler.Enabled)
{
PtcProfiler.UpdateEntry(request.Address, request.Mode, highCq: true);
}
RegisterFunction(request.Address, func);
_backgroundTranslatorLock.ReleaseReaderLock();
}
else
{
_backgroundTranslatorLock.ReleaseReaderLock();
_backgroundTranslatorEvent.WaitOne();
}
}
// Wake up any other background translator threads, to encourage them to exit.
_backgroundTranslatorEvent.Set();
}
public void Execute(State.ExecutionContext context, ulong address) public void Execute(State.ExecutionContext context, ulong address)
{ {
if (Interlocked.Increment(ref _threadCount) == 1) if (Interlocked.Increment(ref _threadCount) == 1)
@ -155,7 +111,7 @@ namespace ARMeilleure.Translation
{ {
bool last = i != 0 && i == unboundedThreadCount - 1; bool last = i != 0 && i == unboundedThreadCount - 1;
Thread backgroundTranslatorThread = new Thread(TranslateStackedSubs) Thread backgroundTranslatorThread = new Thread(BackgroundTranslate)
{ {
Name = "CPU.BackgroundTranslatorThread." + i, Name = "CPU.BackgroundTranslatorThread." + i,
Priority = last ? ThreadPriority.Lowest : ThreadPriority.Normal Priority = last ? ThreadPriority.Lowest : ThreadPriority.Normal
@ -186,10 +142,9 @@ namespace ARMeilleure.Translation
if (Interlocked.Decrement(ref _threadCount) == 0) if (Interlocked.Decrement(ref _threadCount) == 0)
{ {
_backgroundTranslatorEvent.Set();
ClearJitCache(); ClearJitCache();
Queue.Dispose();
Stubs.Dispose(); Stubs.Dispose();
FunctionTable.Dispose(); FunctionTable.Dispose();
CountTable.Dispose(); CountTable.Dispose();
@ -317,6 +272,27 @@ namespace ARMeilleure.Translation
return new TranslatedFunction(func, counter, funcSize, highCq); return new TranslatedFunction(func, counter, funcSize, highCq);
} }
private void BackgroundTranslate()
{
while (_threadCount != 0 && Queue.TryDequeue(out RejitRequest request))
{
TranslatedFunction func = Translate(request.Address, request.Mode, highCq: true);
Functions.AddOrUpdate(request.Address, func.GuestSize, func, (key, oldFunc) =>
{
EnqueueForDeletion(key, oldFunc);
return func;
});
if (PtcProfiler.Enabled)
{
PtcProfiler.UpdateEntry(request.Address, request.Mode, highCq: true);
}
RegisterFunction(request.Address, func);
}
}
private struct Range private struct Range
{ {
public ulong Start { get; } public ulong Start { get; }
@ -504,11 +480,7 @@ namespace ARMeilleure.Translation
internal void EnqueueForRejit(ulong guestAddress, ExecutionMode mode) internal void EnqueueForRejit(ulong guestAddress, ExecutionMode mode)
{ {
if (_backgroundSet.TryAdd(guestAddress, null)) Queue.Enqueue(guestAddress, mode);
{
_backgroundStack.Push(new RejitRequest(guestAddress, mode));
_backgroundTranslatorEvent.Set();
}
} }
private void EnqueueForDeletion(ulong guestAddress, TranslatedFunction func) private void EnqueueForDeletion(ulong guestAddress, TranslatedFunction func)
@ -542,26 +514,23 @@ namespace ARMeilleure.Translation
private void ClearRejitQueue(bool allowRequeue) private void ClearRejitQueue(bool allowRequeue)
{ {
_backgroundTranslatorLock.AcquireWriterLock(Timeout.Infinite); if (!allowRequeue)
if (allowRequeue)
{ {
while (_backgroundStack.TryPop(out var request)) Queue.Clear();
return;
}
lock (Queue.Sync)
{
while (Queue.Count > 0 && Queue.TryDequeue(out RejitRequest request))
{ {
if (Functions.TryGetValue(request.Address, out var func) && func.CallCounter != null) if (Functions.TryGetValue(request.Address, out var func) && func.CallCounter != null)
{ {
Volatile.Write(ref func.CallCounter.Value, 0); Volatile.Write(ref func.CallCounter.Value, 0);
} }
_backgroundSet.TryRemove(request.Address, out _);
} }
} }
else
{
_backgroundStack.Clear();
}
_backgroundTranslatorLock.ReleaseWriterLock();
} }
} }
} }

View File

@ -0,0 +1,121 @@
using ARMeilleure.Diagnostics;
using ARMeilleure.State;
using System;
using System.Collections.Generic;
using System.Threading;
namespace ARMeilleure.Translation
{
/// <summary>
/// Represents a queue of <see cref="RejitRequest"/>.
/// </summary>
/// <remarks>
/// This does not necessarily behave like a queue, i.e: a FIFO collection.
/// </remarks>
sealed class TranslatorQueue : IDisposable
{
private bool _disposed;
private readonly Stack<RejitRequest> _requests;
private readonly HashSet<ulong> _requestAddresses;
/// <summary>
/// Gets the object used to synchronize access to the <see cref="TranslatorQueue"/>.
/// </summary>
public object Sync { get; }
/// <summary>
/// Gets the number of requests in the <see cref="TranslatorQueue"/>.
/// </summary>
public int Count => _requests.Count;
/// <summary>
/// Initializes a new instance of the <see cref="TranslatorQueue"/> class.
/// </summary>
public TranslatorQueue()
{
Sync = new object();
_requests = new Stack<RejitRequest>();
_requestAddresses = new HashSet<ulong>();
}
/// <summary>
/// Enqueues a request with the specified <paramref name="address"/> and <paramref name="mode"/>.
/// </summary>
/// <param name="address">Address of request</param>
/// <param name="mode"><see cref="ExecutionMode"/> of request</param>
public void Enqueue(ulong address, ExecutionMode mode)
{
lock (Sync)
{
if (_requestAddresses.Add(address))
{
_requests.Push(new RejitRequest(address, mode));
TranslatorEventSource.Log.RejitQueueAdd(1);
Monitor.Pulse(Sync);
}
}
}
/// <summary>
/// Tries to dequeue a <see cref="RejitRequest"/>. This will block the thread until a <see cref="RejitRequest"/>
/// is enqueued or the <see cref="TranslatorQueue"/> is disposed.
/// </summary>
/// <param name="result"><see cref="RejitRequest"/> dequeued</param>
/// <returns><see langword="true"/> on success; otherwise <see langword="false"/></returns>
public bool TryDequeue(out RejitRequest result)
{
while (!_disposed)
{
lock (Sync)
{
if (_requests.TryPop(out result))
{
_requestAddresses.Remove(result.Address);
TranslatorEventSource.Log.RejitQueueAdd(-1);
return true;
}
Monitor.Wait(Sync);
}
}
result = default;
return false;
}
/// <summary>
/// Clears the <see cref="TranslatorQueue"/>.
/// </summary>
public void Clear()
{
lock (Sync)
{
TranslatorEventSource.Log.RejitQueueAdd(-_requests.Count);
_requests.Clear();
_requestAddresses.Clear();
Monitor.PulseAll(Sync);
}
}
/// <summary>
/// Releases all resources used by the <see cref="TranslatorQueue"/> instance.
/// </summary>
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
Clear();
}
}
}
}

View File

@ -27,7 +27,7 @@
</a> </a>
<br> <br>
<br> <br>
<img src="https://raw.githubusercontent.com/Ryujinx/Ryujinx-Website/master/static/public/shell_fullsize.png"> <img src="https://raw.githubusercontent.com/Ryujinx/Ryujinx-Website/master/public/assets/images/shell.png">
</p> </p>
<h5 align="center"> <h5 align="center">
@ -36,8 +36,8 @@
## Compatibility ## Compatibility
As of January 2022, Ryujinx has been tested on approximately 3,500 titles; over 3,200 boot past menus and into gameplay, with roughly 2,500 of those being considered playable. As of September 2022, Ryujinx has been tested on approximately 3,600 titles; over 3,400 boot past menus and into gameplay, with roughly 2,700 of those being considered playable. You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues).
You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues). Anyone is free to submit an updated test on an existing game entry; simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue. Use the search function to see if a game has been tested already! Anyone is free to submit a new game test or update an existing game test entry; simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue. Use the search function to see if a game has been tested already!
## Usage ## Usage
@ -118,11 +118,11 @@ If you'd like to support the project financially, Ryujinx has an active Patreon
<img src="https://images.squarespace-cdn.com/content/v1/560c1d39e4b0b4fae0c9cf2a/1567548955044-WVD994WZP76EWF15T0L3/Patreon+Button.png?format=500w" width="150"> <img src="https://images.squarespace-cdn.com/content/v1/560c1d39e4b0b4fae0c9cf2a/1567548955044-WVD994WZP76EWF15T0L3/Patreon+Button.png?format=500w" width="150">
</a> </a>
All the developers working on the project do so on their free time, but the project has several expenses: All developers working on the project do so in their free time, but the project has several expenses:
* Hackable Nintendo Switch consoles to reverse-engineer the hardware * Hackable Nintendo Switch consoles to reverse-engineer the hardware
* Additional computer hardware for testing purposes (e.g. GPUs to diagnose graphical bugs, etc.) * Additional computer hardware for testing purposes (e.g. GPUs to diagnose graphical bugs, etc.)
* Licenses for various software development tools (e.g. Jetbrains, LDN servers, IDA) * Licenses for various software development tools (e.g. Jetbrains, IDA)
* Web hosting and infrastructure maintenance * Web hosting and infrastructure maintenance (e.g. LDN servers)
All funds received through Patreon are considered a donation to support the project. Patrons receive early access to progress reports and exclusive access to developer interviews. All funds received through Patreon are considered a donation to support the project. Patrons receive early access to progress reports and exclusive access to developer interviews.

View File

@ -55,7 +55,6 @@ namespace Ryujinx.Audio.Renderer.Server
private uint _processHandle; private uint _processHandle;
private ulong _appletResourceId; private ulong _appletResourceId;
private WritableRegion _workBufferRegion;
private MemoryHandle _workBufferMemoryPin; private MemoryHandle _workBufferMemoryPin;
private Memory<float> _mixBuffer; private Memory<float> _mixBuffer;
@ -98,7 +97,15 @@ namespace Ryujinx.Audio.Renderer.Server
_sessionId = 0; _sessionId = 0;
} }
public ResultCode Initialize(ref AudioRendererConfiguration parameter, uint processHandle, CpuAddress workBuffer, ulong workBufferSize, int sessionId, ulong appletResourceId, IVirtualMemoryManager memoryManager) public ResultCode Initialize(
ref AudioRendererConfiguration parameter,
uint processHandle,
Memory<byte> workBufferMemory,
CpuAddress workBuffer,
ulong workBufferSize,
int sessionId,
ulong appletResourceId,
IVirtualMemoryManager memoryManager)
{ {
if (!BehaviourContext.CheckValidRevision(parameter.Revision)) if (!BehaviourContext.CheckValidRevision(parameter.Revision))
{ {
@ -134,11 +141,10 @@ namespace Ryujinx.Audio.Renderer.Server
WorkBufferAllocator workBufferAllocator; WorkBufferAllocator workBufferAllocator;
_workBufferRegion = MemoryManager.GetWritableRegion(workBuffer, (int)workBufferSize); workBufferMemory.Span.Fill(0);
_workBufferRegion.Memory.Span.Fill(0); _workBufferMemoryPin = workBufferMemory.Pin();
_workBufferMemoryPin = _workBufferRegion.Memory.Pin();
workBufferAllocator = new WorkBufferAllocator(_workBufferRegion.Memory); workBufferAllocator = new WorkBufferAllocator(workBufferMemory);
PoolMapper poolMapper = new PoolMapper(processHandle, false); PoolMapper poolMapper = new PoolMapper(processHandle, false);
poolMapper.InitializeSystemPool(ref _dspMemoryPoolState, workBuffer, workBufferSize); poolMapper.InitializeSystemPool(ref _dspMemoryPoolState, workBuffer, workBufferSize);
@ -841,7 +847,6 @@ namespace Ryujinx.Audio.Renderer.Server
_manager.Unregister(this); _manager.Unregister(this);
_terminationEvent.Dispose(); _terminationEvent.Dispose();
_workBufferMemoryPin.Dispose(); _workBufferMemoryPin.Dispose();
_workBufferRegion.Dispose();
if (MemoryManager is IRefCounted rc) if (MemoryManager is IRefCounted rc)
{ {

View File

@ -305,13 +305,34 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="workBufferSize">The guest work buffer size.</param> /// <param name="workBufferSize">The guest work buffer size.</param>
/// <param name="processHandle">The process handle of the application.</param> /// <param name="processHandle">The process handle of the application.</param>
/// <returns>A <see cref="ResultCode"/> reporting an error or a success.</returns> /// <returns>A <see cref="ResultCode"/> reporting an error or a success.</returns>
public ResultCode OpenAudioRenderer(out AudioRenderSystem renderer, IVirtualMemoryManager memoryManager, ref AudioRendererConfiguration parameter, ulong appletResourceUserId, ulong workBufferAddress, ulong workBufferSize, uint processHandle, float volume) public ResultCode OpenAudioRenderer(
out AudioRenderSystem renderer,
IVirtualMemoryManager memoryManager,
ref AudioRendererConfiguration parameter,
ulong appletResourceUserId,
ulong workBufferAddress,
ulong workBufferSize,
uint processHandle,
float volume)
{ {
int sessionId = AcquireSessionId(); int sessionId = AcquireSessionId();
AudioRenderSystem audioRenderer = new AudioRenderSystem(this, _sessionsSystemEvent[sessionId]); AudioRenderSystem audioRenderer = new AudioRenderSystem(this, _sessionsSystemEvent[sessionId]);
ResultCode result = audioRenderer.Initialize(ref parameter, processHandle, workBufferAddress, workBufferSize, sessionId, appletResourceUserId, memoryManager); // TODO: Eventually, we should try to use the guest supplied work buffer instead of allocating
// our own. However, it was causing problems on some applications that would unmap the memory
// before the audio renderer was fully disposed.
Memory<byte> workBufferMemory = GC.AllocateArray<byte>((int)workBufferSize, pinned: true);
ResultCode result = audioRenderer.Initialize(
ref parameter,
processHandle,
workBufferMemory,
workBufferAddress,
workBufferSize,
sessionId,
appletResourceUserId,
memoryManager);
if (result == ResultCode.Success) if (result == ResultCode.Success)
{ {

View File

@ -1,6 +1,5 @@
using ARMeilleure.Translation; using ARMeilleure.Translation;
using ARMeilleure.Translation.PTC; using ARMeilleure.Translation.PTC;
using Avalonia;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Threading; using Avalonia.Threading;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
@ -12,10 +11,8 @@ using Ryujinx.Audio.Integration;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input; using Ryujinx.Ava.Input;
using Ryujinx.Ava.Ui.Backend.Vulkan;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.Ui.Controls;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.Ui.Models;
using Ryujinx.Ava.Ui.Vulkan;
using Ryujinx.Ava.Ui.Windows; using Ryujinx.Ava.Ui.Windows;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
@ -39,6 +36,7 @@ using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
using SPB.Graphics.Vulkan;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
@ -58,24 +56,24 @@ namespace Ryujinx.Ava
{ {
private const int CursorHideIdleTime = 8; // Hide Cursor seconds private const int CursorHideIdleTime = 8; // Hide Cursor seconds
private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping. private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping.
private const int TargetFps = 60;
private static readonly Cursor InvisibleCursor = new Cursor(StandardCursorType.None); private static readonly Cursor InvisibleCursor = new Cursor(StandardCursorType.None);
private readonly long _ticksPerFrame;
private readonly Stopwatch _chrono;
private readonly AccountManager _accountManager; private readonly AccountManager _accountManager;
private readonly UserChannelPersistence _userChannelPersistence; private readonly UserChannelPersistence _userChannelPersistence;
private readonly InputManager _inputManager; private readonly InputManager _inputManager;
private readonly IKeyboard _keyboardInterface;
private readonly MainWindow _parent; private readonly MainWindow _parent;
private readonly IKeyboard _keyboardInterface;
private readonly GraphicsDebugLevel _glLogLevel; private readonly GraphicsDebugLevel _glLogLevel;
private bool _hideCursorOnIdle; private bool _hideCursorOnIdle;
private bool _isStopped; private bool _isStopped;
private bool _isActive; private bool _isActive;
private long _lastCursorMoveTime; private long _lastCursorMoveTime;
private long _ticks = 0;
private KeyboardHotkeyState _prevHotkeyState; private KeyboardHotkeyState _prevHotkeyState;
@ -93,7 +91,7 @@ namespace Ryujinx.Ava
public event EventHandler AppExit; public event EventHandler AppExit;
public event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent; public event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent;
public RendererControl Renderer { get; } public RendererHost Renderer { get; }
public VirtualFileSystem VirtualFileSystem { get; } public VirtualFileSystem VirtualFileSystem { get; }
public ContentManager ContentManager { get; } public ContentManager ContentManager { get; }
public Switch Device { get; set; } public Switch Device { get; set; }
@ -111,7 +109,7 @@ namespace Ryujinx.Ava
private object _lockObject = new(); private object _lockObject = new();
public AppHost( public AppHost(
RendererControl renderer, RendererHost renderer,
InputManager inputManager, InputManager inputManager,
string applicationPath, string applicationPath,
VirtualFileSystem virtualFileSystem, VirtualFileSystem virtualFileSystem,
@ -128,7 +126,7 @@ namespace Ryujinx.Ava
_hideCursorOnIdle = ConfigurationState.Instance.HideCursorOnIdle; _hideCursorOnIdle = ConfigurationState.Instance.HideCursorOnIdle;
_lastCursorMoveTime = Stopwatch.GetTimestamp(); _lastCursorMoveTime = Stopwatch.GetTimestamp();
_glLogLevel = ConfigurationState.Instance.Logger.GraphicsDebugLevel; _glLogLevel = ConfigurationState.Instance.Logger.GraphicsDebugLevel;
_inputManager.SetMouseDriver(new AvaloniaMouseDriver(renderer)); _inputManager.SetMouseDriver(new AvaloniaMouseDriver(_parent, renderer));
_keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0"); _keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
NpadManager = _inputManager.CreateNpadManager(); NpadManager = _inputManager.CreateNpadManager();
@ -138,6 +136,9 @@ namespace Ryujinx.Ava
VirtualFileSystem = virtualFileSystem; VirtualFileSystem = virtualFileSystem;
ContentManager = contentManager; ContentManager = contentManager;
_chrono = new Stopwatch();
_ticksPerFrame = Stopwatch.Frequency / TargetFps;
if (ApplicationPath.StartsWith("@SystemContent")) if (ApplicationPath.StartsWith("@SystemContent"))
{ {
ApplicationPath = _parent.VirtualFileSystem.SwitchPathToSystemPath(ApplicationPath); ApplicationPath = _parent.VirtualFileSystem.SwitchPathToSystemPath(ApplicationPath);
@ -177,7 +178,7 @@ namespace Ryujinx.Ava
if (_renderer != null) if (_renderer != null)
{ {
double scale = _parent.PlatformImpl.RenderScaling; double scale = _parent.PlatformImpl.RenderScaling;
_renderer.Window.SetSize((int)(size.Width * scale), (int)(size.Height * scale)); _renderer.Window?.SetSize((int)(size.Width * scale), (int)(size.Height * scale));
} }
} }
@ -335,8 +336,6 @@ namespace Ryujinx.Ava
return; return;
} }
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface.Display.ChangeVSyncMode(true);
_isStopped = true; _isStopped = true;
_isActive = false; _isActive = false;
} }
@ -376,6 +375,8 @@ namespace Ryujinx.Ava
_gpuCancellationTokenSource.Cancel(); _gpuCancellationTokenSource.Cancel();
_gpuCancellationTokenSource.Dispose(); _gpuCancellationTokenSource.Dispose();
_chrono.Stop();
} }
public void DisposeGpu() public void DisposeGpu()
@ -389,8 +390,7 @@ namespace Ryujinx.Ava
Renderer?.MakeCurrent(); Renderer?.MakeCurrent();
Device.DisposeGpu(); Device.DisposeGpu();
Renderer?.DestroyBackgroundContext();
Renderer?.MakeCurrent(null); Renderer?.MakeCurrent(null);
} }
@ -596,16 +596,11 @@ namespace Ryujinx.Ava
IRenderer renderer; IRenderer renderer;
if (Program.UseVulkan) if (Renderer.IsVulkan)
{ {
var vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>(); string preferredGpu = ConfigurationState.Instance.Graphics.PreferredGpu.Value;
renderer = new VulkanRenderer(vulkan.Instance.InternalHandle, renderer = new VulkanRenderer(Renderer.CreateVulkanSurface, VulkanHelper.GetRequiredInstanceExtensions, preferredGpu);
vulkan.MainSurface.Device.InternalHandle,
vulkan.PhysicalDevice.InternalHandle,
vulkan.MainSurface.Device.Queue.InternalHandle,
vulkan.PhysicalDevice.QueueFamilyIndex,
vulkan.MainSurface.Device.Lock);
} }
else else
{ {
@ -778,11 +773,7 @@ namespace Ryujinx.Ava
{ {
Width = (int)e.Width; Width = (int)e.Width;
Height = (int)e.Height; Height = (int)e.Height;
SetRendererWindowSize(e);
if (!Program.UseVulkan)
{
SetRendererWindowSize(e);
}
} }
private void MainLoop() private void MainLoop()
@ -822,12 +813,10 @@ namespace Ryujinx.Ava
_renderer.ScreenCaptured += Renderer_ScreenCaptured; _renderer.ScreenCaptured += Renderer_ScreenCaptured;
(_renderer as OpenGLRenderer)?.InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext((Renderer as OpenGLRendererControl).GameContext)); (_renderer as OpenGLRenderer)?.InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext(Renderer.GetContext()));
Renderer.MakeCurrent(); Renderer.MakeCurrent();
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface?.Display?.ChangeVSyncMode(Device.EnableDeviceVsync);
Device.Gpu.Renderer.Initialize(_glLogLevel); Device.Gpu.Renderer.Initialize(_glLogLevel);
Width = (int)Renderer.Bounds.Width; Width = (int)Renderer.Bounds.Width;
@ -835,16 +824,20 @@ namespace Ryujinx.Ava
_renderer.Window.SetSize((int)(Width * _parent.PlatformImpl.RenderScaling), (int)(Height * _parent.PlatformImpl.RenderScaling)); _renderer.Window.SetSize((int)(Width * _parent.PlatformImpl.RenderScaling), (int)(Height * _parent.PlatformImpl.RenderScaling));
_chrono.Start();
Device.Gpu.Renderer.RunLoop(() => Device.Gpu.Renderer.RunLoop(() =>
{ {
Device.Gpu.SetGpuThread(); Device.Gpu.SetGpuThread();
Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token); Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
Translator.IsReadyForTranslation.Set(); Translator.IsReadyForTranslation.Set();
Renderer.Start();
while (_isActive) while (_isActive)
{ {
_ticks += _chrono.ElapsedTicks;
_chrono.Restart();
if (Device.WaitFifo()) if (Device.WaitFifo())
{ {
Device.Statistics.RecordFifoStart(); Device.Statistics.RecordFifoStart();
@ -860,19 +853,20 @@ namespace Ryujinx.Ava
_parent.SwitchToGameControl(); _parent.SwitchToGameControl();
} }
Device.PresentFrame(Present); Device.PresentFrame(() => Renderer?.SwapBuffers());
}
if (_ticks >= _ticksPerFrame)
{
UpdateStatus();
} }
} }
Renderer.Stop();
}); });
Renderer?.MakeCurrent(null); Renderer?.MakeCurrent(null);
Renderer.SizeChanged -= Window_SizeChanged;
} }
private void Present(object image) public void UpdateStatus()
{ {
// Run a status update only when a frame is to be drawn. This prevents from updating the ui and wasting a render when no frame is queued // Run a status update only when a frame is to be drawn. This prevents from updating the ui and wasting a render when no frame is queued
string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? LocaleManager.Instance["Docked"] : LocaleManager.Instance["Handheld"]; string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? LocaleManager.Instance["Docked"] : LocaleManager.Instance["Handheld"];
@ -885,25 +879,13 @@ namespace Ryujinx.Ava
StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs( StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
Device.EnableDeviceVsync, Device.EnableDeviceVsync,
Device.GetVolume(), LocaleManager.Instance["VolumeShort"] + $": {(int)(Device.GetVolume() * 100)}%",
Program.UseVulkan ? "Vulkan" : "OpenGL", Renderer.IsVulkan ? "Vulkan" : "OpenGL",
dockedMode, dockedMode,
ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(), ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(),
LocaleManager.Instance["Game"] + $": {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)", LocaleManager.Instance["Game"] + $": {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
$"FIFO: {Device.Statistics.GetFifoPercent():00.00} %", $"FIFO: {Device.Statistics.GetFifoPercent():00.00} %",
$"GPU: {_renderer.GetHardwareInfo().GpuVendor}")); $"GPU: {_renderer.GetHardwareInfo().GpuVendor}"));
if (Program.UseVulkan)
{
var platformInterface = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
if (platformInterface.MainSurface.Display.IsSurfaceChanged())
{
SetRendererWindowSize(new Size(Width, Height));
return;
}
}
Renderer.Present(image);
} }
public async Task ShowExitPrompt() public async Task ShowExitPrompt()
@ -985,8 +967,6 @@ namespace Ryujinx.Ava
case KeyboardHotkeyState.ToggleVSync: case KeyboardHotkeyState.ToggleVSync:
Device.EnableDeviceVsync = !Device.EnableDeviceVsync; Device.EnableDeviceVsync = !Device.EnableDeviceVsync;
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface?.Display?.ChangeVSyncMode(Device.EnableDeviceVsync);
break; break;
case KeyboardHotkeyState.Screenshot: case KeyboardHotkeyState.Screenshot:
ScreenshotRequested = true; ScreenshotRequested = true;

View File

@ -20,7 +20,7 @@
"MenuBarOptionsManageUserProfiles": "_Profilverwaltung", "MenuBarOptionsManageUserProfiles": "_Profilverwaltung",
"MenuBarActions": "_Aktionen", "MenuBarActions": "_Aktionen",
"MenuBarOptionsSimulateWakeUpMessage": "Aufwachnachricht", "MenuBarOptionsSimulateWakeUpMessage": "Aufwachnachricht",
"MenuBarActionsScanAmiibo": "Virtualisiere Amiibo", "MenuBarActionsScanAmiibo": "Scanne ein Amiibo",
"MenuBarTools": "_Werkzeuge", "MenuBarTools": "_Werkzeuge",
"MenuBarToolsInstallFirmware": "Firmware installieren", "MenuBarToolsInstallFirmware": "Firmware installieren",
"MenuBarFileToolsInstallFirmwareFromFile": "Installiere Firmware von einer XCI oder einer ZIP Datei", "MenuBarFileToolsInstallFirmwareFromFile": "Installiere Firmware von einer XCI oder einer ZIP Datei",
@ -52,8 +52,8 @@
"GameListContextMenuOpenModsDirectory": "Mod-Verzeichnis öffnen", "GameListContextMenuOpenModsDirectory": "Mod-Verzeichnis öffnen",
"GameListContextMenuOpenModsDirectoryToolTip": "Öffnet das Verzeichnis, welches Mods für die Spiele beinhaltet", "GameListContextMenuOpenModsDirectoryToolTip": "Öffnet das Verzeichnis, welches Mods für die Spiele beinhaltet",
"GameListContextMenuCacheManagement": "Cache Verwaltung", "GameListContextMenuCacheManagement": "Cache Verwaltung",
"GameListContextMenuCacheManagementPurgePptc": "PPTC Cache löschen", "GameListContextMenuCacheManagementPurgePptc": "PPTC als ungültig markieren",
"GameListContextMenuCacheManagementPurgePptcToolTip": "Löscht den PPTC Cache der Anwendung", "GameListContextMenuCacheManagementPurgePptcToolTip": "Markiert den PPTC als ungültig, sodass dieser beim nächsten Spielstart neu erstellt wird",
"GameListContextMenuCacheManagementPurgeShaderCache": "Shader Cache löschen", "GameListContextMenuCacheManagementPurgeShaderCache": "Shader Cache löschen",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Löscht den Shader Cache der Anwendung", "GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Löscht den Shader Cache der Anwendung",
"GameListContextMenuCacheManagementOpenPptcDirectory": "PPTC Verzeichnis öffnen", "GameListContextMenuCacheManagementOpenPptcDirectory": "PPTC Verzeichnis öffnen",
@ -109,21 +109,21 @@
"SettingsTabSystemSystemLanguageTraditionalChinese": "Traditionelles Chinesisch", "SettingsTabSystemSystemLanguageTraditionalChinese": "Traditionelles Chinesisch",
"SettingsTabSystemSystemTimeZone": "System Zeitzone:", "SettingsTabSystemSystemTimeZone": "System Zeitzone:",
"SettingsTabSystemSystemTime": "System Zeit:", "SettingsTabSystemSystemTime": "System Zeit:",
"SettingsTabSystemEnableVsync": "Aktiviere VSync", "SettingsTabSystemEnableVsync": "VSync",
"SettingsTabSystemEnablePptc": "Aktiviere PPTC Cache (Profiled presistent translastion cache)", "SettingsTabSystemEnablePptc": "PPTC Cache (Profiled Persistent Translation Cache)",
"SettingsTabSystemEnableFsIntegrityChecks": "Aktiviere die FS Integritätsprüfung", "SettingsTabSystemEnableFsIntegrityChecks": "FS Integritätsprüfung",
"SettingsTabSystemAudioBackend": "Audio-Backend:", "SettingsTabSystemAudioBackend": "Audio-Backend:",
"SettingsTabSystemAudioBackendDummy": "Dummy", "SettingsTabSystemAudioBackendDummy": "Dummy",
"SettingsTabSystemAudioBackendOpenAL": "OpenAL", "SettingsTabSystemAudioBackendOpenAL": "OpenAL",
"SettingsTabSystemAudioBackendSoundIO": "SoundIO", "SettingsTabSystemAudioBackendSoundIO": "SoundIO",
"SettingsTabSystemAudioBackendSDL2": "SDL2", "SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemHacks": "Hacks", "SettingsTabSystemHacks": "Hacks",
"SettingsTabSystemHacksNote": " (Können Fehler verursachen)", "SettingsTabSystemHacksNote": " (Kann Fehler verursachen)",
"SettingsTabSystemExpandDramSize": "Erweitere DRAM Größe auf 6GB", "SettingsTabSystemExpandDramSize": "Erweitere DRAM Größe auf 6GB",
"SettingsTabSystemIgnoreMissingServices": "Ignoriere fehlende Dienste", "SettingsTabSystemIgnoreMissingServices": "Ignoriere fehlende Dienste",
"SettingsTabGraphics": "Grafik", "SettingsTabGraphics": "Grafik",
"SettingsTabGraphicsAPI": "Grafik-API", "SettingsTabGraphicsAPI": "Grafik-API",
"SettingsTabGraphicsEnableShaderCache": "Aktiviere den Shader Cache", "SettingsTabGraphicsEnableShaderCache": "Shader Cache",
"SettingsTabGraphicsAnisotropicFiltering": "Anisotrope Filterung:", "SettingsTabGraphicsAnisotropicFiltering": "Anisotrope Filterung:",
"SettingsTabGraphicsAnisotropicFilteringAuto": "Auto", "SettingsTabGraphicsAnisotropicFilteringAuto": "Auto",
"SettingsTabGraphicsAnisotropicFiltering2x": "2x", "SettingsTabGraphicsAnisotropicFiltering2x": "2x",
@ -185,9 +185,9 @@
"ControllerSettingsControllerType": "Controller Typ", "ControllerSettingsControllerType": "Controller Typ",
"ControllerSettingsControllerTypeHandheld": "Handheld", "ControllerSettingsControllerTypeHandheld": "Handheld",
"ControllerSettingsControllerTypeProController": "Pro Controller", "ControllerSettingsControllerTypeProController": "Pro Controller",
"ControllerSettingsControllerTypeJoyConPair": "JoyCon Paar", "ControllerSettingsControllerTypeJoyConPair": "Joy-Con Paar",
"ControllerSettingsControllerTypeJoyConLeft": "JoyCon Links", "ControllerSettingsControllerTypeJoyConLeft": "Joy-Con Links",
"ControllerSettingsControllerTypeJoyConRight": "JoyCon Rechts", "ControllerSettingsControllerTypeJoyConRight": "Joy-Con Rechts",
"ControllerSettingsProfile": "Profil", "ControllerSettingsProfile": "Profil",
"ControllerSettingsProfileDefault": "Default", "ControllerSettingsProfileDefault": "Default",
"ControllerSettingsLoad": "Laden", "ControllerSettingsLoad": "Laden",
@ -212,8 +212,8 @@
"ControllerSettingsLStickLeft": "Links", "ControllerSettingsLStickLeft": "Links",
"ControllerSettingsLStickRight": "Rechts", "ControllerSettingsLStickRight": "Rechts",
"ControllerSettingsLStickStick": "Analogstick", "ControllerSettingsLStickStick": "Analogstick",
"ControllerSettingsLStickInvertXAxis": "Invertiert X-Achse", "ControllerSettingsLStickInvertXAxis": "X-Achse invertieren",
"ControllerSettingsLStickInvertYAxis": "Invertiert Y-Achse", "ControllerSettingsLStickInvertYAxis": "Y-Achse invertieren",
"ControllerSettingsLStickDeadzone": "Deadzone:", "ControllerSettingsLStickDeadzone": "Deadzone:",
"ControllerSettingsRStick": "Rechter Analogstick", "ControllerSettingsRStick": "Rechter Analogstick",
"ControllerSettingsRStickButton": "R3", "ControllerSettingsRStickButton": "R3",
@ -222,8 +222,8 @@
"ControllerSettingsRStickLeft": "Links", "ControllerSettingsRStickLeft": "Links",
"ControllerSettingsRStickRight": "Rechts", "ControllerSettingsRStickRight": "Rechts",
"ControllerSettingsRStickStick": "Analogstick", "ControllerSettingsRStickStick": "Analogstick",
"ControllerSettingsRStickInvertXAxis": "Invertiert X-Achse", "ControllerSettingsRStickInvertXAxis": "X-Achse invertieren",
"ControllerSettingsRStickInvertYAxis": "Invertiert Y-Achse", "ControllerSettingsRStickInvertYAxis": "Y-Achse invertieren",
"ControllerSettingsRStickDeadzone": "Deadzone:", "ControllerSettingsRStickDeadzone": "Deadzone:",
"ControllerSettingsTriggersLeft": "Linker Trigger", "ControllerSettingsTriggersLeft": "Linker Trigger",
"ControllerSettingsTriggersRight": "Rechter Trigger", "ControllerSettingsTriggersRight": "Rechter Trigger",
@ -246,7 +246,7 @@
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "CemuHook kompatible Bewegungssteuerung", "ControllerSettingsMotionUseCemuhookCompatibleMotion": "CemuHook kompatible Bewegungssteuerung",
"ControllerSettingsMotionControllerSlot": "Controller Slot:", "ControllerSettingsMotionControllerSlot": "Controller Slot:",
"ControllerSettingsMotionMirrorInput": "Spiegele Eingabe", "ControllerSettingsMotionMirrorInput": "Spiegele Eingabe",
"ControllerSettingsMotionRightJoyConSlot": "Rechter JoyCon Slot:", "ControllerSettingsMotionRightJoyConSlot": "Rechter Joy-Con Slot:",
"ControllerSettingsMotionServerHost": "Server Host:", "ControllerSettingsMotionServerHost": "Server Host:",
"ControllerSettingsMotionGyroSensitivity": "Gyro Empfindlichkeit:", "ControllerSettingsMotionGyroSensitivity": "Gyro Empfindlichkeit:",
"ControllerSettingsMotionGyroDeadzone": "Gyro Deadzone:", "ControllerSettingsMotionGyroDeadzone": "Gyro Deadzone:",
@ -256,8 +256,8 @@
"UserProfilesSaveProfileName": "Profilname speichern", "UserProfilesSaveProfileName": "Profilname speichern",
"UserProfilesChangeProfileImage": "Profilbild ändern", "UserProfilesChangeProfileImage": "Profilbild ändern",
"UserProfilesAvailableUserProfiles": "Verfügbare Profile:", "UserProfilesAvailableUserProfiles": "Verfügbare Profile:",
"UserProfilesAddNewProfile": "Neues Profil hinzufügen", "UserProfilesAddNewProfile": "Neues Profil",
"UserProfilesDeleteSelectedProfile": "Ausgewähltes Profil löschen", "UserProfilesDeleteSelectedProfile": "Profil löschen",
"UserProfilesClose": "Schließen", "UserProfilesClose": "Schließen",
"ProfileImageSelectionTitle": "Auswahl des Profilbildes", "ProfileImageSelectionTitle": "Auswahl des Profilbildes",
"ProfileImageSelectionHeader": "Wähle ein Profilbild aus", "ProfileImageSelectionHeader": "Wähle ein Profilbild aus",
@ -281,17 +281,17 @@
"MenuBarFileToolsHideUi": "Verstecke UI", "MenuBarFileToolsHideUi": "Verstecke UI",
"GameListContextMenuToggleFavorite": "Als Favoriten hinzufügen/entfernen", "GameListContextMenuToggleFavorite": "Als Favoriten hinzufügen/entfernen",
"GameListContextMenuToggleFavoriteToolTip": "Aktiviert den Favoriten-Status des Spiels", "GameListContextMenuToggleFavoriteToolTip": "Aktiviert den Favoriten-Status des Spiels",
"SettingsTabGeneralTheme": "Thema", "SettingsTabGeneralTheme": "Design",
"SettingsTabGeneralThemeCustomTheme": "Verzeichnis für benutzerdefiniertes Thema", "SettingsTabGeneralThemeCustomTheme": "Pfad für das benutzerdefinierte Design",
"SettingsTabGeneralThemeBaseStyle": "Farbschema", "SettingsTabGeneralThemeBaseStyle": "Farbschema",
"SettingsTabGeneralThemeBaseStyleDark": "Dunkel", "SettingsTabGeneralThemeBaseStyleDark": "Dunkel",
"SettingsTabGeneralThemeBaseStyleLight": "Hell", "SettingsTabGeneralThemeBaseStyleLight": "Hell",
"SettingsTabGeneralThemeEnableCustomTheme": "Benutzerdefiniertes Thema", "SettingsTabGeneralThemeEnableCustomTheme": "Design für die Emulator-Benutzeroberfläche",
"ButtonBrowse": "Durchsuchen", "ButtonBrowse": "Durchsuchen",
"ControllerSettingsConfigureGeneral": "Konfigurieren", "ControllerSettingsConfigureGeneral": "Konfigurieren",
"ControllerSettingsRumble": "Vibration", "ControllerSettingsRumble": "Vibration",
"ControllerSettingsRumbleStrongMultiplier": "Starke Vibration - Multiplikator", "ControllerSettingsRumbleStrongMultiplier": "Starker Vibrations-Multiplikator",
"ControllerSettingsRumbleWeakMultiplier": "Schwache Vibration - Multiplikator", "ControllerSettingsRumbleWeakMultiplier": "Schwacher Vibrations-Multiplikator",
"DialogMessageSaveNotAvailableMessage": "Es existieren keine Speicherdaten für {0} [{1:x16}]", "DialogMessageSaveNotAvailableMessage": "Es existieren keine Speicherdaten für {0} [{1:x16}]",
"DialogMessageSaveNotAvailableCreateSaveMessage": "Soll Ryujinx Speicherdaten für dieses Spiel erstellen?", "DialogMessageSaveNotAvailableCreateSaveMessage": "Soll Ryujinx Speicherdaten für dieses Spiel erstellen?",
"DialogConfirmationTitle": "Ryujinx - Bestätigung", "DialogConfirmationTitle": "Ryujinx - Bestätigung",
@ -328,7 +328,7 @@
"DialogUpdaterDirtyBuildMessage": "Inoffizielle Versionen von Ryujinx können nicht aktualisiert werden", "DialogUpdaterDirtyBuildMessage": "Inoffizielle Versionen von Ryujinx können nicht aktualisiert werden",
"DialogUpdaterDirtyBuildSubMessage": "Lade Ryujinx bitte von hier herunter, um eine unterstützte Version zu erhalten: https://ryujinx.org/", "DialogUpdaterDirtyBuildSubMessage": "Lade Ryujinx bitte von hier herunter, um eine unterstützte Version zu erhalten: https://ryujinx.org/",
"DialogRestartRequiredMessage": "Neustart erforderlich", "DialogRestartRequiredMessage": "Neustart erforderlich",
"DialogThemeRestartMessage": "Das Thema wurde gespeichert. Ein Neustart ist erforderlich, um das Thema anzuwenden.", "DialogThemeRestartMessage": "Das Design wurde gespeichert. Ein Neustart ist erforderlich, um das Design anzuwenden.",
"DialogThemeRestartSubMessage": "Jetzt neu starten?", "DialogThemeRestartSubMessage": "Jetzt neu starten?",
"DialogFirmwareInstallEmbeddedMessage": "Die in diesem Spiel enthaltene Firmware installieren? (Firmware {0})", "DialogFirmwareInstallEmbeddedMessage": "Die in diesem Spiel enthaltene Firmware installieren? (Firmware {0})",
"DialogFirmwareInstallEmbeddedSuccessMessage": "Es wurde keine installierte Firmware gefunden, aber Ryujinx konnte die Firmware {0} aus dem bereitgestellten Spiel installieren.\nRyujinx wird nun gestartet.", "DialogFirmwareInstallEmbeddedSuccessMessage": "Es wurde keine installierte Firmware gefunden, aber Ryujinx konnte die Firmware {0} aus dem bereitgestellten Spiel installieren.\nRyujinx wird nun gestartet.",
@ -350,7 +350,7 @@
"DialogProfileDeleteProfileTitle": "Profil löschen", "DialogProfileDeleteProfileTitle": "Profil löschen",
"DialogProfileDeleteProfileMessage": "Diese Aktion kann nicht rückgängig gemacht werden. Wirklich fortfahren?", "DialogProfileDeleteProfileMessage": "Diese Aktion kann nicht rückgängig gemacht werden. Wirklich fortfahren?",
"DialogWarning": "Warnung", "DialogWarning": "Warnung",
"DialogPPTCDeletionMessage": "Du bist dabei, den PPTC Cache zu löschen für :\n\n{0}\n\nWirklich fortfahren?", "DialogPPTCDeletionMessage": "Du bist dabei den PPTC für das folgende Spiel als ungültig zu markieren:\n\n{0}\n\nWirklich fortfahren?",
"DialogPPTCDeletionErrorMessage": "Fehler bei der Löschung des PPTC Caches bei {0}: {1}", "DialogPPTCDeletionErrorMessage": "Fehler bei der Löschung des PPTC Caches bei {0}: {1}",
"DialogShaderDeletionMessage": "Du bist dabei, den Shader Cache zu löschen für :\n\n{0}\n\nWirklich fortfahren?", "DialogShaderDeletionMessage": "Du bist dabei, den Shader Cache zu löschen für :\n\n{0}\n\nWirklich fortfahren?",
"DialogShaderDeletionErrorMessage": "Es ist ein Fehler bei der Löschung des Shader Caches bei {0}: {1} aufgetreten", "DialogShaderDeletionErrorMessage": "Es ist ein Fehler bei der Löschung des Shader Caches bei {0}: {1} aufgetreten",
@ -379,7 +379,7 @@
"DialogSettingsBackendThreadingWarningTitle": "Warnung - Render Threading", "DialogSettingsBackendThreadingWarningTitle": "Warnung - Render Threading",
"DialogSettingsBackendThreadingWarningMessage": "Ryujinx muss muss neu gestartet werden, damit die Änderungen wirksam werden. Abhängig von dem Betriebssystem muss möglicherweise das Multithreading des Treibers manuell deaktiviert werden, wenn Ryujinx verwendet wird.", "DialogSettingsBackendThreadingWarningMessage": "Ryujinx muss muss neu gestartet werden, damit die Änderungen wirksam werden. Abhängig von dem Betriebssystem muss möglicherweise das Multithreading des Treibers manuell deaktiviert werden, wenn Ryujinx verwendet wird.",
"SettingsTabGraphicsFeaturesOptions": "Erweiterungen", "SettingsTabGraphicsFeaturesOptions": "Erweiterungen",
"SettingsTabGraphicsBackendMultithreading": "Grafikbackend Multithreading:", "SettingsTabGraphicsBackendMultithreading": "Grafik-Backend Multithreading:",
"CommonAuto": "Auto", "CommonAuto": "Auto",
"CommonOff": "Aus", "CommonOff": "Aus",
"CommonOn": "An", "CommonOn": "An",
@ -416,52 +416,52 @@
"CommonFavorite": "Favoriten", "CommonFavorite": "Favoriten",
"OrderAscending": "Aufsteigend", "OrderAscending": "Aufsteigend",
"OrderDescending": "Absteigend", "OrderDescending": "Absteigend",
"SettingsTabGraphicsFeatures": "Erweiterungen & Verbesserungen", "SettingsTabGraphicsFeatures": "Erweiterungen",
"ErrorWindowTitle": "Fehler-Fenster", "ErrorWindowTitle": "Fehler-Fenster",
"ToggleDiscordTooltip": "Aktiviert/Deaktiviert Discord Rich Presence", "ToggleDiscordTooltip": "Zeige momentanes Spiel auf Discord",
"AddGameDirBoxTooltip": "Gibt das Spielverzeichnis an, das der Liste hinzuzufügt wird", "AddGameDirBoxTooltip": "Gibt das Spielverzeichnis an, das der Liste hinzuzufügt wird",
"AddGameDirTooltip": "Fügt ein neues Spielverzeichnis hinzu", "AddGameDirTooltip": "Fügt ein neues Spielverzeichnis hinzu",
"RemoveGameDirTooltip": "Entfernt das ausgewähltes Spielverzeichnis", "RemoveGameDirTooltip": "Entfernt das ausgewähltes Spielverzeichnis",
"CustomThemeCheckTooltip": "Aktiviert/Deaktiviert die benutzerdefinierten Thema in dem GUI", "CustomThemeCheckTooltip": "Verwende ein eigenes Design für die Emulator-Benutzeroberfläche",
"CustomThemePathTooltip": " Gibt das Verzeichnis zum benutzerdefinierten GUI Thema an", "CustomThemePathTooltip": "Gibt den Pfad zum Design für die Emulator-Benutzeroberfläche an",
"CustomThemeBrowseTooltip": "Ermöglicht die Suche nach benutzerdefinierten GUI Thema", "CustomThemeBrowseTooltip": "Ermöglicht die Suche nach einem benutzerdefinierten Design für die Emulator-Benutzeroberfläche",
"DockModeToggleTooltip": "Aktiviert/Deaktiviert den Docked Mode", "DockModeToggleTooltip": "Im gedockten Modus verhält sich das emulierte System wie eine Nintendo Switch im TV Modus. Dies verbessert die grafische Qualität der meisten Spiele. Umgekehrt führt die Deaktivierung dazu, dass sich das emulierte System wie eine Nintendo Switch im Handheld Modus verhält, was die Grafikqualität beeinträchtigt.\n\nKonfiguriere das Eingabegerät für Spieler 1, um im Docked Modus zu spielen; konfiguriere das Controllerprofil via der Handheld Option, wenn geplant wird den Handheld Modus zu nutzen.\n\nIm Zweifelsfall AN lassen.",
"DirectKeyboardTooltip": "Aktiviert/Deaktiviert den \"Direkter Tastaturzugriff (HID) Unterstützung\" (Ermöglicht die Benutzung der Tastaur als Eingabegerät in Spielen)", "DirectKeyboardTooltip": "Aktiviert/Deaktiviert den \"Direkter Tastaturzugriff (HID) Unterstützung\" (Ermöglicht die Benutzung der Tastaur als Eingabegerät in Spielen)",
"DirectMouseTooltip": "Aktiviert/Deaktiviert den \"Direkten Mauszugriff (HID) Unterstützung\" (Ermöglicht die Benutzung der Maus als Eingabegerät in Spielen)", "DirectMouseTooltip": "Aktiviert/Deaktiviert den \"Direkten Mauszugriff (HID) Unterstützung\" (Ermöglicht die Benutzung der Maus als Eingabegerät in Spielen)",
"RegionTooltip": "Ändert die Systemregion", "RegionTooltip": "Ändert die Systemregion",
"LanguageTooltip": "Ändert die Systemsprache", "LanguageTooltip": "Ändert die Systemsprache",
"TimezoneTooltip": "Ändert die Systemzeitzone", "TimezoneTooltip": "Ändert die Systemzeitzone",
"TimeTooltip": "Ändert die Systemzeit", "TimeTooltip": "Ändert die Systemzeit",
"VSyncToggleTooltip": "Aktiviert/Deaktiviert die Vertikale Synchronisierung", "VSyncToggleTooltip": "Vertikale Synchronisierung der emulierten Konsole. Diese Option ist ein Frame-Limiter für die meisten Spiele; die Deaktivierung kann dazu führen, dass Spiele mit höherer Geschwindigkeit laufen, Ladebildschirme länger benötigen oder hängen bleiben.\n\nKann beim Spielen mit einem frei wählbaren Hotkey ein- und ausgeschaltet werden.\n\nIm Zweifelsfall AN lassen.",
"PptcToggleTooltip": "Aktiviert/Deaktiviert den PPTC", "PptcToggleTooltip": "Speichert übersetzte JIT-Funktionen, sodass jene nicht jedes Mal übersetzt werden müssen, wenn das Spiel geladen wird.\n\nVerringert Stottern und die Zeit beim zweiten und den darauffolgenden Startvorgängen eines Spiels erheblich.\n\nIm Zweifelsfall AN lassen.",
"FsIntegrityToggleTooltip": "Aktiviert/Deaktiviert die Integritätsprüfung der Spieldateien", "FsIntegrityToggleTooltip": "Prüft beim Startvorgang auf beschädigte Dateien und zeigt bei beschädigten Dateien einen Hash-Fehler (Hash Error) im Log an.\n\nDiese Einstellung hat keinen Einfluss auf die Leistung und hilft bei der Fehlersuche.\n\nIm Zweifelsfall AN lassen.",
"AudioBackendTooltip": "Ändert das Audio-Backend", "AudioBackendTooltip": "Ändert das Backend, das zum Rendern von Audio verwendet wird.\n\nSDL2 ist das bevorzugte Audio-Backend, OpenAL und SoundIO sind als Alternativen vorhanden. Dummy wird keinen Audio-Output haben.\n\nIm Zweifelsfall SDL2 auswählen.",
"MemoryManagerTooltip": "Ändert wie der Gastspeicher abgebildet wird und wie auf ihn zugegriffen wird. Beinflusst die Leistung der emulierten CPU erheblich.", "MemoryManagerTooltip": "Ändert wie der Gastspeicher abgebildet wird und wie auf ihn zugegriffen wird. Beinflusst die Leistung der emulierten CPU erheblich.\n\nIm Zweifelsfall Host ungeprüft auswählen.",
"MemoryManagerSoftwareTooltip": "Verwendung einer Software-Seitentabelle für die Adressumsetzung. Höchste Genauigkeit, aber langsamste Leistung.", "MemoryManagerSoftwareTooltip": "Verwendung einer Software-Seitentabelle für die Adressumsetzung. Höchste Genauigkeit, aber langsamste Leistung.",
"MemoryManagerHostTooltip": "Direkte Zuordnung von Speicher im Host-Adressraum. Viel schnellere JIT-Kompilierung und Ausführung.", "MemoryManagerHostTooltip": "Direkte Zuordnung von Speicher im Host-Adressraum. Viel schnellere JIT-Kompilierung und Ausführung.",
"MemoryManagerUnsafeTooltip": "Direkte Zuordnung des Speichers, aber keine Maskierung der Adresse innerhalb des Gastadressraums vor dem Zugriff. Schneller, aber auf Kosten der Sicherheit. Die Gastanwendung kann von überall in Ryujinx auf den Speicher zugreifen, daher sollte in diesem Modus nur Programme ausgeführt werden denen vertraut wird.", "MemoryManagerUnsafeTooltip": "Direkte Zuordnung des Speichers, aber keine Maskierung der Adresse innerhalb des Gastadressraums vor dem Zugriff. Schneller, aber auf Kosten der Sicherheit. Die Gastanwendung kann von überall in Ryujinx auf den Speicher zugreifen, daher sollte in diesem Modus nur Programme ausgeführt werden denen vertraut wird.",
"DRamTooltip": "Erweitert den Speicher des emulierten Systems von 4 GB auf 6 GB", "DRamTooltip": "Erhöht den Arbeitsspeicher des emulierten Systems von 4 GB auf 6 GB.\n\nDies ist nur für Texturenpakete mit höherer Auflösung oder Mods mit 4K-Auflösung nützlich. Diese Option verbessert NICHT die Leistung.\n\nIm Zweifelsfall AUS lassen.",
"IgnoreMissingServicesTooltip": "Aktiviert/Deaktiviert die 'Ignoriere fehlende Dienste' Option", "IgnoreMissingServicesTooltip": "Durch diese Option werden nicht implementierte Dienste der Switch-Firmware ignoriert. Dies kann dabei helfen, Abstürze beim Starten bestimmter Spiele zu umgehen.\n\nIm Zweifelsfall AUS lassen.",
"GraphicsBackendThreadingTooltip": "Aktiviert das Grafikbackend Multithreading", "GraphicsBackendThreadingTooltip": "Führt Grafik-Backend Befehle auf einem zweiten Thread aus.\n\nDies beschleunigt die Shader-Kompilierung, reduziert Stottern und verbessert die Leistung auf GPU-Treibern ohne eigene Multithreading-Unterstützung. Geringfügig bessere Leistung bei Treibern mit Multithreading.\n\nIm Zweifelsfall auf AUTO stellen.",
"GalThreadingTooltip": "Führt Grafikbackendbefehle auf einem zweiten Thread aus. Ermöglicht Multithreading bei der Shader Kompilierung zur Laufzeit, reduziert Stottern und verbessert die Leistung bei Treibern ohne eigene Multithreading Unterstützung. Geringfügig abweichende Spitzenleistung bei Treibern mit Multithreading. Ryujinx muss möglicherweise neu gestartet werden, um das in den Treiber integrierte Multithreading korrekt zu deaktivieren, oder es muss manuell getan werden, um die beste Leistung zu erzielen.", "GalThreadingTooltip": "Führt Grafik-Backend Befehle auf einem zweiten Thread aus.\n\nDies Beschleunigt die Shader-Kompilierung, reduziert Stottern und verbessert die Leistung auf GPU-Treibern ohne eigene Multithreading-Unterstützung. Geringfügig bessere Leistung bei Treibern mit Multithreading.\n\nIm Zweifelsfall auf auf AUTO stellen.",
"ShaderCacheToggleTooltip": "Aktiviert/Deaktiviert Shader Cache", "ShaderCacheToggleTooltip": "Speichert einen persistenten Shader Cache, der das Stottern bei nachfolgenden Durchläufen reduziert.\n\nIm Zweifelsfall AN lassen.",
"ResolutionScaleTooltip": "Wendet die Auflösungsskalierung auf anwendbare Render Ziele", "ResolutionScaleTooltip": "Wendet die Auflösungsskalierung auf anwendbare Render Ziele",
"ResolutionScaleEntryTooltip": "Fließkomma Auflösungsskalierung, wie 1,5.\n Bei nicht ganzzahligen Werten ist die Wahrscheinlichkeit größer, dass Probleme entstehen, die auch zum Absturz führen können.", "ResolutionScaleEntryTooltip": "Fließkomma Auflösungsskalierung, wie 1,5.\n Bei nicht ganzzahligen Werten ist die Wahrscheinlichkeit größer, dass Probleme entstehen, die auch zum Absturz führen können.",
"AnisotropyTooltip": "Stufe der Anisotropen Filterung (Auf Auto setzen, um den vom Spiel geforderten Wert zu verwenden)", "AnisotropyTooltip": "Stufe der Anisotropen Filterung (Auf Auto setzen, um den vom Spiel geforderten Wert zu verwenden)",
"AspectRatioTooltip": "Auf das Renderer-Fenster angewandtes Seitenverhältnis.", "AspectRatioTooltip": "Auf das Renderer-Fenster angewandtes Seitenverhältnis.",
"ShaderDumpPathTooltip": "Grafik-Shader-Dump-Pfad", "ShaderDumpPathTooltip": "Grafik-Shader-Dump-Pfad",
"FileLogTooltip": "Aktiviert/Deaktiviert die Erstellung und Speicherung eines Logs", "FileLogTooltip": "Speichert die Konsolenausgabe in einer Log-Datei auf der Festplatte. Hat keinen Einfluss auf die Leistung.",
"StubLogTooltip": "Aktiviert die Ausgabe von Stub-Logs in der Konsole", "StubLogTooltip": "Ausgabe von Stub-Logs in der Konsole. Hat keinen Einfluss auf die Leistung.",
"InfoLogTooltip": "Aktiviert die Ausgabe von Info-Logs in der Konsole", "InfoLogTooltip": "Ausgabe von Info-Logs in der Konsole. Hat keinen Einfluss auf die Leistung.",
"WarnLogTooltip": "Aktiviert die Ausgabe von Warn-Logs in der Konsole", "WarnLogTooltip": "Ausgabe von Warn-Logs in der Konsole. Hat keinen Einfluss auf die Leistung.",
"TraceLogTooltip": "Aktiviert die Ausgabe von Trace-Log in der Konsole", "TraceLogTooltip": "Ausgabe von Trace-Log in der Konsole. Hat keinen Einfluss auf die Leistung.",
"ErrorLogTooltip": "Aktiviert die Ausgabe von Fehler-Logs in der Konsole", "ErrorLogTooltip": "Ausgabe von Fehler-Logs in der Konsole. Hat keinen Einfluss auf die Leistung.",
"GuestLogTooltip": "Aktiviert die Ausgabe von Gast-Logs in der Konsole", "GuestLogTooltip": "Ausgabe von Gast-Logs in der Konsole. Hat keinen Einfluss auf die Leistung.",
"FileAccessLogTooltip": "Aktiviert die Ausgabe von FS-Zugriff-Logs in der Konsole", "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", "FSAccessLogModeTooltip": "Aktiviert die Ausgabe des FS-Zugriff-Logs in der Konsole. Mögliche Modi sind 0-3",
"DeveloperOptionTooltip": "Mit Vorsicht verwenden", "DeveloperOptionTooltip": "Mit Vorsicht verwenden",
"OpenGlLogLevel": "Erfordert die Aktivierung der entsprechenden Log-Level", "OpenGlLogLevel": "Erfordert die Aktivierung der entsprechenden Log-Level",
"DebugLogTooltip": "Aktiviert das Dokumentierern von Debug-Protokollmeldungen", "DebugLogTooltip": "Ausgabe von Debug-Logs in der Konsole.\n\nVerwende diese Option nur auf ausdrückliche Anweisung von Ryujinx Entwicklern, da sie das Lesen der Protokolle erschwert und die Leistung des Emulators verschlechtert.",
"LoadApplicationFileTooltip": "Öffnet die Dateiauswahl um Datei zu laden, welche mit der Switch kompatibel ist", "LoadApplicationFileTooltip": "Öffnet die Dateiauswahl um Datei zu laden, welche mit der Switch kompatibel ist",
"LoadApplicationFolderTooltip": "Öffnet die Dateiauswahl um ein Spiel zu laden, welches mit der Switch kompatibel ist", "LoadApplicationFolderTooltip": "Öffnet die Dateiauswahl um ein Spiel zu laden, welches mit der Switch kompatibel ist",
"OpenRyujinxFolderTooltip": "Öffnet den Ordner, der das Ryujinx Dateisystem enthält", "OpenRyujinxFolderTooltip": "Öffnet den Ordner, der das Ryujinx Dateisystem enthält",
@ -478,8 +478,8 @@
"AboutRyujinxContributorsButtonHeader": "Alle Mitwirkenden anzeigen", "AboutRyujinxContributorsButtonHeader": "Alle Mitwirkenden anzeigen",
"SettingsTabSystemAudioVolume" : "Lautstärke: ", "SettingsTabSystemAudioVolume" : "Lautstärke: ",
"AudioVolumeTooltip": "Ändert die Lautstärke", "AudioVolumeTooltip": "Ändert die Lautstärke",
"SettingsTabSystemEnableInternetAccess": "Aktiviert den Gast-Internet-Zugang", "SettingsTabSystemEnableInternetAccess": "Gast-Internet-Zugang/LAN Modus",
"EnableInternetAccessTooltip": "Aktiviert den Gast-Internet-Zugang. Die Anwendung verhält sich so, als ob die emulierte Switch-Konsole mit dem Internet verbunden wäre. Beachte, dass in einigen Fällen Anwendungen auch bei deaktivierter Option auf das Internet zugreifen können", "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",
"GameListContextMenuManageCheatToolTip": "Öffnet den Cheat-Manager", "GameListContextMenuManageCheatToolTip": "Öffnet den Cheat-Manager",
"GameListContextMenuManageCheat": "Cheats verwalten", "GameListContextMenuManageCheat": "Cheats verwalten",
"ControllerSettingsStickRange": "Bereich:", "ControllerSettingsStickRange": "Bereich:",
@ -491,11 +491,11 @@
"SettingsTabNetworkConnection": "Netwerkverbindung", "SettingsTabNetworkConnection": "Netwerkverbindung",
"SettingsTabCpuCache": "CPU-Cache", "SettingsTabCpuCache": "CPU-Cache",
"SettingsTabCpuMemory": "CPU-Speicher", "SettingsTabCpuMemory": "CPU-Speicher",
"DialogUpdaterFlatpakNotSupportedMessage": "Bitte Aktualisiere Ryujinx mit FlatHub", "DialogUpdaterFlatpakNotSupportedMessage": "Bitte aktualisiere Ryujinx mit FlatHub",
"UpdaterDisabledWarningTitle": "Updater deaktiviert!", "UpdaterDisabledWarningTitle": "Updater deaktiviert!",
"GameListContextMenuOpenSdModsDirectory": "Atmosphere-Mod-Verzeichnis öffnen", "GameListContextMenuOpenSdModsDirectory": "Atmosphere-Mod-Verzeichnis öffnen",
"GameListContextMenuOpenSdModsDirectoryToolTip": "Öffnet das alternative SD-Karten-Atmosphere-Verzeichnis, das die Mods der Anwendung enthält", "GameListContextMenuOpenSdModsDirectoryToolTip": "Öffnet das alternative SD-Karten-Atmosphere-Verzeichnis, das die Mods der Anwendung enthält. Dieser Ordner ist nützlich für Mods, die für einen gemoddete Switch erstellt worden sind.",
"ControllerSettingsRotate90": "Rotiert um 90°", "ControllerSettingsRotate90": "Um 90° rotieren",
"IconSize": "Cover Größe", "IconSize": "Cover Größe",
"IconSizeTooltip": "Ändert die Größe der Spiel-Cover", "IconSizeTooltip": "Ändert die Größe der Spiel-Cover",
"MenuBarOptionsShowConsole": "Zeige Konsole", "MenuBarOptionsShowConsole": "Zeige Konsole",
@ -546,17 +546,47 @@
"RyujinxUpdater": "Ryujinx - Updater", "RyujinxUpdater": "Ryujinx - Updater",
"SettingsTabHotkeys": "Tastatur Hotkeys", "SettingsTabHotkeys": "Tastatur Hotkeys",
"SettingsTabHotkeysHotkeys": "Tastatur Hotkeys", "SettingsTabHotkeysHotkeys": "Tastatur Hotkeys",
"SettingsTabHotkeysToggleVsyncHotkey": "Aktiviert/Deaktiviert VSync:", "SettingsTabHotkeysToggleVsyncHotkey": "VSync:",
"SettingsTabHotkeysScreenshotHotkey": "Screenshot:", "SettingsTabHotkeysScreenshotHotkey": "Screenshot:",
"SettingsTabHotkeysShowUiHotkey": "Zeige UI:", "SettingsTabHotkeysShowUiHotkey": "Zeige UI:",
"SettingsTabHotkeysPauseHotkey": "Pausieren:", "SettingsTabHotkeysPauseHotkey": "Pausieren:",
"SettingsTabHotkeysToggleMuteHotkey": "Stummschalten:", "SettingsTabHotkeysToggleMuteHotkey": "Stummschalten:",
"ControllerMotionTitle": "Bewegungssteuerung - Einstellungen", "ControllerMotionTitle": "Bewegungssteuerung - Einstellungen",
"ControllerRumbleTitle": "Vibration - Einstellungen", "ControllerRumbleTitle": "Vibration - Einstellungen",
"SettingsSelectThemeFileDialogTitle" : "Wähle ein benutzerdefiniertes Thema", "SettingsSelectThemeFileDialogTitle" : "Wähle ein Design für die Emulator-Benutzeroberfläche",
"SettingsXamlThemeFile" : "Xaml Thema-Datei", "SettingsXamlThemeFile" : "Xaml Design-Datei",
"SettingsTabGraphicsBackend" : "Grafik-Backend", "AvatarWindowTitle": "Profile verwalten - Avatar",
"GraphicsBackendTooltip" : "Ändert das Grafik-Backend", "Amiibo": "Amiibo",
"Unknown": "Unbekannt",
"Usage": "Nutzung",
"Writable": "Beschreibbar",
"SelectDlcDialogTitle": "DLC-Dateien auswählen",
"SelectUpdateDialogTitle": "Update-Datei auswählen",
"UserProfileWindowTitle": "Benutzerprofile verwalten",
"CheatWindowTitle": "Spiel-Cheats verwalten",
"DlcWindowTitle": "Spiel-DLC verwalten",
"UpdateWindowTitle": "Spiel-Updates verwalten",
"CheatWindowHeading": "Cheats verfügbar für {0} [{1}]",
"DlcWindowHeading": "DLC verfügbar für {0} [{1}]",
"UserProfilesEditProfile": "Profil bearbeiten",
"Cancel": "Abbrechen",
"Save": "Speichern",
"Discard": "Verwerfen",
"UserProfilesSetProfileImage": "Profilbild einrichten",
"UserProfileEmptyNameError": "Name ist erforderlich",
"UserProfileNoImageError": "Bitte ein Profilbild auswählen",
"GameUpdateWindowHeading": "Update verfügbar für {0} [{1}]",
"SettingsTabHotkeysResScaleUpHotkey": "Auflösung erhöhen:", "SettingsTabHotkeysResScaleUpHotkey": "Auflösung erhöhen:",
"SettingsTabHotkeysResScaleDownHotkey": "Auflösung vermindern:" "SettingsTabHotkeysResScaleDownHotkey": "Auflösung verringern:",
"UserProfilesName": "Name:",
"UserProfilesUserId" : "Benutzer Id:",
"SettingsTabGraphicsBackend": "Grafik-Backend:",
"SettingsTabGraphicsBackendTooltip": "Verwendendetes Grafik-Backend",
"SettingsEnableTextureRecompression": "Textur-Rekompression",
"SettingsEnableTextureRecompressionTooltip": "Komprimiert bestimmte Texturen, um den VRAM-Verbrauch zu reduzieren.\n\nEmpfohlen für die Verwendung von GPUs, die weniger als 4 GB VRAM haben.\n\nIm Zweifelsfall AUS lassen",
"SettingsTabGraphicsPreferredGpu": "Bevorzugte GPU:",
"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?"
} }

View File

@ -588,5 +588,6 @@
"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.", "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", "SettingsAppRequiredRestartMessage": "Ryujinx Restart Required",
"SettingsGpuBackendRestartMessage": "Graphics Backend or Gpu settings have been modified. This will require a restart to be applied", "SettingsGpuBackendRestartMessage": "Graphics Backend or Gpu settings have been modified. This will require a restart to be applied",
"SettingsGpuBackendRestartSubMessage": "Do you want to restart now?" "SettingsGpuBackendRestartSubMessage": "Do you want to restart now?",
"VolumeShort": "Vol"
} }

View File

@ -52,8 +52,8 @@
"GameListContextMenuOpenModsDirectory": "Modディレクトリを開く", "GameListContextMenuOpenModsDirectory": "Modディレクトリを開く",
"GameListContextMenuOpenModsDirectoryToolTip": "アプリケーションの Mod データを格納するディレクトリを開きます", "GameListContextMenuOpenModsDirectoryToolTip": "アプリケーションの Mod データを格納するディレクトリを開きます",
"GameListContextMenuCacheManagement": "キャッシュ管理", "GameListContextMenuCacheManagement": "キャッシュ管理",
"GameListContextMenuCacheManagementPurgePptc": "PPTC キャッシュを破棄", "GameListContextMenuCacheManagementPurgePptc": "PPTC を再構築",
"GameListContextMenuCacheManagementPurgePptcToolTip": "アプリケーションの PPTC キャッシュを破棄します", "GameListContextMenuCacheManagementPurgePptcToolTip": "次回のゲーム起動時に PPTC を再構築します",
"GameListContextMenuCacheManagementPurgeShaderCache": "シェーダキャッシュを破棄", "GameListContextMenuCacheManagementPurgeShaderCache": "シェーダキャッシュを破棄",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "アプリケーションのシェーダキャッシュを破棄します", "GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "アプリケーションのシェーダキャッシュを破棄します",
"GameListContextMenuCacheManagementOpenPptcDirectory": "PPTC ディレクトリを開く", "GameListContextMenuCacheManagementOpenPptcDirectory": "PPTC ディレクトリを開く",
@ -121,9 +121,9 @@
"SettingsTabSystemHacksNote": " (挙動が不安定になる可能性があります)", "SettingsTabSystemHacksNote": " (挙動が不安定になる可能性があります)",
"SettingsTabSystemExpandDramSize": "DRAMサイズを6GBに拡大", "SettingsTabSystemExpandDramSize": "DRAMサイズを6GBに拡大",
"SettingsTabSystemIgnoreMissingServices": "未実装サービスを無視", "SettingsTabSystemIgnoreMissingServices": "未実装サービスを無視",
"SettingsTabGraphics": "グラフィクス", "SettingsTabGraphics": "グラフィクス",
"SettingsTabGraphicsEnhancements": "拡張", "SettingsTabGraphicsAPI": "グラフィックスAPI",
"SettingsTabGraphicsEnableShaderCache": "シェーダキャッシュ", "SettingsTabGraphicsEnableShaderCache": "シェーダキャッシュを有効",
"SettingsTabGraphicsAnisotropicFiltering": "異方性フィルタリング:", "SettingsTabGraphicsAnisotropicFiltering": "異方性フィルタリング:",
"SettingsTabGraphicsAnisotropicFilteringAuto": "自動", "SettingsTabGraphicsAnisotropicFilteringAuto": "自動",
"SettingsTabGraphicsAnisotropicFiltering2x": "2x", "SettingsTabGraphicsAnisotropicFiltering2x": "2x",
@ -144,7 +144,7 @@
"SettingsTabGraphicsAspectRatio32x9": "32:9", "SettingsTabGraphicsAspectRatio32x9": "32:9",
"SettingsTabGraphicsAspectRatioStretch": "ウインドウサイズに合わせる", "SettingsTabGraphicsAspectRatioStretch": "ウインドウサイズに合わせる",
"SettingsTabGraphicsDeveloperOptions": "開発者向けオプション", "SettingsTabGraphicsDeveloperOptions": "開発者向けオプション",
"SettingsTabGraphicsShaderDumpPath": "グラフィクス シェーダダンプパス:", "SettingsTabGraphicsShaderDumpPath": "グラフィクス シェーダダンプパス:",
"SettingsTabLogging": "ロギング", "SettingsTabLogging": "ロギング",
"SettingsTabLoggingLogging": "ロギング", "SettingsTabLoggingLogging": "ロギング",
"SettingsTabLoggingEnableLoggingToFile": "ファイルへのロギングを有効", "SettingsTabLoggingEnableLoggingToFile": "ファイルへのロギングを有効",
@ -350,7 +350,7 @@
"DialogProfileDeleteProfileTitle": "プロファイルを削除中", "DialogProfileDeleteProfileTitle": "プロファイルを削除中",
"DialogProfileDeleteProfileMessage": "このアクションは元に戻せません. 本当に続けてよろしいですか?", "DialogProfileDeleteProfileMessage": "このアクションは元に戻せません. 本当に続けてよろしいですか?",
"DialogWarning": "警告", "DialogWarning": "警告",
"DialogPPTCDeletionMessage": "PPTC キャッシュを破棄しようとしています:\n\n{0}\n\n実行してよろしいですか?", "DialogPPTCDeletionMessage": "次回起動時に PPTC を再構築します:\n\n{0}\n\n実行してよろしいですか?",
"DialogPPTCDeletionErrorMessage": "PPTC キャッシュ破棄エラー {0}: {1}", "DialogPPTCDeletionErrorMessage": "PPTC キャッシュ破棄エラー {0}: {1}",
"DialogShaderDeletionMessage": "シェーダキャッシュを破棄しようとしています:\n\n{0}\n\n実行してよろしいですか?", "DialogShaderDeletionMessage": "シェーダキャッシュを破棄しようとしています:\n\n{0}\n\n実行してよろしいですか?",
"DialogShaderDeletionErrorMessage": "シェーダキャッシュ破棄エラー {0}: {1}", "DialogShaderDeletionErrorMessage": "シェーダキャッシュ破棄エラー {0}: {1}",
@ -379,7 +379,7 @@
"DialogSettingsBackendThreadingWarningTitle": "警告 - バックエンドスレッディング", "DialogSettingsBackendThreadingWarningTitle": "警告 - バックエンドスレッディング",
"DialogSettingsBackendThreadingWarningMessage": "このオプションの変更を完全に適用するには Ryujinx の再起動が必要です. プラットフォームによっては, Ryujinx のものを使用する前に手動でドライバ自身のマルチスレッディングを無効にする必要があるかもしれません.", "DialogSettingsBackendThreadingWarningMessage": "このオプションの変更を完全に適用するには Ryujinx の再起動が必要です. プラットフォームによっては, Ryujinx のものを使用する前に手動でドライバ自身のマルチスレッディングを無効にする必要があるかもしれません.",
"SettingsTabGraphicsFeaturesOptions": "機能", "SettingsTabGraphicsFeaturesOptions": "機能",
"SettingsTabGraphicsBackendMultithreading": "グラフィクスバックエンドのマルチスレッド実行:", "SettingsTabGraphicsBackendMultithreading": "グラフィクスバックエンドのマルチスレッド実行:",
"CommonAuto": "自動", "CommonAuto": "自動",
"CommonOff": "オフ", "CommonOff": "オフ",
"CommonOn": "オン", "CommonOn": "オン",
@ -425,7 +425,7 @@
"CustomThemeCheckTooltip": "エミュレータのメニュー外観を変更するためカスタム Avalonia テーマを使用します", "CustomThemeCheckTooltip": "エミュレータのメニュー外観を変更するためカスタム Avalonia テーマを使用します",
"CustomThemePathTooltip": "カスタム GUI テーマのパスです", "CustomThemePathTooltip": "カスタム GUI テーマのパスです",
"CustomThemeBrowseTooltip": "カスタム GUI テーマを参照します", "CustomThemeBrowseTooltip": "カスタム GUI テーマを参照します",
"DockModeToggleTooltip": "有効にすると,ドッキングされた Nintendo Switch をエミュレートします.多くのゲームではグラフィクス品質が向上します.\n無効にすると,携帯モードの Nintendo Switch をエミュレートします.グラフィクスの品質は低下します.\n\nドッキングモード有効ならプレイヤー1の,無効なら携帯の入力を設定してください.\n\nよくわからない場合はオンのままにしてください.", "DockModeToggleTooltip": "有効にすると,ドッキングされた Nintendo Switch をエミュレートします.多くのゲームではグラフィクス品質が向上します.\n無効にすると,携帯モードの Nintendo Switch をエミュレートします.グラフィクスの品質は低下します.\n\nドッキングモード有効ならプレイヤー1の,無効なら携帯の入力を設定してください.\n\nよくわからない場合はオンのままにしてください.",
"DirectKeyboardTooltip": "キーボード直接アクセス (HID) に対応します. キーボードをテキスト入力デバイスとして使用できます.", "DirectKeyboardTooltip": "キーボード直接アクセス (HID) に対応します. キーボードをテキスト入力デバイスとして使用できます.",
"DirectMouseTooltip": "マウス直接アクセス (HID) に対応します. マウスをポインティングデバイスとして使用できます.", "DirectMouseTooltip": "マウス直接アクセス (HID) に対応します. マウスをポインティングデバイスとして使用できます.",
"RegionTooltip": "システムの地域を変更します", "RegionTooltip": "システムの地域を変更します",
@ -442,14 +442,14 @@
"MemoryManagerUnsafeTooltip": "メモリを直接マップしますが, アクセス前にゲストのアドレス空間内のアドレスをマスクしません. より高速になりますが, 安全性が犠牲になります. ゲストアプリケーションは Ryujinx のどこからでもメモリにアクセスできるので,このモードでは信頼できるプログラムだけを実行するようにしてください.", "MemoryManagerUnsafeTooltip": "メモリを直接マップしますが, アクセス前にゲストのアドレス空間内のアドレスをマスクしません. より高速になりますが, 安全性が犠牲になります. ゲストアプリケーションは Ryujinx のどこからでもメモリにアクセスできるので,このモードでは信頼できるプログラムだけを実行するようにしてください.",
"DRamTooltip": "エミュレートされたシステムのメモリ容量を 4GB から 6GB に増加します.\n\n高解像度のテクスチャパックや 4K解像度の mod を使用する場合に有用です. パフォーマンスを改善するものではありません.\n\nよくわからない場合はオフのままにしてください.", "DRamTooltip": "エミュレートされたシステムのメモリ容量を 4GB から 6GB に増加します.\n\n高解像度のテクスチャパックや 4K解像度の mod を使用する場合に有用です. パフォーマンスを改善するものではありません.\n\nよくわからない場合はオフのままにしてください.",
"IgnoreMissingServicesTooltip": "未実装の Horizon OS サービスを無視します. 特定のゲームにおいて起動時のクラッシュを回避できる場合があります.\n\nよくわからない場合はオフのままにしてください.", "IgnoreMissingServicesTooltip": "未実装の Horizon OS サービスを無視します. 特定のゲームにおいて起動時のクラッシュを回避できる場合があります.\n\nよくわからない場合はオフのままにしてください.",
"GraphicsBackendThreadingTooltip": "グラフィクスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.", "GraphicsBackendThreadingTooltip": "グラフィクスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.",
"GalThreadingTooltip": "グラフィクスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.", "GalThreadingTooltip": "グラフィクスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.",
"ShaderCacheToggleTooltip": "ディスクシェーダキャッシュをセーブし,次回以降の実行時遅延を軽減します.\n\nよくわからない場合はオンのままにしてください.", "ShaderCacheToggleTooltip": "ディスクシェーダキャッシュをセーブし,次回以降の実行時遅延を軽減します.\n\nよくわからない場合はオンのままにしてください.",
"ResolutionScaleTooltip": "レンダリングに適用される解像度の倍率です", "ResolutionScaleTooltip": "レンダリングに適用される解像度の倍率です",
"ResolutionScaleEntryTooltip": "1.5 のような整数でない倍率を指定すると,問題が発生したりクラッシュしたりする場合があります.", "ResolutionScaleEntryTooltip": "1.5 のような整数でない倍率を指定すると,問題が発生したりクラッシュしたりする場合があります.",
"AnisotropyTooltip": "異方性フィルタリングのレベルです (ゲームが要求する値を使用する場合は「自動」を設定してください)", "AnisotropyTooltip": "異方性フィルタリングのレベルです (ゲームが要求する値を使用する場合は「自動」を設定してください)",
"AspectRatioTooltip": "レンダリングに適用されるアスペクト比です.", "AspectRatioTooltip": "レンダリングに適用されるアスペクト比です.",
"ShaderDumpPathTooltip": "グラフィクス シェーダダンプのパスです", "ShaderDumpPathTooltip": "グラフィクス シェーダダンプのパスです",
"FileLogTooltip": "コンソール出力されるログをディスク上のログファイルにセーブします. パフォーマンスには影響を与えません.", "FileLogTooltip": "コンソール出力されるログをディスク上のログファイルにセーブします. パフォーマンスには影響を与えません.",
"StubLogTooltip": "stub ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.", "StubLogTooltip": "stub ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"InfoLogTooltip": "info ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.", "InfoLogTooltip": "info ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
@ -539,7 +539,7 @@
"LoadingHeading": "ロード中: {0}", "LoadingHeading": "ロード中: {0}",
"CompilingPPTC": "PTC をコンパイル中", "CompilingPPTC": "PTC をコンパイル中",
"CompilingShaders": "シェーダをコンパイル中", "CompilingShaders": "シェーダをコンパイル中",
"AllKeyboards": "すべてキーボード", "AllKeyboards": "すべてキーボード",
"OpenFileDialogTitle": "開くファイルを選択", "OpenFileDialogTitle": "開くファイルを選択",
"OpenFolderDialogTitle": "展開されたゲームフォルダを選択", "OpenFolderDialogTitle": "展開されたゲームフォルダを選択",
"AllSupportedFormats": "すべての対応フォーマット", "AllSupportedFormats": "すべての対応フォーマット",
@ -573,9 +573,20 @@
"Save": "セーブ", "Save": "セーブ",
"Discard": "破棄", "Discard": "破棄",
"UserProfilesSetProfileImage": "プロファイル画像を設定", "UserProfilesSetProfileImage": "プロファイル画像を設定",
"UserProfileEmptyNameError": "名が必要です", "UserProfileEmptyNameError": "名が必要です",
"UserProfileNoImageError": "プロファイル画像が必要です", "UserProfileNoImageError": "プロファイル画像が必要です",
"GameUpdateWindowHeading": "利用可能なアップデート {0} [{1}]", "GameUpdateWindowHeading": "利用可能なアップデート {0} [{1}]",
"SettingsTabHotkeysResScaleUpHotkey": "解像度を上げる:", "SettingsTabHotkeysResScaleUpHotkey": "解像度を上げる:",
"SettingsTabHotkeysResScaleDownHotkey": "解像度を下げる:" "SettingsTabHotkeysResScaleDownHotkey": "解像度を下げる:",
"UserProfilesName": "名称:",
"UserProfilesUserId" : "ユーザID:",
"SettingsTabGraphicsBackend": "グラフィックスバックエンド",
"SettingsTabGraphicsBackendTooltip": "使用するグラフィックスバックエンドです",
"SettingsEnableTextureRecompression": "テクスチャの再圧縮を有効",
"SettingsEnableTextureRecompressionTooltip": "VRAMの使用量を削減するためテクスチャを圧縮します.\n\nGPUのVRAMが4GB未満の場合は使用を推奨します.\n\nよくわからない場合はオフのままにしてください.",
"SettingsTabGraphicsPreferredGpu": "優先使用するGPU",
"SettingsTabGraphicsPreferredGpuTooltip": "Vulkanグラフィックスバックエンドで使用されるグラフィックスカードを選択します.\n\nOpenGLが使用するGPUには影響しません.\n\n不明な場合は, \"dGPU\" としてフラグが立っているGPUに設定します. ない場合はそのままにします.",
"SettingsAppRequiredRestartMessage": "Ryujinx の再起動が必要です",
"SettingsGpuBackendRestartMessage": "グラフィックスバックエンドまたはGPUの設定が変更されました. 変更を適用するには再起動する必要があります",
"SettingsGpuBackendRestartSubMessage": "今すぐ再起動しますか?"
} }

View File

@ -0,0 +1,592 @@
{
"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",
"SettingsTabSystemMemoryManagerModeHost": "Host (szybko)",
"SettingsTabSystemMemoryManagerModeHostUnchecked": "Host Niesprawdzony (najszybciej, niebezpiecznie)",
"MenuBarFile": "_Plik",
"MenuBarFileOpenFromFile": "_Załaduj Aplikację z Pliku",
"MenuBarFileOpenUnpacked": "Załaduj _Rozpakowaną Grę",
"MenuBarFileOpenEmuFolder": "Otwórz Folder Ryujinx",
"MenuBarFileOpenLogsFolder": "Otwórz Folder Logów",
"MenuBarFileExit": "_Wyjdź",
"MenuBarOptions": "Opcje",
"MenuBarOptionsToggleFullscreen": "Przełącz Tryb Pełnoekranowy",
"MenuBarOptionsStartGamesInFullscreen": "Uruchamiaj Gry w Trybie Pełnoekranowym",
"MenuBarOptionsStopEmulation": "Zatrzymaj Emulację",
"MenuBarOptionsSettings": "_Ustawienia",
"MenuBarOptionsManageUserProfiles": "_Zarządzaj Profilami Użytkowników",
"MenuBarActions": "_Akcje",
"MenuBarOptionsSimulateWakeUpMessage": "Symuluj Wiadomość Budzenia",
"MenuBarActionsScanAmiibo": "Skanuj Amiibo",
"MenuBarTools": "_Narzędzia",
"MenuBarToolsInstallFirmware": "Zainstaluj Firmware",
"MenuBarFileToolsInstallFirmwareFromFile": "Zainstaluj Firmware z XCI lub ZIP",
"MenuBarFileToolsInstallFirmwareFromDirectory": "Zainstaluj Firmware z Katalogu",
"MenuBarHelp": "Pomoc",
"MenuBarHelpCheckForUpdates": "Sprawdź Aktualizacje",
"MenuBarHelpAbout": "O Aplikacji",
"MenuSearch": "Szukaj...",
"GameListHeaderFavorite": "Ulub",
"GameListHeaderIcon": "Ikona",
"GameListHeaderApplication": "Nazwa",
"GameListHeaderDeveloper": "Deweloper",
"GameListHeaderVersion": "Wersja",
"GameListHeaderTimePlayed": "Czas Gry",
"GameListHeaderLastPlayed": "Ostatnio Grane",
"GameListHeaderFileExtension": "Rozsz. Pliku",
"GameListHeaderFileSize": "Rozm. Pliku",
"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",
"GameListContextMenuManageTitleUpdates": "Zarządzaj Aktualizacjami Tytułów",
"GameListContextMenuManageTitleUpdatesToolTip": "Otwiera okno zarządzania Aktualizacjami Tytułu",
"GameListContextMenuManageDlc": "Zarządzaj DLC",
"GameListContextMenuManageDlcToolTip": "Otwiera okno zarządzania DLC",
"GameListContextMenuOpenModsDirectory": "Otwórz Katalog Modów",
"GameListContextMenuOpenModsDirectoryToolTip": "Otwiera katalog zawierający Mody Aplikacji",
"GameListContextMenuCacheManagement": "Zarządzanie Cache",
"GameListContextMenuCacheManagementPurgePptc": "Dodaj Rekompilację PPTC do Kolejki",
"GameListContextMenuCacheManagementPurgePptcToolTip": "Zainicjuj Rekompilację PPTC przy następnym uruchomieniu gry",
"GameListContextMenuCacheManagementPurgeShaderCache": "Wyczyść Cache Shaderów",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "Usuwa cache shaderów aplikacji",
"GameListContextMenuCacheManagementOpenPptcDirectory": "Otwórz Katalog PPTC",
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "Otwiera katalog, który zawiera cache PPTC aplikacji",
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "Otwórz Katalog Cache Shaderów",
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "Otwiera katalog, który zawiera cache shaderów aplikacji",
"GameListContextMenuExtractData": "Wyodrębnij Dane",
"GameListContextMenuExtractDataExeFS": "ExeFS",
"GameListContextMenuExtractDataExeFSToolTip": "Wyodrębnij sekcję ExeFS z bieżącej konfiguracji aplikacji (w tym aktualizacje)",
"GameListContextMenuExtractDataRomFS": "RomFS",
"GameListContextMenuExtractDataRomFSToolTip": "Wyodrębnij sekcję RomFS z bieżącej konfiguracji aplikacji (w tym aktualizacje)",
"GameListContextMenuExtractDataLogo": "Logo",
"GameListContextMenuExtractDataLogoToolTip": "Wyodrębnij sekcję Logo z bieżącej konfiguracji aplikacji (w tym aktualizacje)",
"StatusBarGamesLoaded": "{0}/{1} Załadowane Gry",
"StatusBarSystemVersion": "Wersja Systemu: {0}",
"Settings": "Ustawienia",
"SettingsTabGeneral": "Interfejs Użytkownika",
"SettingsTabGeneralGeneral": "Ogólne",
"SettingsTabGeneralEnableDiscordRichPresence": "Włącz Bogatą Obecność Discord",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Sprawdź Aktualizacje przy Uruchomieniu",
"SettingsTabGeneralShowConfirmExitDialog": "Pokaż Okno Dialogowe \"Potwierdzenia Wyjścia\"",
"SettingsTabGeneralHideCursorOnIdle": "Ukryj Kursor Podczas Bezczynności",
"SettingsTabGeneralGameDirectories": "Katalogi Gier",
"SettingsTabGeneralAdd": "Dodaj",
"SettingsTabGeneralRemove": "Usuń",
"SettingsTabSystem": "System",
"SettingsTabSystemCore": "Główne",
"SettingsTabSystemSystemRegion": "Region Systemu:",
"SettingsTabSystemSystemRegionJapan": "Japonia",
"SettingsTabSystemSystemRegionUSA": "USA",
"SettingsTabSystemSystemRegionEurope": "Europa",
"SettingsTabSystemSystemRegionAustralia": "Australia",
"SettingsTabSystemSystemRegionChina": "Chiny",
"SettingsTabSystemSystemRegionKorea": "Korea",
"SettingsTabSystemSystemRegionTaiwan": "Tajwan",
"SettingsTabSystemSystemLanguage": "Język Systemu:",
"SettingsTabSystemSystemLanguageJapanese": "Japoński",
"SettingsTabSystemSystemLanguageAmericanEnglish": "Amerykański Angielski",
"SettingsTabSystemSystemLanguageFrench": "Francuski",
"SettingsTabSystemSystemLanguageGerman": "Niemiecki",
"SettingsTabSystemSystemLanguageItalian": "Włoski",
"SettingsTabSystemSystemLanguageSpanish": "Hiszpański",
"SettingsTabSystemSystemLanguageChinese": "Chiński",
"SettingsTabSystemSystemLanguageKorean": "Koreański",
"SettingsTabSystemSystemLanguageDutch": "Holenderski",
"SettingsTabSystemSystemLanguagePortuguese": "Portugalski",
"SettingsTabSystemSystemLanguageRussian": "Rosyjski",
"SettingsTabSystemSystemLanguageTaiwanese": "Tajwański",
"SettingsTabSystemSystemLanguageBritishEnglish": "Brytyjski Angielski",
"SettingsTabSystemSystemLanguageCanadianFrench": "Kanadyjski Francuski",
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "Hiszpański Latynoamerykański",
"SettingsTabSystemSystemLanguageSimplifiedChinese": "Chiński Uproszczony",
"SettingsTabSystemSystemLanguageTraditionalChinese": "Chiński Tradycyjny",
"SettingsTabSystemSystemTimeZone": "Strefa Czasowa Systemu:",
"SettingsTabSystemSystemTime": "Czas Systemu:",
"SettingsTabSystemEnableVsync": "VSync",
"SettingsTabSystemEnablePptc": "PPTC (Profilowany Cache Trwałych Tłumaczeń)",
"SettingsTabSystemEnableFsIntegrityChecks": "Kontrole Integralności Systemu Plików",
"SettingsTabSystemAudioBackend": "Backend Dżwięku:",
"SettingsTabSystemAudioBackendDummy": "Atrapa",
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
"SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemHacks": "Hacki",
"SettingsTabSystemHacksNote": " (mogą powodować niestabilność)",
"SettingsTabSystemExpandDramSize": "Rozszerz Rozmiar DRAM do 6 GB",
"SettingsTabSystemIgnoreMissingServices": "Ignoruj Brakujące Usługi",
"SettingsTabGraphics": "Grafika",
"SettingsTabGraphicsAPI": "Graficzne API",
"SettingsTabGraphicsEnableShaderCache": "Włącz Cache Shaderów",
"SettingsTabGraphicsAnisotropicFiltering": "Filtrowanie Anizotropowe:",
"SettingsTabGraphicsAnisotropicFilteringAuto": "Auto",
"SettingsTabGraphicsAnisotropicFiltering2x": "2x",
"SettingsTabGraphicsAnisotropicFiltering4x": "4x",
"SettingsTabGraphicsAnisotropicFiltering8x": "8x",
"SettingsTabGraphicsAnisotropicFiltering16x": "16x",
"SettingsTabGraphicsResolutionScale": "Skala Rozdzielczości:",
"SettingsTabGraphicsResolutionScaleCustom": "Niestandardowa (Niezalecane)",
"SettingsTabGraphicsResolutionScaleNative": "Natywna (720p/1080p)",
"SettingsTabGraphicsResolutionScale2x": "2x (1440p/2160p)",
"SettingsTabGraphicsResolutionScale3x": "3x (2160p/3240p)",
"SettingsTabGraphicsResolutionScale4x": "4x (2880p/4320p)",
"SettingsTabGraphicsAspectRatio": "Współczynnik Proporcji:",
"SettingsTabGraphicsAspectRatio4x3": "4:3",
"SettingsTabGraphicsAspectRatio16x9": "16:9",
"SettingsTabGraphicsAspectRatio16x10": "16:10",
"SettingsTabGraphicsAspectRatio21x9": "21:9",
"SettingsTabGraphicsAspectRatio32x9": "32:9",
"SettingsTabGraphicsAspectRatioStretch": "Rozciągnij do Okna",
"SettingsTabGraphicsDeveloperOptions": "Opcje Programistyczne",
"SettingsTabGraphicsShaderDumpPath": "Ścieżka Zrzutu Shaderów Grafiki:",
"SettingsTabLogging": "Logowanie",
"SettingsTabLoggingLogging": "Logowanie",
"SettingsTabLoggingEnableLoggingToFile": "Włącz Logowanie do Pliku",
"SettingsTabLoggingEnableStubLogs": "Wlącz Skróty Logów",
"SettingsTabLoggingEnableInfoLogs": "Włącz Logi Informacyjne",
"SettingsTabLoggingEnableWarningLogs": "Włącz Logi Ostrzeżeń",
"SettingsTabLoggingEnableErrorLogs": "Włącz Logi Błędów",
"SettingsTabLoggingEnableTraceLogs": "Włącz Logi Śledzenia",
"SettingsTabLoggingEnableGuestLogs": "Włącz Logi Gości",
"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ść)",
"SettingsTabLoggingOpenglLogLevel": "Poziom Logów OpenGL:",
"SettingsTabLoggingOpenglLogLevelNone": "Żadne",
"SettingsTabLoggingOpenglLogLevelError": "Błędy",
"SettingsTabLoggingOpenglLogLevelPerformance": "Spowolnienia",
"SettingsTabLoggingOpenglLogLevelAll": "Wszystkie",
"SettingsTabLoggingEnableDebugLogs": "Włącz Logi Debugowania",
"SettingsTabInput": "Sterowanie",
"SettingsTabInputEnableDockedMode": "Tryb Zadokowany",
"SettingsTabInputDirectKeyboardAccess": "Bezpośredni Dostęp do Klawiatury",
"SettingsButtonSave": "Zapisz",
"SettingsButtonClose": "Zamknij",
"SettingsButtonApply": "Zastosuj",
"ControllerSettingsPlayer": "Gracz",
"ControllerSettingsPlayer1": "Gracz 1",
"ControllerSettingsPlayer2": "Gracz 2",
"ControllerSettingsPlayer3": "Gracz 3",
"ControllerSettingsPlayer4": "Gracz 4",
"ControllerSettingsPlayer5": "Gracz 5",
"ControllerSettingsPlayer6": "Gracz 6",
"ControllerSettingsPlayer7": "Gracz 7",
"ControllerSettingsPlayer8": "Gracz 8",
"ControllerSettingsHandheld": "Przenośny",
"ControllerSettingsInputDevice": "Urządzenie Wejściowe",
"ControllerSettingsRefresh": "Odśwież",
"ControllerSettingsDeviceDisabled": "Wyłączone",
"ControllerSettingsControllerType": "Typ Kontrolera",
"ControllerSettingsControllerTypeHandheld": "Przenośny",
"ControllerSettingsControllerTypeProController": "Pro Controller",
"ControllerSettingsControllerTypeJoyConPair": "Para JoyCon-ów",
"ControllerSettingsControllerTypeJoyConLeft": "Lewy JoyCon",
"ControllerSettingsControllerTypeJoyConRight": "Prawy JoyCon",
"ControllerSettingsProfile": "Profil",
"ControllerSettingsProfileDefault": "Domyślny",
"ControllerSettingsLoad": "Wczytaj",
"ControllerSettingsAdd": "Dodaj",
"ControllerSettingsRemove": "Usuń",
"ControllerSettingsButtons": "Przyciski",
"ControllerSettingsButtonA": "A",
"ControllerSettingsButtonB": "B",
"ControllerSettingsButtonX": "X",
"ControllerSettingsButtonY": "Y",
"ControllerSettingsButtonPlus": "+",
"ControllerSettingsButtonMinus": "-",
"ControllerSettingsDPad": "Pad Kierunkowy",
"ControllerSettingsDPadUp": "Góra",
"ControllerSettingsDPadDown": "Dół",
"ControllerSettingsDPadLeft": "Lewo",
"ControllerSettingsDPadRight": "Prawo",
"ControllerSettingsLStick": "Lewa Gałka",
"ControllerSettingsLStickButton": "Przycisk",
"ControllerSettingsLStickUp": "Góra",
"ControllerSettingsLStickDown": "Dół",
"ControllerSettingsLStickLeft": "Lewo",
"ControllerSettingsLStickRight": "Prawo",
"ControllerSettingsLStickStick": "Gałka",
"ControllerSettingsLStickInvertXAxis": "Odwróć X Gałki",
"ControllerSettingsLStickInvertYAxis": "Odwróć Y Gałki",
"ControllerSettingsLStickDeadzone": "Deadzone:",
"ControllerSettingsRStick": "Prawa Gałka",
"ControllerSettingsRStickButton": "Przycisk",
"ControllerSettingsRStickUp": "Góra",
"ControllerSettingsRStickDown": "Dół",
"ControllerSettingsRStickLeft": "Lewo",
"ControllerSettingsRStickRight": "Prawo",
"ControllerSettingsRStickStick": "Gałka",
"ControllerSettingsRStickInvertXAxis": "Odwróć X Gałki",
"ControllerSettingsRStickInvertYAxis": "Odwróć Y Gałki",
"ControllerSettingsRStickDeadzone": "Deadzone:",
"ControllerSettingsTriggersLeft": "Lewe Triggery",
"ControllerSettingsTriggersRight": "Prawe Triggery",
"ControllerSettingsTriggersButtonsLeft": "Lewe Przyciski Triggerów",
"ControllerSettingsTriggersButtonsRight": "Prawe Przyciski Triggerów",
"ControllerSettingsTriggers": "Triggery",
"ControllerSettingsTriggerL": "L",
"ControllerSettingsTriggerR": "R",
"ControllerSettingsTriggerZL": "ZL",
"ControllerSettingsTriggerZR": "ZR",
"ControllerSettingsLeftSL": "SL",
"ControllerSettingsLeftSR": "SR",
"ControllerSettingsRightSL": "SL",
"ControllerSettingsRightSR": "SR",
"ControllerSettingsExtraButtonsLeft": "Lewe Przyciski",
"ControllerSettingsExtraButtonsRight": "Prawe Przyciski",
"ControllerSettingsMisc": "Różne",
"ControllerSettingsTriggerThreshold": "Próg Triggerów:",
"ControllerSettingsMotion": "Ruch",
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "Użyj ruchu zgodnego z CemuHook",
"ControllerSettingsMotionControllerSlot": "Slot Kontrolera:",
"ControllerSettingsMotionMirrorInput": "Odzwierciedlaj Sterowanie",
"ControllerSettingsMotionRightJoyConSlot": "Prawy Slot JoyCon:",
"ControllerSettingsMotionServerHost": "Host Serwera:",
"ControllerSettingsMotionGyroSensitivity": "Czułość Żyroskopu:",
"ControllerSettingsMotionGyroDeadzone": "Deadzone Żyroskopu:",
"ControllerSettingsSave": "Zapisz",
"ControllerSettingsClose": "Zamknij",
"UserProfilesSelectedUserProfile": "Wybrany Profil Użytkownika:",
"UserProfilesSaveProfileName": "Zapisz Nazwę Profilu",
"UserProfilesChangeProfileImage": "Zmień Obraz Profilu",
"UserProfilesAvailableUserProfiles": "Dostępne Profile Użytkowników:",
"UserProfilesAddNewProfile": "Utwórz Profil",
"UserProfilesDeleteSelectedProfile": "Usuń Zaznaczone",
"UserProfilesClose": "Zamknij",
"ProfileImageSelectionTitle": "Wybór Obrazu Profilu",
"ProfileImageSelectionHeader": "Wybierz zdjęcie profilowe",
"ProfileImageSelectionNote": "Możesz zaimportować niestandardowy obraz profilu lub wybrać awatar z firmware'u systemowego",
"ProfileImageSelectionImportImage": "Importuj Plik Obrazu",
"ProfileImageSelectionSelectAvatar": "Wybierz Awatar z Firmware'u",
"InputDialogTitle": "Okno Dialogowe Wprowadzania",
"InputDialogOk": "OK",
"InputDialogCancel": "Anuluj",
"InputDialogAddNewProfileTitle": "Wybierz Nazwę Profilu",
"InputDialogAddNewProfileHeader": "Wprowadź Nazwę Profilu",
"InputDialogAddNewProfileSubtext": "(Maksymalna Długość: {0})",
"AvatarChoose": "Wybierz",
"AvatarSetBackgroundColor": "Ustaw Kolor Tła",
"AvatarClose": "Zamknij",
"ControllerSettingsLoadProfileToolTip": "Załaduj Profil",
"ControllerSettingsAddProfileToolTip": "Dodaj Profil",
"ControllerSettingsRemoveProfileToolTip": "Usuń Profil",
"ControllerSettingsSaveProfileToolTip": "Zapisz Profil",
"MenuBarFileToolsTakeScreenshot": "Zrób Zrzut Ekranu",
"MenuBarFileToolsHideUi": "Ukryj UI",
"GameListContextMenuToggleFavorite": "Przełącz Ulubione",
"GameListContextMenuToggleFavoriteToolTip": "Przełącz status Ulubionej Gry",
"SettingsTabGeneralTheme": "Motyw",
"SettingsTabGeneralThemeCustomTheme": "Ścieżka Niestandardowych Motywów",
"SettingsTabGeneralThemeBaseStyle": "Styl Podstawowy",
"SettingsTabGeneralThemeBaseStyleDark": "Ciemny",
"SettingsTabGeneralThemeBaseStyleLight": "Jasny",
"SettingsTabGeneralThemeEnableCustomTheme": "Włącz Niestandardowy Motyw",
"ButtonBrowse": "Przeglądaj",
"ControllerSettingsConfigureGeneral": "Konfiguruj",
"ControllerSettingsRumble": "Wibracje",
"ControllerSettingsRumbleStrongMultiplier": "Mocny Mnożnik Wibracji",
"ControllerSettingsRumbleWeakMultiplier": "Słaby Mnożnik Wibracji",
"DialogMessageSaveNotAvailableMessage": "Nie ma danych zapisu dla {0} [{1:x16}]",
"DialogMessageSaveNotAvailableCreateSaveMessage": "Czy chcesz utworzyć dane zapisu dla tej gry?",
"DialogConfirmationTitle": "Ryujinx - Potwierdzenie",
"DialogUpdaterTitle": "Ryujinx - Aktualizator",
"DialogErrorTitle": "Ryujinx - Błąd",
"DialogWarningTitle": "Ryujinx - Uwaga",
"DialogExitTitle": "Ryujinx - Wyjdź",
"DialogErrorMessage": "Ryujinx napotkał błąd",
"DialogExitMessage": "Czy na pewno chcesz zamknąć Ryujinx?",
"DialogExitSubMessage": "Wszystkie niezapisane dane zostaną utracone!",
"DialogMessageCreateSaveErrorMessage": "Wystąpił błąd podczas tworzenia określonych danych zapisu: {0}",
"DialogMessageFindSaveErrorMessage": "Wystąpił błąd podczas znajdowania określonych danych zapisu: {0}",
"FolderDialogExtractTitle": "Wybierz folder do rozpakowania",
"DialogNcaExtractionMessage": "Wyodrębnianie sekcji {0} z {1}...",
"DialogNcaExtractionTitle": "Ryujinx - Ekstraktor Sekcji NCA",
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "Niepowodzenie ekstrakcji. W wybranym pliku nie było głównego NCA.",
"DialogNcaExtractionCheckLogErrorMessage": "Niepowodzenie ekstrakcji. Przeczytaj plik dziennika, aby uzyskać więcej informacji.",
"DialogNcaExtractionSuccessMessage": "Ekstrakcja zakończona pomyślnie.",
"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.",
"DialogUpdaterConvertFailedGithubMessage": "Nie udało się przekonwertować otrzymanej wersji Ryujinx z Github Release.",
"DialogUpdaterDownloadingMessage": "Pobieranie Aktualizacji...",
"DialogUpdaterExtractionMessage": "Wypakowywanie Aktualizacji...",
"DialogUpdaterRenamingMessage": "Zmiana Nazwy Aktualizacji...",
"DialogUpdaterAddingFilesMessage": "Dodawanie Nowej Aktualizacji...",
"DialogUpdaterCompleteMessage": "Aktualizacja Zakończona!",
"DialogUpdaterRestartMessage": "Czy chcesz teraz zrestartować Ryujinx?",
"DialogUpdaterArchNotSupportedMessage": "Nie używasz obsługiwanej architektury systemu!",
"DialogUpdaterArchNotSupportedSubMessage": "(Obsługiwane są tylko systemy x64!)",
"DialogUpdaterNoInternetMessage": "Nie masz połączenia z Internetem!",
"DialogUpdaterNoInternetSubMessage": "Sprawdź, czy masz działające połączenie internetowe!",
"DialogUpdaterDirtyBuildMessage": "Nie możesz zaktualizować Dirty wersji Ryujinx!",
"DialogUpdaterDirtyBuildSubMessage": "Pobierz Ryujinx ze strony https://ryujinx.org/, jeśli szukasz obsługiwanej wersji.",
"DialogRestartRequiredMessage": "Wymagane Ponowne Uruchomienie",
"DialogThemeRestartMessage": "Motyw został zapisany. Aby zastosować motyw, konieczne jest ponowne uruchomienie.",
"DialogThemeRestartSubMessage": "Czy chcesz uruchomić ponownie?",
"DialogFirmwareInstallEmbeddedMessage": "Czy chcesz zainstalować firmware wbudowany w tę grę? (Firmware {0})",
"DialogFirmwareInstallEmbeddedSuccessMessage": "Nie znaleziono zainstalowanego firmware'u, ale Ryujinx był w stanie zainstalować firmware {0} z dostarczonej gry.\n\nEmulator uruchomi się teraz.",
"DialogFirmwareNoFirmwareInstalledMessage": "Brak Zainstalowanego Firmware'u",
"DialogFirmwareInstalledMessage": "Firmware {0} został zainstalowany",
"DialogOpenSettingsWindowLabel": "Otwórz Okno Ustawień",
"DialogControllerAppletTitle": "Aplet Kontrolera",
"DialogMessageDialogErrorExceptionMessage": "Błąd wyświetlania okna Dialogowego Wiadomości: {0}",
"DialogSoftwareKeyboardErrorExceptionMessage": "Błąd wyświetlania Klawiatury Oprogramowania: {0}",
"DialogErrorAppletErrorExceptionMessage": "Błąd wyświetlania okna Dialogowego ErrorApplet: {0}",
"DialogUserErrorDialogMessage": "{0}: {1}",
"DialogUserErrorDialogInfoMessage": "\nAby uzyskać więcej informacji o tym, jak naprawić ten błąd, zapoznaj się z naszym Przewodnikiem instalacji.",
"DialogUserErrorDialogTitle": "Błąd Ryujinxa ({0})",
"DialogAmiiboApiTitle": "API Amiibo",
"DialogAmiiboApiFailFetchMessage": "Wystąpił błąd podczas pobierania informacji z API.",
"DialogAmiiboApiConnectErrorMessage": "Nie można połączyć się z serwerem API Amiibo. Usługa może nie działać lub może być konieczne sprawdzenie, czy połączenie internetowe jest online.",
"DialogProfileInvalidProfileErrorMessage": "Profil {0} jest niezgodny z bieżącym systemem konfiguracji sterowania.",
"DialogProfileDefaultProfileOverwriteErrorMessage": "Profil Domyślny nie może zostać nadpisany",
"DialogProfileDeleteProfileTitle": "Usuwanie Profilu",
"DialogProfileDeleteProfileMessage": "Ta czynność jest nieodwracalna, czy na pewno chcesz kontynuować?",
"DialogWarning": "Uwaga",
"DialogPPTCDeletionMessage": "Masz zamiar umieścić w kolejce rekompilację PPTC przy następnym uruchomieniu:\n\n{0}\n\nCzy na pewno chcesz kontynuować?",
"DialogPPTCDeletionErrorMessage": "Błąd czyszczenia cache PPTC w {0}: {1}",
"DialogShaderDeletionMessage": "Zamierzasz usunąć cache Shaderów dla :\n\n{0}\n\nNa pewno chcesz kontynuować?",
"DialogShaderDeletionErrorMessage": "Błąd czyszczenia cache Shaderów w {0}: {1}",
"DialogRyujinxErrorMessage": "Ryujinx napotkał błąd",
"DialogInvalidTitleIdErrorMessage": "Błąd UI: Wybrana gra nie miała prawidłowego ID tytułu",
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "Nie znaleziono prawidłowego firmware'u systemowego w {0}.",
"DialogFirmwareInstallerFirmwareInstallTitle": "Zainstaluj Firmware {0}",
"DialogFirmwareInstallerFirmwareInstallMessage": "Wersja systemu {0} zostanie zainstalowana.",
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\nZastąpi to obecną wersję systemu {0}.",
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\nCzy chcesz kontynuować?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "Instalowanie firmware'u...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "Wersja systemu {0} została pomyślnie zainstalowana.",
"DialogUserProfileDeletionWarningMessage": "Nie będzie innych profili do otwarcia, jeśli wybrany profil zostanie usunięty",
"DialogUserProfileDeletionConfirmMessage": "Czy chcesz usunąć wybrany profil",
"DialogControllerSettingsModifiedConfirmMessage": "Aktualne ustawienia kontrolera zostały zaktualizowane.",
"DialogControllerSettingsModifiedConfirmSubMessage": "Czy chcesz zapisać?",
"DialogDlcLoadNcaErrorMessage": "{0}. Błędny Plik: {1}",
"DialogDlcNoDlcErrorMessage": "Określony plik nie zawiera DLC dla wybranego tytułu!",
"DialogPerformanceCheckLoggingEnabledMessage": "Masz włączone rejestrowanie śledzenia, które jest przeznaczone tylko dla programistów.",
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "Aby uzyskać optymalną wydajność, zaleca się wyłączenie rejestrowania śledzenia. Czy chcesz teraz wyłączyć rejestrowanie śledzenia?",
"DialogPerformanceCheckShaderDumpEnabledMessage": "Masz włączone zrzucanie shaderów, które jest przeznaczone tylko dla programistów.",
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "Aby uzyskać optymalną wydajność, zaleca się wyłączenie zrzucania shaderów. Czy chcesz teraz wyłączyć zrzucanie shaderów?",
"DialogLoadAppGameAlreadyLoadedMessage": "Gra została już załadowana",
"DialogLoadAppGameAlreadyLoadedSubMessage": "Zatrzymaj emulację lub zamknij emulator przed uruchomieniem innej gry.",
"DialogUpdateAddUpdateErrorMessage": "Określony plik nie zawiera aktualizacji dla wybranego tytułu!",
"DialogSettingsBackendThreadingWarningTitle": "Ostrzeżenie — Wątki Backend",
"DialogSettingsBackendThreadingWarningMessage": "Ryujinx musi zostać ponownie uruchomiony po zmianie tej opcji, aby działał w pełni. W zależności od platformy może być konieczne ręczne wyłączenie sterownika wielowątkowości podczas korzystania z Ryujinx.",
"SettingsTabGraphicsFeaturesOptions": "Funkcje",
"SettingsTabGraphicsBackendMultithreading": "Wielowątkowość Backendu Graficznego:",
"CommonAuto": "Auto",
"CommonOff": "Wyłączone",
"CommonOn": "Włączone",
"InputDialogYes": "Tak",
"InputDialogNo": "Nie",
"DialogProfileInvalidProfileNameErrorMessage": "Nazwa pliku zawiera nieprawidłowe znaki. Proszę spróbuj ponownie.",
"MenuBarOptionsPauseEmulation": "Pauza",
"MenuBarOptionsResumeEmulation": "Wznów",
"AboutUrlTooltipMessage": "Kliknij, aby otworzyć stronę Ryujinx w domyślnej przeglądarce.",
"AboutDisclaimerMessage": "Ryujinx nie jest w żaden sposób powiązany z Nintendo™,\nani z żadnym z jej partnerów.",
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) jest używane\nw naszej emulacji Amiibo.",
"AboutPatreonUrlTooltipMessage": "Kliknij, aby otworzyć stronę Patreon Ryujinx w domyślnej przeglądarce.",
"AboutGithubUrlTooltipMessage": "Kliknij, aby otworzyć stronę GitHub Ryujinx w domyślnej przeglądarce.",
"AboutDiscordUrlTooltipMessage": "Kliknij, aby otworzyć zaproszenie na serwer Discord Ryujinx w domyślnej przeglądarce.",
"AboutTwitterUrlTooltipMessage": "Kliknij, aby otworzyć stronę Twitter Ryujinx w domyślnej przeglądarce.",
"AboutRyujinxAboutTitle": "O Aplikacji:",
"AboutRyujinxAboutContent": "Ryujinx to emulator Nintendo Switch™.\nWspieraj nas na Patreonie.\nOtrzymuj najnowsze wiadomości na naszym Twitterze lub Discordzie.\nDeweloperzy zainteresowani współpracą mogą dowiedzieć się więcej na naszym GitHubie lub Discordzie.",
"AboutRyujinxMaintainersTitle": "Utrzymywany Przez:",
"AboutRyujinxMaintainersContentTooltipMessage": "Kliknij, aby otworzyć stronę Współtwórcy w domyślnej przeglądarce.",
"AboutRyujinxSupprtersTitle": "Wspierani na Patreonie Przez:",
"AmiiboSeriesLabel": "Seria Amiibo",
"AmiiboCharacterLabel": "Postać",
"AmiiboScanButtonLabel": "Zeskanuj",
"AmiiboOptionsShowAllLabel": "Pokaż Wszystkie Amiibo",
"AmiiboOptionsUsRandomTagLabel": "Hack: Użyj losowego UUID tagu",
"DlcManagerTableHeadingEnabledLabel": "Włączone",
"DlcManagerTableHeadingTitleIdLabel": "ID Tytułu",
"DlcManagerTableHeadingContainerPathLabel": "Ścieżka Kontenera",
"DlcManagerTableHeadingFullPathLabel": "Pełna Ścieżka",
"DlcManagerRemoveAllButton": "Usuń Wszystkie",
"MenuBarOptionsChangeLanguage": "Zmień Język",
"CommonSort": "Sortuj",
"CommonShowNames": "Pokaż Nazwy",
"CommonFavorite": "Ulubione",
"OrderAscending": "Rosnąco",
"OrderDescending": "Malejąco",
"SettingsTabGraphicsFeatures": "Funkcje i Ulepszenia",
"ErrorWindowTitle": "Okno Błędu",
"ToggleDiscordTooltip": "Wybierz, czy chcesz wyświetlać Ryujinx w swojej \"aktualnie grane\" aktywności Discord",
"AddGameDirBoxTooltip": "Wprowadź katalog gier aby dodać go do listy",
"AddGameDirTooltip": "Dodaj katalog gier do listy",
"RemoveGameDirTooltip": "Usuń wybrany katalog gier",
"CustomThemeCheckTooltip": "Użyj niestandardowego motywu Avalonia dla GUI, aby zmienić wygląd menu emulatora",
"CustomThemePathTooltip": "Ścieżka do niestandardowego motywu GUI",
"CustomThemeBrowseTooltip": "Wyszukaj niestandardowy motyw GUI",
"DockModeToggleTooltip": "Tryb Zadokowany sprawia, że emulowany system zachowuje się jak zadokowany Nintendo Switch. Poprawia to jakość grafiki w większości gier. I odwrotnie, wyłączenie tej opcji sprawi, że emulowany system będzie zachowywał się jak przenośny Nintendo Switch, zmniejszając jakość grafiki.\n\nSkonfiguruj sterowanie gracza 1, jeśli planujesz używać trybu Zadokowanego; Skonfiguruj sterowanie przenośne, jeśli planujesz używać trybu przenośnego.\n\nPozostaw WŁĄCZONY, jeśli nie masz pewności.",
"DirectKeyboardTooltip": "Obsługa bezpośredniego dostępu klawiatury (HID). Zapewnia dostęp gier do klawiatury jako urządzenia do wprowadzania tekstu.",
"DirectMouseTooltip": "Obsługa bezpośredniego dostępu myszy (HID). Zapewnia grom dostęp do myszy jako urządzenia wskazującego.",
"RegionTooltip": "Zmień Region Systemu",
"LanguageTooltip": "Zmień Język Systemu",
"TimezoneTooltip": "Zmień Strefę Czasową Systemu",
"TimeTooltip": "Zmień Czas Systemu",
"VSyncToggleTooltip": "Pionowa synchronizacja emulowanej konsoli. Zasadniczo ogranicznik klatek dla większości gier; wyłączenie jej może spowodować, że gry będą działać z większą szybkością, ekrany wczytywania wydłużą się lub nawet utkną.\n\nMoże być przełączana w grze za pomocą preferowanego skrótu klawiszowego. Zalecamy to zrobić, jeśli planujesz ją wyłączyć.\n\nW razie wątpliwości pozostaw WŁĄCZONĄ",
"PptcToggleTooltip": "Zapisuje przetłumaczone funkcje JIT, dzięki czemu nie muszą być tłumaczone za każdym razem, gdy gra się ładuje.\n\nZmniejsza zacinanie się i znacznie przyspiesza uruchamianie po pierwszym uruchomieniu gry.\n\nJeśli nie masz pewności, pozostaw WŁĄCZONE",
"FsIntegrityToggleTooltip": "Sprawdza pliki podczas uruchamiania gry i jeśli zostaną wykryte uszkodzone pliki, wyświetla w dzienniku błąd hash.\n\nNie ma wpływu na wydajność i ma pomóc w rozwiązywaniu problemów.\n\nPozostaw WŁĄCZONE, jeśli nie masz pewności.",
"AudioBackendTooltip": "Zmienia backend używany do renderowania dźwięku.\n\nSDL2 jest preferowany, podczas gdy OpenAL i SoundIO są używane jako rezerwy. Dummy nie będzie odtwarzać dźwięku.\n\nW razie wątpliwości ustaw SDL2.",
"MemoryManagerTooltip": "Zmień sposób mapowania i uzyskiwania dostępu do pamięci gości. Znacznie wpływa na wydajność emulowanego procesora.\n\nUstaw na HOST UNCHECKED, jeśli nie masz pewności.",
"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 GB do 6 GB.\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.",
"ShaderCacheToggleTooltip": "Zapisuje pamięć podręczną shaderów na dysku, co zmniejsza zacinanie się w kolejnych uruchomieniach.\n\nPozostaw WŁĄCZONE, jeśli nie masz pewności.",
"ResolutionScaleTooltip": "Skala Rozdzielczości zastosowana do odpowiednich celów renderowania",
"ResolutionScaleEntryTooltip": "Skala rozdzielczości zmiennoprzecinkowej, np. 1,5. Skale niecałkowite częściej powodują problemy lub awarie.",
"AnisotropyTooltip": "Poziom filtrowania anizotropowego (ustaw na Auto, aby użyć wartości wymaganej przez grę)",
"AspectRatioTooltip": "Współczynnik proporcji zastosowany do okna renderowania.",
"ShaderDumpPathTooltip": "Ścieżka Zrzutu Shaderów Grafiki",
"FileLogTooltip": "Zapisuje logowanie konsoli w pliku dziennika na dysku. Nie wpływa na wydajność.",
"StubLogTooltip": "Wyświetla w konsoli skrótowe komunikaty dziennika. Nie wpływa na wydajność.",
"InfoLogTooltip": "Wyświetla komunikaty dziennika informacyjnego w konsoli. Nie wpływa na wydajność.",
"WarnLogTooltip": "Wyświetla komunikaty dziennika ostrzeżeń w konsoli. Nie wpływa na wydajność.",
"ErrorLogTooltip": "Wyświetla w konsoli komunikaty dziennika błędów. Nie wpływa na wydajność.",
"TraceLogTooltip": "Wyświetla komunikaty dziennika śledzenia w konsoli. Nie wpływa na wydajność.",
"GuestLogTooltip": "Wyświetla komunikaty dziennika gości w konsoli. Nie wpływa na wydajność.",
"FileAccessLogTooltip": "Wyświetla w konsoli komunikaty dziennika dostępu do plików.",
"FSAccessLogModeTooltip": "Włącza wyjście dziennika dostępu FS do konsoli. Możliwe tryby to 0-3",
"DeveloperOptionTooltip": "Używaj ostrożnie",
"OpenGlLogLevel": "Wymaga włączonych odpowiednich poziomów logów",
"DebugLogTooltip": "Wyświetla komunikaty dziennika debugowania w konsoli.\n\nUżywaj tego tylko na wyraźne polecenie członka załogi, ponieważ utrudni to odczytanie dzienników i pogorszy wydajność emulatora.",
"LoadApplicationFileTooltip": "Otwórz eksplorator plików, aby wybrać plik kompatybilny z Switch do wczytania",
"LoadApplicationFolderTooltip": "Otwórz eksplorator plików, aby wybrać zgodną z Switch, rozpakowaną aplikację do załadowania",
"OpenRyujinxFolderTooltip": "Otwórz folder systemu plików Ryujinx",
"OpenRyujinxLogsTooltip": "Otwiera folder, w którym zapisywane są logi",
"ExitTooltip": "Wyjdź z Ryujinx",
"OpenSettingsTooltip": "Otwórz okno ustawień",
"OpenProfileManagerTooltip": "Otwórz okno Menedżera Profili Użytkownika",
"StopEmulationTooltip": "Zatrzymaj emulację bieżącej gry i wróć do wyboru gier",
"CheckUpdatesTooltip": "Sprawdź aktualizacje Ryujinx",
"OpenAboutTooltip": "Otwórz Okno Informacje",
"GridSize": "Wielkość siatki",
"GridSizeTooltip": "Zmień rozmiar elementów siatki",
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "Brazylijski Portugalski",
"AboutRyujinxContributorsButtonHeader": "Zobacz Wszystkich Współtwórców",
"SettingsTabSystemAudioVolume": "Głośność: ",
"AudioVolumeTooltip": "Zmień Głośność Dźwięku",
"SettingsTabSystemEnableInternetAccess": "Dostęp do Internetu Gościa/Tryb LAN",
"EnableInternetAccessTooltip": "Pozwala emulowanej aplikacji na łączenie się z Internetem.\n\nGry w trybie LAN mogą łączyć się ze sobą, gdy ta opcja jest włączona, a systemy są połączone z tym samym punktem dostępu. Dotyczy to również prawdziwych konsol.\n\nNie pozwala na łączenie się z serwerami Nintendo. Może powodować awarie niektórych gier, które próbują połączyć się z Internetem.\n\nPozostaw WYŁĄCZONE, jeśli nie masz pewności.",
"GameListContextMenuManageCheatToolTip": "Zarządzaj Kodami",
"GameListContextMenuManageCheat": "Zarządzaj Kodami",
"ControllerSettingsStickRange": "Zasięg:",
"DialogStopEmulationTitle": "Ryujinx - Zatrzymaj Emulację",
"DialogStopEmulationMessage": "Czy na pewno chcesz zatrzymać emulację?",
"SettingsTabCpu": "CPU",
"SettingsTabAudio": "Dżwięk",
"SettingsTabNetwork": "Sieć",
"SettingsTabNetworkConnection": "Połączenie Sieciowe",
"SettingsTabCpuCache": "Cache CPU",
"SettingsTabCpuMemory": "Pamięć CPU",
"DialogUpdaterFlatpakNotSupportedMessage": "Zaktualizuj Ryujinx przez FlatHub.",
"UpdaterDisabledWarningTitle": "Aktualizator Wyłączony!",
"GameListContextMenuOpenSdModsDirectory": "Otwórz Katalog Modów Atmosphere",
"GameListContextMenuOpenSdModsDirectoryToolTip": "Otwiera alternatywny katalog Atmosphere na karcie SD, który zawiera modyfikacje aplikacji. Przydatne dla modów, które są pakowane dla prawdziwego sprzętu.",
"ControllerSettingsRotate90": "Obróć o 90° w Prawo",
"IconSize": "Rozmiar Ikon",
"IconSizeTooltip": "Zmień rozmiar ikon gry",
"MenuBarOptionsShowConsole": "Pokaż Konsolę",
"ShaderCachePurgeError": "Błąd podczas czyszczenia cache shaderów w {0}: {1}",
"UserErrorNoKeys": "Nie znaleziono kluczy",
"UserErrorNoFirmware": "Nie znaleziono firmware'u",
"UserErrorFirmwareParsingFailed": "Błąd parsowania firmware'u",
"UserErrorApplicationNotFound": "Aplikacja nie znaleziona",
"UserErrorUnknown": "Nieznany błąd",
"UserErrorUndefined": "Niezdefiniowany błąd",
"UserErrorNoKeysDescription": "Ryujinx nie mógł znaleźć twojego pliku 'prod.keys'",
"UserErrorNoFirmwareDescription": "Ryujinx nie mógł znaleźć żadnego zainstalowanego firmware'u",
"UserErrorFirmwareParsingFailedDescription": "Ryujinx nie był w stanie zparsować dostarczonego firmware'u. Jest to zwykle spowodowane nieaktualnymi kluczami.",
"UserErrorApplicationNotFoundDescription": "Ryujinx nie mógł znaleźć prawidłowej aplikacji na podanej ścieżce.",
"UserErrorUnknownDescription": "Wystąpił nieznany błąd!",
"UserErrorUndefinedDescription": "Wystąpił niezdefiniowany błąd! To nie powinno się zdarzyć, skontaktuj się z deweloperem!",
"OpenSetupGuideMessage": "Otwórz Podręcznik Konfiguracji",
"NoUpdate": "Brak Aktualizacji",
"TitleUpdateVersionLabel": "Wersja {0} - {1}",
"RyujinxInfo": "Ryujinx - Info",
"RyujinxConfirm": "Ryujinx - Potwierdzenie",
"FileDialogAllTypes": "Wszystkie typy",
"Never": "Nigdy",
"SwkbdMinCharacters": "Musi mieć co najmniej {0} znaków",
"SwkbdMinRangeCharacters": "Musi mieć długość od {0}-{1} znaków",
"SoftwareKeyboard": "Klawiatura Oprogramowania",
"DialogControllerAppletMessagePlayerRange": "Aplikacja żąda {0} graczy z:\n\nTYPY: {1}\n\nGRACZE: {2}\n\n{3}Otwórz Ustawienia i ponownie skonfiguruj Sterowanie lub naciśnij Zamknij.",
"DialogControllerAppletMessage": "Aplikacja żąda dokładnie {0} graczy z:\n\nTYPY: {1}\n\nGRACZE: {2}\n\n{3}Otwórz teraz Ustawienia i ponownie skonfiguruj Sterowanie lub naciśnij Zamknij.",
"DialogControllerAppletDockModeSet": "Ustawiono tryb Zadokowane. Przenośny też jest nieprawidłowy.\n\n",
"UpdaterRenaming": "Zmienianie Nazw Starych Plików...",
"UpdaterRenameFailed": "Aktualizator nie mógł zmienić nazwy pliku: {0}",
"UpdaterAddingFiles": "Dodawanie Nowych Plików...",
"UpdaterExtracting": "Wypakowywanie Aktualizacji...",
"UpdaterDownloading": "Pobieranie Aktualizacji...",
"Game": "Gra",
"Docked": "Zadokowany",
"Handheld": "Przenośny",
"ConnectionError": "Błąd Połączenia.",
"AboutPageDeveloperListMore": "{0} i więcej...",
"ApiError": "Błąd API.",
"LoadingHeading": "Wczytywanie {0}",
"CompilingPPTC": "Kompilowanie PTC",
"CompilingShaders": "Kompilowanie Shaderów",
"AllKeyboards": "Wszystkie klawiatury",
"OpenFileDialogTitle": "Wybierz obsługiwany plik do otwarcia",
"OpenFolderDialogTitle": "Wybierz folder z rozpakowaną grą",
"AllSupportedFormats": "Wszystkie Obsługiwane Formaty",
"RyujinxUpdater": "Aktualizator Ryujinx",
"SettingsTabHotkeys": "Skróty Klawiszowe Klawiatury",
"SettingsTabHotkeysHotkeys": "Skróty Klawiszowe Klawiatury",
"SettingsTabHotkeysToggleVsyncHotkey": "Przełącz VSync:",
"SettingsTabHotkeysScreenshotHotkey": "Zrzut Ekranu:",
"SettingsTabHotkeysShowUiHotkey": "Pokaż UI:",
"SettingsTabHotkeysPauseHotkey": "Pauza:",
"SettingsTabHotkeysToggleMuteHotkey": "Wycisz:",
"ControllerMotionTitle": "Ustawienia Sterowania Ruchowego",
"ControllerRumbleTitle": "Ustawienia Wibracji",
"SettingsSelectThemeFileDialogTitle": "Wybierz Plik Motywu",
"SettingsXamlThemeFile": "Plik Motywu Xaml",
"AvatarWindowTitle": "Zarządzaj Kontami — Avatar",
"Amiibo": "Amiibo",
"Unknown": "Nieznane",
"Usage": "Użycie",
"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",
"CheatWindowHeading": "Kody Dostępne dla {0} [{1}]",
"DlcWindowHeading": "DLC Dostępne dla {0} [{1}]",
"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}]",
"SettingsTabHotkeysResScaleUpHotkey": "Zwiększ Rozdzielczość:",
"SettingsTabHotkeysResScaleDownHotkey": "Zmniejsz Rozdzielczość:",
"UserProfilesName": "Nazwa:",
"UserProfilesUserId" : "ID Użytkownika:",
"SettingsTabGraphicsBackend": "Backend Graficzny",
"SettingsTabGraphicsBackendTooltip": "Używalne Backendy Graficzne",
"SettingsEnableTextureRecompression": "Włącz Rekompresję Tekstur",
"SettingsEnableTextureRecompressionTooltip": "Kompresuje niektóre tekstury w celu zmniejszenia zużycia pamięci VRAM.\n\nZalecane do użytku z GPU, które mają mniej niż 4 GB pamięci VRAM.\n\nW razie wątpliwości pozostaw WYŁĄCZONE.",
"SettingsTabGraphicsPreferredGpu": "Preferowane GPU",
"SettingsTabGraphicsPreferredGpuTooltip": "Wybierz kartę graficzną, która będzie używana z backendem graficznym Vulkan.\n\nNie wpływa na GPU używane przez OpenGL.\n\nW razie wątpliwości ustaw flagę GPU jako \"dGPU\". Jeśli żadnej nie ma, pozostaw nietknięte.",
"SettingsAppRequiredRestartMessage": "Wymagane Zrestartowanie Ryujinx",
"SettingsGpuBackendRestartMessage": "Zmieniono ustawienia Backendu Graficznego lub GPU. Będzie to wymagało ponownego uruchomienia",
"SettingsGpuBackendRestartSubMessage": "Czy chcesz zrestartować teraz?"
}

Some files were not shown because too many files have changed in this diff Show More