Compare commits

...

11 Commits

Author SHA1 Message Date
79becc4b78 Dynamically increase buffer size when resizing (#2861)
* Grow buffers by 1.5x of its size when resizing

* Further restrict the cases where the dynamic expansion is done
2022-03-15 03:33:53 +01:00
223172ac0b Ui: Add option to show/hide console window (Windows-only) (#3170)
* Ui: Add option to show/hide console window (Windows-only)

* Ui: Only display Show Console menu item on Windows

* ConsoleHelper: Handle NULL case

This will never happen

* Address nits

* Address comments

* Address comments 2
2022-03-15 02:35:41 +01:00
8c9633d72f Initialize indexed inputs used on next shader stage (#3198) 2022-03-14 20:02:50 -03:00
1f93fd52d9 Do not initialize geometry shader passthrough attributes (#3196) 2022-03-14 19:35:41 -03:00
aac7bbd378 olsc: Implement GetSaveDataBackupSetting (#3190)
* olsc: Implement GetSaveDataBackupSetting

This PR implement GetSaveDataBackupSetting of OLSC service which is now needed by ACNH 2.0.5. The game is playable as usual if you use the same user profile as the original save file (I don't know if it was the case before), everything is checked by RE.

* addresses gdkchan feedback
2022-03-12 18:38:49 +01:00
bed516bfda Implement rotate stick 90 degrees clockwise (#3084)
* Implement swapping sticks

* Rotate 90 degrees clockwise

Co-authored-by: matesic.darko@gmail.com <Darkman1979>
2022-03-12 18:23:48 +01:00
69b05f9918 Fix GetUserDisableCount NRE (#3187) 2022-03-12 18:12:12 +01:00
fb7c80e928 Limit number of events that can be retrieved from GetDisplayVSyncEvent (#3188)
* Limit number of events that can be retrieved from GetDisplayVSyncEvent

* Cleaning

* Rename openDisplayInfos -> openDisplays
2022-03-12 17:56:19 +01:00
bb2f9df0a1 KThread: Fix GetPsr mask (#3180)
* ExecutionContext: GetPstate / SetPstate

* Put it in NativeContext

* KThread: Fix GetPsr mask

* ExecutionContext: Turn methods into Pstate property

* Address nit
2022-03-11 03:16:32 +01:00
54bfaa125d amadeus: Fix wrong Span usage in CopyHistories (#3181)
Fix a copypasta from the original Amadeus PR causing invalid
CopyHistories output.

Also added a missing size check.

This fix a crash in Mononoke Slashdown
2022-03-07 09:49:29 +01:00
7af9fcbc06 T32: Implement Data Processing (Modified Immediate) instructions (#3178)
* T32: Implement Data Processing (Modified Immediate) instructions

* Update tests

* switch -> lookup table
2022-03-06 22:25:01 +01:00
29 changed files with 901 additions and 50 deletions

View File

@ -0,0 +1,38 @@
using ARMeilleure.Common;
using System.Runtime.Intrinsics;
namespace ARMeilleure.Decoders
{
class OpCodeT32AluImm : OpCodeT32Alu, IOpCode32AluImm
{
public int Immediate { get; }
public bool IsRotated { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluImm(inst, address, opCode);
private static readonly Vector128<int> _factor = Vector128.Create(1, 0x00010001, 0x01000100, 0x01010101);
public OpCodeT32AluImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
int imm8 = (opCode >> 0) & 0xff;
int imm3 = (opCode >> 12) & 7;
int imm1 = (opCode >> 26) & 1;
int imm12 = imm8 | (imm3 << 8) | (imm1 << 11);
if ((imm12 >> 10) == 0)
{
Immediate = imm8 * _factor.GetElement((imm12 >> 8) & 3);
IsRotated = false;
}
else
{
int shift = imm12 >> 7;
Immediate = BitUtils.RotateRight(0x80 | (imm12 & 0x7f), shift, 32);
IsRotated = shift != 0;
}
}
}
}

View File

@ -1048,25 +1048,41 @@ namespace ARMeilleure.Decoders
#region "OpCode Table (AArch32, T32)"
// Base
SetT32("11101011010xxxxx0xxxxxxxxxxxxxxx", InstName.Adc, InstEmit32.Adc, OpCodeT32AluRsImm.Create);
SetT32("11110x01010xxxxx0xxxxxxxxxxxxxxx", InstName.Adc, InstEmit32.Adc, OpCodeT32AluImm.Create);
SetT32("11101011000<xxxx0xxx<<<<xxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT32AluRsImm.Create);
SetT32("11110x01000<xxxx0xxx<<<<xxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT32AluImm.Create);
SetT32("11101010000<xxxx0xxx<<<<xxxxxxxx", InstName.And, InstEmit32.And, OpCodeT32AluRsImm.Create);
SetT32("11110x00000<xxxx0xxx<<<<xxxxxxxx", InstName.And, InstEmit32.And, OpCodeT32AluImm.Create);
SetT32("11110x<<<xxxxxxx10x0xxxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT32BImm20.Create);
SetT32("11110xxxxxxxxxxx10x1xxxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT32BImm24.Create);
SetT32("11101010001xxxxx0xxxxxxxxxxxxxxx", InstName.Bic, InstEmit32.Bic, OpCodeT32AluRsImm.Create);
SetT32("11110x00001xxxxx0xxxxxxxxxxxxxxx", InstName.Bic, InstEmit32.Bic, OpCodeT32AluImm.Create);
SetT32("11110xxxxxxxxxxx11x1xxxxxxxxxxxx", InstName.Bl, InstEmit32.Bl, OpCodeT32BImm24.Create);
SetT32("11110xxxxxxxxxxx11x0xxxxxxxxxxx0", InstName.Blx, InstEmit32.Blx, OpCodeT32BImm24.Create);
SetT32("111010110001xxxx0xxx1111xxxxxxxx", InstName.Cmn, InstEmit32.Cmn, OpCodeT32AluRsImm.Create);
SetT32("11110x010001xxxx0xxx1111xxxxxxxx", InstName.Cmn, InstEmit32.Cmn, OpCodeT32AluImm.Create);
SetT32("111010111011xxxx0xxx1111xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT32AluRsImm.Create);
SetT32("11110x011011xxxx0xxx1111xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT32AluImm.Create);
SetT32("11101010100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCodeT32AluRsImm.Create);
SetT32("11110x00100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCodeT32AluImm.Create);
SetT32("11101010010x11110xxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32AluRsImm.Create);
SetT32("11110x00010x11110xxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32AluImm.Create);
SetT32("11101010011x11110xxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCodeT32AluRsImm.Create);
SetT32("11110x00011x11110xxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCodeT32AluImm.Create);
SetT32("11101010011x<<<<0xxxxxxxxxxxxxxx", InstName.Orn, InstEmit32.Orn, OpCodeT32AluRsImm.Create);
SetT32("11110x00011x<<<<0xxxxxxxxxxxxxxx", InstName.Orn, InstEmit32.Orn, OpCodeT32AluImm.Create);
SetT32("11101010010x<<<<0xxxxxxxxxxxxxxx", InstName.Orr, InstEmit32.Orr, OpCodeT32AluRsImm.Create);
SetT32("11110x00010x<<<<0xxxxxxxxxxxxxxx", InstName.Orr, InstEmit32.Orr, OpCodeT32AluImm.Create);
SetT32("11101011110xxxxx0xxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, OpCodeT32AluRsImm.Create);
SetT32("11110x01110xxxxx0xxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, OpCodeT32AluImm.Create);
SetT32("11101011011xxxxx0xxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCodeT32AluRsImm.Create);
SetT32("11110x01011xxxxx0xxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCodeT32AluImm.Create);
SetT32("11101011101<xxxx0xxx<<<<xxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT32AluRsImm.Create);
SetT32("11110x01101<xxxx0xxx<<<<xxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT32AluImm.Create);
SetT32("111010101001xxxx0xxx1111xxxxxxxx", InstName.Teq, InstEmit32.Teq, OpCodeT32AluRsImm.Create);
SetT32("11110x001001xxxx0xxx1111xxxxxxxx", InstName.Teq, InstEmit32.Teq, OpCodeT32AluImm.Create);
SetT32("111010100001xxxx0xxx1111xxxxxxxx", InstName.Tst, InstEmit32.Tst, OpCodeT32AluRsImm.Create);
SetT32("11110x000001xxxx0xxx1111xxxxxxxx", InstName.Tst, InstEmit32.Tst, OpCodeT32AluImm.Create);
#endregion
FillFastLookupTable(InstA32FastLookup, AllInstA32, ToFastLookupIndexA);

View File

@ -43,6 +43,12 @@ namespace ARMeilleure.State
public long TpidrEl0 { get; set; }
public long Tpidr { get; set; }
public uint Pstate
{
get => _nativeContext.GetPstate();
set => _nativeContext.SetPstate(value);
}
public FPCR Fpcr { get; set; }
public FPSR Fpsr { get; set; }
public FPCR StandardFpcrValue => (Fpcr & (FPCR.Ahp)) | FPCR.Dn | FPCR.Fz;

View File

@ -95,6 +95,25 @@ namespace ARMeilleure.State
GetStorage().Flags[(int)flag] = value ? 1u : 0u;
}
public unsafe uint GetPstate()
{
uint value = 0;
for (int flag = 0; flag < RegisterConsts.FlagsCount; flag++)
{
value |= GetStorage().Flags[flag] != 0 ? 1u << flag : 0u;
}
return value;
}
public unsafe void SetPstate(uint value)
{
for (int flag = 0; flag < RegisterConsts.FlagsCount; flag++)
{
uint bit = 1u << flag;
GetStorage().Flags[flag] = (value & bit) == bit ? 1u : 0u;
}
}
public unsafe bool GetFPStateFlag(FPState flag)
{
if ((uint)flag >= RegisterConsts.FpFlagsCount)

View File

@ -149,11 +149,21 @@ namespace Ryujinx.Audio.Renderer.Server.Performance
Span<byte> targetSpan = performanceOutput.Slice(nextOffset);
// NOTE: We check for the space for two headers for the final blank header.
int requiredSpace = Unsafe.SizeOf<THeader>() + Unsafe.SizeOf<TEntry>() * inputHeader.GetEntryCount()
+ Unsafe.SizeOf<TEntryDetail>() * inputHeader.GetEntryDetailCount()
+ Unsafe.SizeOf<THeader>();
if (targetSpan.Length < requiredSpace)
{
break;
}
ref THeader outputHeader = ref MemoryMarshal.Cast<byte, THeader>(targetSpan)[0];
nextOffset += Unsafe.SizeOf<THeader>();
Span<TEntry> outputEntries = MemoryMarshal.Cast<byte, TEntry>(targetSpan.Slice(nextOffset));
Span<TEntry> outputEntries = MemoryMarshal.Cast<byte, TEntry>(performanceOutput.Slice(nextOffset));
int totalProcessingTime = 0;
@ -175,7 +185,7 @@ namespace Ryujinx.Audio.Renderer.Server.Performance
}
}
Span<TEntryDetail> outputEntriesDetail = MemoryMarshal.Cast<byte, TEntryDetail>(targetSpan.Slice(nextOffset));
Span<TEntryDetail> outputEntriesDetail = MemoryMarshal.Cast<byte, TEntryDetail>(performanceOutput.Slice(nextOffset));
int effectiveEntryDetailCount = 0;

View File

@ -5,6 +5,7 @@
public Stick Joystick { get; set; }
public bool InvertStickX { get; set; }
public bool InvertStickY { get; set; }
public bool Rotate90CW { get; set; }
public Button StickButton { get; set; }
}
}

View File

@ -17,6 +17,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
private const ulong BufferAlignmentSize = 0x1000;
private const ulong BufferAlignmentMask = BufferAlignmentSize - 1;
private const ulong MaxDynamicGrowthSize = 0x100000;
private readonly GpuContext _context;
private readonly PhysicalMemory _physicalMemory;
@ -166,10 +168,35 @@ namespace Ryujinx.Graphics.Gpu.Memory
// Otherwise, we must delete the overlapping buffers and create a bigger buffer
// that fits all the data we need. We also need to copy the contents from the
// old buffer(s) to the new buffer.
ulong endAddress = address + size;
if (_bufferOverlaps[0].Address > address || _bufferOverlaps[0].EndAddress < endAddress)
{
// Check if the following conditions are met:
// - We have a single overlap.
// - The overlap starts at or before the requested range. That is, the overlap happens at the end.
// - The size delta between the new, merged buffer and the old one is of at most 2 pages.
// In this case, we attempt to extend the buffer further than the requested range,
// this can potentially avoid future resizes if the application keeps using overlapping
// sequential memory.
// Allowing for 2 pages (rather than just one) is necessary to catch cases where the
// range crosses a page, and after alignment, ends having a size of 2 pages.
if (overlapsCount == 1 &&
address >= _bufferOverlaps[0].Address &&
endAddress - _bufferOverlaps[0].EndAddress <= BufferAlignmentSize * 2)
{
// Try to grow the buffer by 1.5x of its current size.
// This improves performance in the cases where the buffer is resized often by small amounts.
ulong existingSize = _bufferOverlaps[0].Size;
ulong growthSize = (existingSize + Math.Min(existingSize >> 1, MaxDynamicGrowthSize)) & ~BufferAlignmentMask;
size = Math.Max(size, growthSize);
endAddress = address + size;
overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref _bufferOverlaps);
}
for (int index = 0; index < overlapsCount; index++)
{
Buffer buffer = _bufferOverlaps[index];
@ -183,7 +210,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
}
Buffer newBuffer = new Buffer(_context, _physicalMemory, address, endAddress - address, _bufferOverlaps.Take(overlapsCount));
ulong newSize = endAddress - address;
Buffer newBuffer = new Buffer(_context, _physicalMemory, address, newSize, _bufferOverlaps.Take(overlapsCount));
lock (_buffers)
{
@ -202,7 +231,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
buffer.DisposeData();
}
newBuffer.SynchronizeMemory(address, endAddress - address);
newBuffer.SynchronizeMemory(address, newSize);
// Existing buffers were modified, we need to rebind everything.
NotifyBuffersModified?.Invoke();

View File

@ -328,6 +328,7 @@ namespace Ryujinx.Graphics.Shader.Translation
public void SetAllInputUserAttributes()
{
UsedInputAttributes |= Constants.AllAttributesMask;
ThisInputAttributesComponents |= ~UInt128.Zero >> (128 - Constants.MaxAttributes * 4);
}
public void SetAllOutputUserAttributes()

View File

@ -218,10 +218,17 @@ namespace Ryujinx.Graphics.Shader.Translation
while (usedAttributes != UInt128.Zero)
{
int index = usedAttributes.TrailingZeroCount();
InitializeOutputComponent(context, AttributeConsts.UserAttributeBase + index * 4, perPatch: false);
int vecIndex = index / 4;
usedAttributes &= ~UInt128.Pow2(index);
// We don't need to initialize passthrough attributes.
if ((context.Config.PassthroughAttributes & (1 << vecIndex)) != 0)
{
continue;
}
InitializeOutputComponent(context, AttributeConsts.UserAttributeBase + index * 4, perPatch: false);
}
UInt128 usedAttributesPerPatch = context.Config.NextInputAttributesPerPatchComponents;

View File

@ -10,6 +10,12 @@ namespace Ryujinx.Graphics.Shader.Translation
private ulong _v0;
private ulong _v1;
public UInt128(ulong low, ulong high)
{
_v0 = low;
_v1 = high;
}
public int TrailingZeroCount()
{
int count = BitOperations.TrailingZeroCount(_v0);
@ -25,25 +31,57 @@ namespace Ryujinx.Graphics.Shader.Translation
{
if (x >= 64)
{
return new UInt128() { _v0 = 0, _v1 = 1UL << (x - 64 ) };
return new UInt128(0, 1UL << (x - 64));
}
return new UInt128() { _v0 = 1UL << x, _v1 = 0 };
return new UInt128(1UL << x, 0);
}
public static UInt128 operator ~(UInt128 x)
{
return new UInt128() { _v0 = ~x._v0, _v1 = ~x._v1 };
return new UInt128(~x._v0, ~x._v1);
}
public static UInt128 operator &(UInt128 x, UInt128 y)
{
return new UInt128() { _v0 = x._v0 & y._v0, _v1 = x._v1 & y._v1 };
return new UInt128(x._v0 & y._v0, x._v1 & y._v1);
}
public static UInt128 operator |(UInt128 x, UInt128 y)
{
return new UInt128() { _v0 = x._v0 | y._v0, _v1 = x._v1 | y._v1 };
return new UInt128(x._v0 | y._v0, x._v1 | y._v1);
}
public static UInt128 operator <<(UInt128 x, int shift)
{
if (shift == 0)
{
return new UInt128(x._v0, x._v1);
}
else if (shift >= 64)
{
return new UInt128(0, x._v0 << (shift - 64));
}
ulong shiftOut = x._v0 >> (64 - shift);
return new UInt128(x._v0 << shift, (x._v1 << shift) | shiftOut);
}
public static UInt128 operator >>(UInt128 x, int shift)
{
if (shift == 0)
{
return new UInt128(x._v0, x._v1);
}
else if (shift >= 64)
{
return new UInt128(x._v1 >> (shift - 64), 0);
}
ulong shiftOut = x._v1 & ((1UL << shift) - 1);
return new UInt128((x._v0 >> shift) | (shiftOut << (64 - shift)), x._v1 >> shift);
}
public static bool operator ==(UInt128 x, UInt128 y)

View File

@ -751,7 +751,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{
KThread currentThread = KernelStatic.GetCurrentThread();
if (currentThread.Owner != null &&
if (currentThread.Context.Running &&
currentThread.Owner != null &&
currentThread.GetUserDisableCount() != 0 &&
currentThread.Owner.PinnedThreads[currentThread.CurrentCore] == null)
{

View File

@ -658,10 +658,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
private static uint GetPsr(ARMeilleure.State.ExecutionContext context)
{
return (context.GetPstateFlag(ARMeilleure.State.PState.NFlag) ? (1U << (int)ARMeilleure.State.PState.NFlag) : 0U) |
(context.GetPstateFlag(ARMeilleure.State.PState.ZFlag) ? (1U << (int)ARMeilleure.State.PState.ZFlag) : 0U) |
(context.GetPstateFlag(ARMeilleure.State.PState.CFlag) ? (1U << (int)ARMeilleure.State.PState.CFlag) : 0U) |
(context.GetPstateFlag(ARMeilleure.State.PState.VFlag) ? (1U << (int)ARMeilleure.State.PState.VFlag) : 0U);
return context.Pstate & 0xFF0FFE20;
}
private ThreadContext GetCurrentContext()
@ -1371,7 +1368,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
PreferredCore = _originalPreferredCore;
AffinityMask = _originalAffinityMask;
if (AffinityMask != affinityMask)
{
if ((AffinityMask & 1UL << ActiveCore) != 0)

View File

@ -1,13 +1,15 @@
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Olsc
{
[Service("olsc:u")] // 10.0.0+
class IOlscServiceForApplication : IpcService
{
private bool _initialized;
private bool _initialized;
private Dictionary<UserId, bool> _saveDataBackupSettingDatabase;
public IOlscServiceForApplication(ServiceCtx context) { }
@ -16,7 +18,9 @@ namespace Ryujinx.HLE.HOS.Services.Olsc
public ResultCode Initialize(ServiceCtx context)
{
// NOTE: Service call arp:r GetApplicationInstanceUnregistrationNotifier with the pid and initialize some internal struct.
// Since we will not support online savedata backup. It's fine to stub it for now.
// Since we will not support online savedata backup, it's fine to stub it for now.
_saveDataBackupSettingDatabase = new Dictionary<UserId, bool>();
_initialized = true;
@ -25,12 +29,11 @@ namespace Ryujinx.HLE.HOS.Services.Olsc
return ResultCode.Success;
}
[CommandHipc(14)]
// SetSaveDataBackupSettingEnabled(nn::account::Uid, bool)
public ResultCode SetSaveDataBackupSettingEnabled(ServiceCtx context)
[CommandHipc(13)]
// GetSaveDataBackupSetting(nn::account::Uid) -> u8
public ResultCode GetSaveDataBackupSetting(ServiceCtx context)
{
UserId userId = context.RequestData.ReadStruct<UserId>();
ulong saveDataBackupSettingEnabled = context.RequestData.ReadUInt64();
UserId userId = context.RequestData.ReadStruct<UserId>();
if (!_initialized)
{
@ -42,8 +45,42 @@ namespace Ryujinx.HLE.HOS.Services.Olsc
return ResultCode.NullArgument;
}
// NOTE: Service store the UserId and the boolean in an internal SaveDataBackupSettingDatabase object.
// Since we will not support online savedata backup. It's fine to stub it for now.
if (_saveDataBackupSettingDatabase[userId])
{
context.ResponseData.Write((byte)1); // TODO: Determine value.
}
else
{
context.ResponseData.Write((byte)2); // TODO: Determine value.
}
// NOTE: Since we will not support online savedata backup, it's fine to stub it for now.
Logger.Stub?.PrintStub(LogClass.ServiceOlsc, new { userId });
return ResultCode.Success;
}
[CommandHipc(14)]
// SetSaveDataBackupSettingEnabled(nn::account::Uid, bool)
public ResultCode SetSaveDataBackupSettingEnabled(ServiceCtx context)
{
bool saveDataBackupSettingEnabled = context.RequestData.ReadUInt64() != 0;
UserId userId = context.RequestData.ReadStruct<UserId>();
if (!_initialized)
{
return ResultCode.NotInitialized;
}
if (userId.IsNull)
{
return ResultCode.NullArgument;
}
_saveDataBackupSettingDatabase[userId] = saveDataBackupSettingEnabled;
// NOTE: Since we will not support online savedata backup, it's fine to stub it for now.
Logger.Stub?.PrintStub(LogClass.ServiceOlsc, new { userId, saveDataBackupSettingEnabled });

View File

@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
if (serviceType != ViServiceType.Application)
{
return ResultCode.InvalidRange;
return ResultCode.PermissionDenied;
}
MakeObject(context, new IApplicationDisplayService(serviceType));

View File

@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
if (serviceType != ViServiceType.Manager)
{
return ResultCode.InvalidRange;
return ResultCode.PermissionDenied;
}
MakeObject(context, new IApplicationDisplayService(serviceType));

View File

@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
if (serviceType != ViServiceType.System)
{
return ResultCode.InvalidRange;
return ResultCode.PermissionDenied;
}
MakeObject(context, new IApplicationDisplayService(serviceType));

View File

@ -9,7 +9,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
InvalidArguments = (1 << ErrorCodeShift) | ModuleId,
InvalidLayerSize = (4 << ErrorCodeShift) | ModuleId,
InvalidRange = (5 << ErrorCodeShift) | ModuleId,
PermissionDenied = (5 << ErrorCodeShift) | ModuleId,
InvalidScalingMode = (6 << ErrorCodeShift) | ModuleId,
InvalidValue = (7 << ErrorCodeShift) | ModuleId,
AlreadyOpened = (9 << ErrorCodeShift) | ModuleId

View File

@ -1,7 +1,6 @@
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.Common.Memory;
using Ryujinx.Cpu;
using Ryujinx.HLE.HOS.Applets;
using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel.Common;
@ -22,16 +21,21 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
{
private readonly ViServiceType _serviceType;
private readonly List<DisplayInfo> _displayInfo;
private readonly Dictionary<ulong, DisplayInfo> _openDisplayInfo;
private class DisplayState
{
public int RetrievedEventsCount;
}
private readonly List<DisplayInfo> _displayInfo;
private readonly Dictionary<ulong, DisplayState> _openDisplays;
private int _vsyncEventHandle;
public IApplicationDisplayService(ViServiceType serviceType)
{
_serviceType = serviceType;
_displayInfo = new List<DisplayInfo>();
_openDisplayInfo = new Dictionary<ulong, DisplayInfo>();
_serviceType = serviceType;
_displayInfo = new List<DisplayInfo>();
_openDisplays = new Dictionary<ulong, DisplayState>();
void AddDisplayInfo(string name, bool layerLimitEnabled, ulong layerLimitMax, ulong width, ulong height)
{
@ -64,7 +68,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
// FIXME: Should be _serviceType != ViServiceType.Application but guests crashes if we do this check.
if (_serviceType > ViServiceType.System)
{
return ResultCode.InvalidRange;
return ResultCode.PermissionDenied;
}
MakeObject(context, new HOSBinderDriverServer());
@ -79,7 +83,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
// FIXME: Should be _serviceType == ViServiceType.System but guests crashes if we do this check.
if (_serviceType > ViServiceType.System)
{
return ResultCode.InvalidRange;
return ResultCode.PermissionDenied;
}
MakeObject(context, new ISystemDisplayService(this));
@ -93,7 +97,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
{
if (_serviceType > ViServiceType.System)
{
return ResultCode.InvalidRange;
return ResultCode.PermissionDenied;
}
MakeObject(context, new IManagerDisplayService(this));
@ -107,7 +111,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
{
if (_serviceType > ViServiceType.System)
{
return ResultCode.InvalidRange;
return ResultCode.PermissionDenied;
}
MakeObject(context, new HOSBinderDriverServer());
@ -174,7 +178,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
return ResultCode.InvalidValue;
}
if (!_openDisplayInfo.TryAdd((ulong)displayId, _displayInfo[displayId]))
if (!_openDisplays.TryAdd((ulong)displayId, new DisplayState()))
{
return ResultCode.AlreadyOpened;
}
@ -190,7 +194,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
{
ulong displayId = context.RequestData.ReadUInt64();
if (!_openDisplayInfo.Remove(displayId))
if (!_openDisplays.Remove(displayId))
{
return ResultCode.InvalidValue;
}
@ -454,11 +458,16 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
{
ulong displayId = context.RequestData.ReadUInt64();
if (!_openDisplayInfo.ContainsKey(displayId))
if (!_openDisplays.TryGetValue(displayId, out DisplayState displayState))
{
return ResultCode.InvalidValue;
}
if (displayState.RetrievedEventsCount > 0)
{
return ResultCode.PermissionDenied;
}
if (_vsyncEventHandle == 0)
{
if (context.Process.HandleTable.GenerateHandle(context.Device.System.VsyncEvent.ReadableEvent, out _vsyncEventHandle) != KernelResult.Success)
@ -467,6 +476,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
}
}
displayState.RetrievedEventsCount++;
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_vsyncEventHandle);
return ResultCode.Success;

View File

@ -220,6 +220,7 @@ namespace Ryujinx.Headless.SDL2
StickButton = ConfigGamepadInputId.LeftStick,
InvertStickX = false,
InvertStickY = false,
Rotate90CW = false,
},
RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
@ -241,6 +242,7 @@ namespace Ryujinx.Headless.SDL2
StickButton = ConfigGamepadInputId.RightStick,
InvertStickX = false,
InvertStickY = false,
Rotate90CW = false,
},
Motion = new StandardMotionConfigController

View File

@ -350,6 +350,14 @@ namespace Ryujinx.Input.SDL2
{
resultY = -resultY;
}
if ((inputId == StickInputId.Left && _configuration.LeftJoyconStick.Rotate90CW) ||
(inputId == StickInputId.Right && _configuration.RightJoyconStick.Rotate90CW))
{
float temp = resultX;
resultX = resultY;
resultY = -temp;
}
}
return (resultX, resultY);

View File

@ -283,10 +283,7 @@ namespace Ryujinx.Tests.Cpu
}
uint finalCpsr = test.FinalRegs[15];
for (int i = 0; i < 32; i++)
{
Assert.That(GetContext().GetPstateFlag((PState)i), Is.EqualTo((finalCpsr & (1u << i)) != 0));
}
Assert.That(GetContext().Pstate, Is.EqualTo(finalCpsr));
}
protected void SetWorkingMemory(uint offset, byte[] data)

View File

@ -13,6 +13,12 @@ namespace Ryujinx.Tests.Cpu
RunPrecomputedTestCase(test);
}
[Test]
public void TestT32AluImm([ValueSource(nameof(ImmTestCases))] PrecomputedThumbTestCase test)
{
RunPrecomputedTestCase(test);
}
public static readonly PrecomputedThumbTestCase[] RsImmTestCases =
{
// TST (reg)
@ -506,5 +512,505 @@ namespace Ryujinx.Tests.Cpu
FinalRegs = new uint[] { 0x79108ff6, 0x0cb1e662, 0x9eb9ffed, 0x1ee4d3de, 0x7a8fa20a, 0x1db7e216, 0x6fc42752, 0x9cb6cdad, 0xa497a582, 0x654c446f, 0xcbb31efc, 0x601e6995, 0xe328af35, 0x824026e7, 0x00000000, 0x100001d0 },
},
};
public static readonly PrecomputedThumbTestCase[] ImmTestCases =
{
// TST (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf018, 0x0fd4, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xf5a1b919, 0x37ee0ad4, 0xec1bbb30, 0x8345ecb1, 0xf733e93e, 0x76668927, 0xa9b16176, 0x34b9678e, 0xa6167f8b, 0xea4f20a9, 0x45345e75, 0xc8a2ea55, 0xae108472, 0x67b5e3a4, 0x00000001, 0xb00001f0 },
FinalRegs = new uint[] { 0xf5a1b919, 0x37ee0ad4, 0xec1bbb30, 0x8345ecb1, 0xf733e93e, 0x76668927, 0xa9b16176, 0x34b9678e, 0xa6167f8b, 0xea4f20a9, 0x45345e75, 0xc8a2ea55, 0xae108472, 0x67b5e3a4, 0x00000001, 0x300001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf41b, 0x1fff, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xfc928b9b, 0xeff1f0a6, 0xe1cd22ba, 0xef1e4a75, 0x10779ef3, 0x3b003004, 0x7a532842, 0x2e71a8c4, 0x62b71ce6, 0x5ffcf3ce, 0xdbe8efa1, 0x86822f2b, 0x560da6b6, 0x46550850, 0x00000001, 0x700001f0 },
FinalRegs = new uint[] { 0xfc928b9b, 0xeff1f0a6, 0xe1cd22ba, 0xef1e4a75, 0x10779ef3, 0x3b003004, 0x7a532842, 0x2e71a8c4, 0x62b71ce6, 0x5ffcf3ce, 0xdbe8efa1, 0x86822f2b, 0x560da6b6, 0x46550850, 0x00000001, 0x100001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf416, 0x7f97, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xd0ba5d0a, 0xc8fa5c53, 0xac3069cb, 0x4be76d89, 0xcc9b4f47, 0x36984914, 0xd49fe0a5, 0x7d80c756, 0x8210fb6d, 0xcb498541, 0xc366597f, 0xacef4405, 0xdf6341a9, 0x6a1124b8, 0x00000001, 0xc00001f0 },
FinalRegs = new uint[] { 0xd0ba5d0a, 0xc8fa5c53, 0xac3069cb, 0x4be76d89, 0xcc9b4f47, 0x36984914, 0xd49fe0a5, 0x7d80c756, 0x8210fb6d, 0xcb498541, 0xc366597f, 0xacef4405, 0xdf6341a9, 0x6a1124b8, 0x00000001, 0x000001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf016, 0x0f12, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xb8568ac2, 0x67a7ee09, 0x266abe3b, 0x9d93101d, 0x504b4adb, 0x45838822, 0x62126cc4, 0xf4198159, 0xf24a524c, 0x163fa3e9, 0x3c6d489e, 0xacef0dff, 0x73fc8fdd, 0x9d34fc09, 0x00000001, 0x800001f0 },
FinalRegs = new uint[] { 0xb8568ac2, 0x67a7ee09, 0x266abe3b, 0x9d93101d, 0x504b4adb, 0x45838822, 0x62126cc4, 0xf4198159, 0xf24a524c, 0x163fa3e9, 0x3c6d489e, 0xacef0dff, 0x73fc8fdd, 0x9d34fc09, 0x00000001, 0x400001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf017, 0x2fd1, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x5548cee0, 0x59a88eb4, 0x3624d775, 0x98fe9a19, 0x84d1b83f, 0xed2c476a, 0x046a6aea, 0x0c92fadb, 0xdff5abe1, 0x91a16e82, 0xbb0f8ba4, 0x87c1888c, 0xa2df958e, 0x6cebba03, 0x00000001, 0x400001f0 },
FinalRegs = new uint[] { 0x5548cee0, 0x59a88eb4, 0x3624d775, 0x98fe9a19, 0x84d1b83f, 0xed2c476a, 0x046a6aea, 0x0c92fadb, 0xdff5abe1, 0x91a16e82, 0xbb0f8ba4, 0x87c1888c, 0xa2df958e, 0x6cebba03, 0x00000001, 0x000001f0 },
},
// AND (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf403, 0x3ce5, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xddd90378, 0xc3a2891f, 0x3d5007a2, 0x0f0c0756, 0xbdc5c113, 0xeee78000, 0x90693126, 0x8763b349, 0xbf6814b4, 0x40160bf9, 0xfff4a26d, 0x16a11d59, 0x26b3b8cc, 0xeb09487f, 0x00000001, 0x200001f0 },
FinalRegs = new uint[] { 0xddd90378, 0xc3a2891f, 0x3d5007a2, 0x0f0c0756, 0xbdc5c113, 0xeee78000, 0x90693126, 0x8763b349, 0xbf6814b4, 0x40160bf9, 0xfff4a26d, 0x16a11d59, 0x00000200, 0xeb09487f, 0x00000001, 0x200001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf00a, 0x177d, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xce4db266, 0x67f21be8, 0x0de0c290, 0x2615cfc5, 0x6e3c46cb, 0x44a52240, 0xb12e0470, 0x903e0182, 0x61c32a9a, 0x58bf0753, 0xa9b3c209, 0x68ec1f37, 0x9320a3c9, 0xab952fd9, 0x00000001, 0xa00001f0 },
FinalRegs = new uint[] { 0xce4db266, 0x67f21be8, 0x0de0c290, 0x2615cfc5, 0x6e3c46cb, 0x44a52240, 0xb12e0470, 0x00310009, 0x61c32a9a, 0x58bf0753, 0xa9b3c209, 0x68ec1f37, 0x9320a3c9, 0xab952fd9, 0x00000001, 0xa00001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf014, 0x2913, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x4257c8eb, 0xd9eaf199, 0xe9381b0a, 0x39fcb309, 0xb1f24181, 0xebb2b7e4, 0x73799a0f, 0xc70a2fc7, 0xe2af6496, 0xb9014f5b, 0xe22ff568, 0x12dd4afe, 0x6d8544ac, 0x9293d043, 0x00000001, 0x000001f0 },
FinalRegs = new uint[] { 0x4257c8eb, 0xd9eaf199, 0xe9381b0a, 0x39fcb309, 0xb1f24181, 0xebb2b7e4, 0x73799a0f, 0xc70a2fc7, 0xe2af6496, 0x11000100, 0xe22ff568, 0x12dd4afe, 0x6d8544ac, 0x9293d043, 0x00000001, 0x000001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf004, 0x27c2, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x8d7ceb35, 0x000e9260, 0x6825b561, 0xbcf66952, 0x3fbc7775, 0xd5afaa83, 0xe4fde261, 0xa35fa71e, 0xbefc5c9f, 0x667d9163, 0x8c2543b0, 0xd8489b89, 0x661ffec5, 0x45ccdaa8, 0x00000001, 0xd00001f0 },
FinalRegs = new uint[] { 0x8d7ceb35, 0x000e9260, 0x6825b561, 0xbcf66952, 0x3fbc7775, 0xd5afaa83, 0xe4fde261, 0x02004200, 0xbefc5c9f, 0x667d9163, 0x8c2543b0, 0xd8489b89, 0x661ffec5, 0x45ccdaa8, 0x00000001, 0xd00001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf008, 0x6ce5, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x78a2a638, 0x54ac2bd7, 0x60ad5509, 0x9c38b11f, 0x8dd109de, 0xd07aea77, 0xf5a0bcfc, 0xbcd81a17, 0x2f159ebd, 0xcc7e8454, 0x04621cce, 0xd0e9eca5, 0xb33f4ba6, 0x1e2bb5b2, 0x00000001, 0xf00001f0 },
FinalRegs = new uint[] { 0x78a2a638, 0x54ac2bd7, 0x60ad5509, 0x9c38b11f, 0x8dd109de, 0xd07aea77, 0xf5a0bcfc, 0xbcd81a17, 0x2f159ebd, 0xcc7e8454, 0x04621cce, 0xd0e9eca5, 0x07000000, 0x1e2bb5b2, 0x00000001, 0xf00001f0 },
},
// BIC (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf420, 0x6425, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x28c2ef44, 0x206bdfed, 0x30c780a9, 0x440ab4ab, 0x666fc882, 0x92a4aa1d, 0x3ceb6b36, 0xca757a75, 0xdf2f77b7, 0xae012305, 0x06b5c956, 0x0ff05e78, 0xad918973, 0x73778e28, 0x00000001, 0xe00001f0 },
FinalRegs = new uint[] { 0x28c2ef44, 0x206bdfed, 0x30c780a9, 0x440ab4ab, 0x28c2e504, 0x92a4aa1d, 0x3ceb6b36, 0xca757a75, 0xdf2f77b7, 0xae012305, 0x06b5c956, 0x0ff05e78, 0xad918973, 0x73778e28, 0x00000001, 0xe00001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf430, 0x44ed, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x5cd96673, 0xa1c27ac5, 0xbb205490, 0xa844d844, 0x1e66662f, 0x0f259402, 0xbe81472f, 0x36d55b13, 0x02c6d2a2, 0xc39c31b1, 0x59b71936, 0xf1914252, 0xef8188b8, 0x0c18bea1, 0x00000001, 0x700001f0 },
FinalRegs = new uint[] { 0x5cd96673, 0xa1c27ac5, 0xbb205490, 0xa844d844, 0x5cd90073, 0x0f259402, 0xbe81472f, 0x36d55b13, 0x02c6d2a2, 0xc39c31b1, 0x59b71936, 0xf1914252, 0xef8188b8, 0x0c18bea1, 0x00000001, 0x100001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf038, 0x1334, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xe0afc0e0, 0x7ffd49d1, 0x6fe858fa, 0x7564882e, 0xaa895bf1, 0x725f4071, 0x612b9956, 0xb28fd700, 0xf0acd15c, 0xb62cf0bb, 0x1d9d5c1f, 0xdc3942a2, 0x9b3248ea, 0x3b7593ca, 0x00000001, 0xb00001f0 },
FinalRegs = new uint[] { 0xe0afc0e0, 0x7ffd49d1, 0x6fe858fa, 0xf088d148, 0xaa895bf1, 0x725f4071, 0x612b9956, 0xb28fd700, 0xf0acd15c, 0xb62cf0bb, 0x1d9d5c1f, 0xdc3942a2, 0x9b3248ea, 0x3b7593ca, 0x00000001, 0xb00001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf438, 0x51d7, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x75f070b0, 0x24e410c6, 0x128174fa, 0x04a10755, 0x6728fd35, 0xf6007f21, 0x0cb9efa3, 0x260e061c, 0xc5e02c94, 0x4aaa3354, 0x00796ab8, 0x897274d2, 0xe87dcffc, 0xa47bd3ab, 0x00000001, 0x200001f0 },
FinalRegs = new uint[] { 0x75f070b0, 0xc5e02414, 0x128174fa, 0x04a10755, 0x6728fd35, 0xf6007f21, 0x0cb9efa3, 0x260e061c, 0xc5e02c94, 0x4aaa3354, 0x00796ab8, 0x897274d2, 0xe87dcffc, 0xa47bd3ab, 0x00000001, 0x800001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf438, 0x1db2, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x62dcbe9e, 0x55f42016, 0x6689f461, 0x31e32805, 0x1fc90a1e, 0x02e3a47f, 0xf236bafd, 0x65006290, 0x0065bd7f, 0xc1752579, 0x59528615, 0x6ef68c79, 0x138b8bb3, 0x0761d66c, 0x00000001, 0xc00001f0 },
FinalRegs = new uint[] { 0x62dcbe9e, 0x55f42016, 0x6689f461, 0x31e32805, 0x1fc90a1e, 0x02e3a47f, 0xf236bafd, 0x65006290, 0x0065bd7f, 0xc1752579, 0x59528615, 0x6ef68c79, 0x138b8bb3, 0x0061bd7f, 0x00000001, 0x000001f0 },
},
// MOV (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf45f, 0x5032, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x6ed98807, 0x536a9cb7, 0x79c2d5bb, 0xc2e9a860, 0x185b4e57, 0x77c1c99f, 0x99a24897, 0xc6cc4ea1, 0xe3d294a6, 0xb8e525ae, 0xca245840, 0x27943892, 0xa76ed6fe, 0xecbcffe8, 0x00000001, 0xc00001f0 },
FinalRegs = new uint[] { 0x00002c80, 0x536a9cb7, 0x79c2d5bb, 0xc2e9a860, 0x185b4e57, 0x77c1c99f, 0x99a24897, 0xc6cc4ea1, 0xe3d294a6, 0xb8e525ae, 0xca245840, 0x27943892, 0xa76ed6fe, 0xecbcffe8, 0x00000001, 0x000001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf04f, 0x23f9, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x7e6bf90e, 0x87533a8f, 0x29389323, 0x96a37f30, 0x63e6e58e, 0xb8bb21d0, 0x5bd9ae04, 0x26b7a586, 0xfa359510, 0x131a4e95, 0x5d0adb02, 0xa8148f64, 0xbfe74669, 0xea2cdf2d, 0x00000001, 0xb00001f0 },
FinalRegs = new uint[] { 0x7e6bf90e, 0x87533a8f, 0x29389323, 0xf900f900, 0x63e6e58e, 0xb8bb21d0, 0x5bd9ae04, 0x26b7a586, 0xfa359510, 0x131a4e95, 0x5d0adb02, 0xa8148f64, 0xbfe74669, 0xea2cdf2d, 0x00000001, 0xb00001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf45f, 0x5351, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xd8b5d8b2, 0x7ae44f2b, 0xda909eb2, 0xdb2fe423, 0xb2486971, 0x23427a2c, 0x96c88749, 0xb88d6d78, 0x2f4aa092, 0xbf40760f, 0x88d72a3f, 0x88854e62, 0x8d459486, 0x82a8ba9f, 0x00000001, 0x300001f0 },
FinalRegs = new uint[] { 0xd8b5d8b2, 0x7ae44f2b, 0xda909eb2, 0x00003440, 0xb2486971, 0x23427a2c, 0x96c88749, 0xb88d6d78, 0x2f4aa092, 0xbf40760f, 0x88d72a3f, 0x88854e62, 0x8d459486, 0x82a8ba9f, 0x00000001, 0x100001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf45f, 0x207c, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x73063041, 0x038b5f4a, 0xf7e85421, 0xe935f110, 0x9a5c34de, 0xbc3dbed9, 0x1c57c517, 0x3294067f, 0x01cd78b5, 0xe7bfe428, 0x6e297fce, 0xccb2c833, 0x2e8bb930, 0xeb6e2004, 0x00000001, 0x300001f0 },
FinalRegs = new uint[] { 0x000fc000, 0x038b5f4a, 0xf7e85421, 0xe935f110, 0x9a5c34de, 0xbc3dbed9, 0x1c57c517, 0x3294067f, 0x01cd78b5, 0xe7bfe428, 0x6e297fce, 0xccb2c833, 0x2e8bb930, 0xeb6e2004, 0x00000001, 0x100001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf45f, 0x5073, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xd0d531fe, 0xeb1676df, 0x0acf5912, 0x6061b3fe, 0xecac2ae2, 0x40075143, 0x88a47781, 0x3ecb7baa, 0x6aee3603, 0x53133f32, 0x1e891e57, 0x4d7f8f94, 0xd09c727a, 0x28a79c93, 0x00000001, 0x400001f0 },
FinalRegs = new uint[] { 0x00003cc0, 0xeb1676df, 0x0acf5912, 0x6061b3fe, 0xecac2ae2, 0x40075143, 0x88a47781, 0x3ecb7baa, 0x6aee3603, 0x53133f32, 0x1e891e57, 0x4d7f8f94, 0xd09c727a, 0x28a79c93, 0x00000001, 0x000001f0 },
},
// ORR (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf45c, 0x03c9, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xc7d9e145, 0xc2a6bd5b, 0x92c8ca0b, 0x1fde4d2f, 0xa4705c7f, 0x47559e93, 0x9f9d3e22, 0x7b3719c0, 0x3746ffc9, 0xa1476ae8, 0x88f45e36, 0x0fc7d2a7, 0xaa94b64c, 0xe9fee33b, 0x00000001, 0x700001f0 },
FinalRegs = new uint[] { 0xc7d9e145, 0xc2a6bd5b, 0x92c8ca0b, 0xaaf4b64c, 0xa4705c7f, 0x47559e93, 0x9f9d3e22, 0x7b3719c0, 0x3746ffc9, 0xa1476ae8, 0x88f45e36, 0x0fc7d2a7, 0xaa94b64c, 0xe9fee33b, 0x00000001, 0x900001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf441, 0x60ec, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x2262c23f, 0xf8ba9254, 0x2a870feb, 0xa66d2c1a, 0xa3bb8f6d, 0x2f754de2, 0xb3b0b9be, 0xc3cf59e8, 0xebaa6300, 0x22ea8a3d, 0xf3bcf0f4, 0xffb0aae8, 0x4982d5ab, 0x4c945119, 0x00000001, 0x800001f0 },
FinalRegs = new uint[] { 0xf8ba9774, 0xf8ba9254, 0x2a870feb, 0xa66d2c1a, 0xa3bb8f6d, 0x2f754de2, 0xb3b0b9be, 0xc3cf59e8, 0xebaa6300, 0x22ea8a3d, 0xf3bcf0f4, 0xffb0aae8, 0x4982d5ab, 0x4c945119, 0x00000001, 0x800001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf44c, 0x5343, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x844cd5c4, 0x5a244353, 0xd74ff677, 0x25eefc9f, 0xa040f56f, 0x06e237a6, 0x7ccb1c91, 0xc9aa6d32, 0xf9e18bd6, 0xc0780954, 0x955d8f60, 0xa9cb014e, 0x64d583e2, 0x3e50533a, 0x00000001, 0x000001f0 },
FinalRegs = new uint[] { 0x844cd5c4, 0x5a244353, 0xd74ff677, 0x64d5b3e2, 0xa040f56f, 0x06e237a6, 0x7ccb1c91, 0xc9aa6d32, 0xf9e18bd6, 0xc0780954, 0x955d8f60, 0xa9cb014e, 0x64d583e2, 0x3e50533a, 0x00000001, 0x000001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf040, 0x48e2, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x24423eae, 0x40f7667e, 0x017f283e, 0x72887399, 0x063f4da0, 0x9b57a1c5, 0x5500c630, 0x6a304cac, 0xf9f10e9a, 0x02cdd193, 0x3f42bccd, 0x3c52ef2e, 0x15858a11, 0x25fd30bf, 0x00000001, 0xc00001f0 },
FinalRegs = new uint[] { 0x24423eae, 0x40f7667e, 0x017f283e, 0x72887399, 0x063f4da0, 0x9b57a1c5, 0x5500c630, 0x6a304cac, 0x75423eae, 0x02cdd193, 0x3f42bccd, 0x3c52ef2e, 0x15858a11, 0x25fd30bf, 0x00000001, 0xc00001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf455, 0x1de0, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xc8c22d0e, 0x98a19d05, 0x61b4ea5e, 0x52f6f9a0, 0x2f8ceae4, 0x15649771, 0x61953174, 0x45b9d93f, 0x4e0629af, 0x30f43259, 0x863e8e5c, 0x3310b69e, 0xae5e5b9d, 0xf00e065a, 0x00000001, 0xb00001f0 },
FinalRegs = new uint[] { 0xc8c22d0e, 0x98a19d05, 0x61b4ea5e, 0x52f6f9a0, 0x2f8ceae4, 0x15649771, 0x61953174, 0x45b9d93f, 0x4e0629af, 0x30f43259, 0x863e8e5c, 0x3310b69e, 0xae5e5b9d, 0x157c9771, 0x00000001, 0x100001f0 },
},
// MVN (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf46f, 0x1681, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xb1267a38, 0xe72b03aa, 0x50dc392a, 0xaff74b0d, 0xf83a17ba, 0xb8edf09d, 0x799df56d, 0x1ecbd371, 0xb4a74b9a, 0xe79f52fb, 0xbcec8b62, 0xbb0b01ea, 0x26d72e8c, 0x1d2ac349, 0x00000001, 0x900001f0 },
FinalRegs = new uint[] { 0xb1267a38, 0xe72b03aa, 0x50dc392a, 0xaff74b0d, 0xf83a17ba, 0xb8edf09d, 0xffefdfff, 0x1ecbd371, 0xb4a74b9a, 0xe79f52fb, 0xbcec8b62, 0xbb0b01ea, 0x26d72e8c, 0x1d2ac349, 0x00000001, 0x900001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf07f, 0x572f, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xa95387ad, 0x256c4ece, 0x32084d7a, 0x84935d58, 0x12f6880b, 0x3b386e47, 0xbeb69796, 0xdcf3fac5, 0xee2f9386, 0x25372541, 0x56499ba6, 0x06fa7586, 0xd114f908, 0x3442736e, 0x00000001, 0x400001f0 },
FinalRegs = new uint[] { 0xa95387ad, 0x256c4ece, 0x32084d7a, 0x84935d58, 0x12f6880b, 0x3b386e47, 0xbeb69796, 0xd43fffff, 0xee2f9386, 0x25372541, 0x56499ba6, 0x06fa7586, 0xd114f908, 0x3442736e, 0x00000001, 0x800001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf46f, 0x17e3, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xd7f2d1e1, 0x1d12b22c, 0x2c26620c, 0xeadb8ead, 0x73560a2e, 0xf521b384, 0x4094f3d2, 0x17ed0f6f, 0x79d30498, 0x6d47211a, 0x8fdfef1d, 0xce6cbfa7, 0x75dc1c1b, 0x2ffd5d28, 0x00000001, 0x700001f0 },
FinalRegs = new uint[] { 0xd7f2d1e1, 0x1d12b22c, 0x2c26620c, 0xeadb8ead, 0x73560a2e, 0xf521b384, 0x4094f3d2, 0xffe39fff, 0x79d30498, 0x6d47211a, 0x8fdfef1d, 0xce6cbfa7, 0x75dc1c1b, 0x2ffd5d28, 0x00000001, 0x700001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf07f, 0x1431, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x4154dce7, 0x66c452e9, 0xff9bea1b, 0x228a4a5e, 0xe9fee66b, 0xddd7117f, 0x303cdcb6, 0x4bdf78a2, 0xfbcca92c, 0x2f628d24, 0x51816529, 0xcdea5042, 0x77a1e4a2, 0x8a745cb4, 0x00000001, 0xa00001f0 },
FinalRegs = new uint[] { 0x4154dce7, 0x66c452e9, 0xff9bea1b, 0x228a4a5e, 0xffceffce, 0xddd7117f, 0x303cdcb6, 0x4bdf78a2, 0xfbcca92c, 0x2f628d24, 0x51816529, 0xcdea5042, 0x77a1e4a2, 0x8a745cb4, 0x00000001, 0xa00001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf07f, 0x73ac, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xd7b60274, 0x1ff3baba, 0xfdc8fa51, 0xcfacae9d, 0xd27a8214, 0xbbfb1abf, 0x3766111f, 0x89af2196, 0x4bd14cd6, 0x5af84659, 0xd279ed2f, 0x7abdf656, 0x868a6980, 0xd343d52a, 0x00000001, 0xd00001f0 },
FinalRegs = new uint[] { 0xd7b60274, 0x1ff3baba, 0xfdc8fa51, 0xfea7ffff, 0xd27a8214, 0xbbfb1abf, 0x3766111f, 0x89af2196, 0x4bd14cd6, 0x5af84659, 0xd279ed2f, 0x7abdf656, 0x868a6980, 0xd343d52a, 0x00000001, 0x900001f0 },
},
// ORN (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf464, 0x0976, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x02e1c999, 0x40c2ff04, 0x16f00059, 0xd360cd62, 0xcb34f9d2, 0x303b434a, 0x53e0151f, 0x188b36bc, 0x84868958, 0xebad0ada, 0xdcd0cb74, 0x64bc056c, 0xd17a7256, 0xb71ddae3, 0x00000001, 0x500001f0 },
FinalRegs = new uint[] { 0x02e1c999, 0x40c2ff04, 0x16f00059, 0xd360cd62, 0xcb34f9d2, 0x303b434a, 0x53e0151f, 0x188b36bc, 0x84868958, 0xff3dffff, 0xdcd0cb74, 0x64bc056c, 0xd17a7256, 0xb71ddae3, 0x00000001, 0x500001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf477, 0x3c66, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x71910713, 0xd17f8e75, 0x2652c7ac, 0xfad0527a, 0xc52b726d, 0x29e66793, 0xa1011225, 0x00c8ecc1, 0x48af4edd, 0x5c4e2e67, 0xc5393bd5, 0x702fcda1, 0x4549b1cf, 0x72d5a971, 0x00000001, 0xd00001f0 },
FinalRegs = new uint[] { 0x71910713, 0xd17f8e75, 0x2652c7ac, 0xfad0527a, 0xc52b726d, 0x29e66793, 0xa1011225, 0x00c8ecc1, 0x48af4edd, 0x5c4e2e67, 0xc5393bd5, 0x702fcda1, 0xfffcefff, 0x72d5a971, 0x00000001, 0x900001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf479, 0x1270, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x91060c85, 0x9b9c9033, 0x771ac325, 0x001e17c8, 0xb1adee43, 0xbaa9ec02, 0xf57f9f83, 0x3fed4e5c, 0x198cc3ea, 0x1a40edde, 0x6844391b, 0xa03319a0, 0xf741e11b, 0xc1892487, 0x00000001, 0x600001f0 },
FinalRegs = new uint[] { 0x91060c85, 0x9b9c9033, 0xffc3ffff, 0x001e17c8, 0xb1adee43, 0xbaa9ec02, 0xf57f9f83, 0x3fed4e5c, 0x198cc3ea, 0x1a40edde, 0x6844391b, 0xa03319a0, 0xf741e11b, 0xc1892487, 0x00000001, 0x800001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf46f, 0x19d4, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x4fd5b2bd, 0x1c8f29ae, 0x12803c79, 0x93683874, 0xccd779c1, 0x6978c335, 0x06eb789d, 0xc8b74ef8, 0x51ca145a, 0x242d8047, 0x5036f51f, 0x13a4a4a2, 0x08818ae4, 0xe1687e67, 0x00000001, 0x000001f0 },
FinalRegs = new uint[] { 0x4fd5b2bd, 0x1c8f29ae, 0x12803c79, 0x93683874, 0xccd779c1, 0x6978c335, 0x06eb789d, 0xc8b74ef8, 0x51ca145a, 0xffe57fff, 0x5036f51f, 0x13a4a4a2, 0x08818ae4, 0xe1687e67, 0x00000001, 0x000001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf07f, 0x614f, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x83c9ef5a, 0xb5933c7e, 0x2dc23d71, 0x5723ae27, 0x1218bc2c, 0x456f3dbd, 0xf6ee7d22, 0xde4df878, 0x3e800973, 0x39c4c131, 0x0676384d, 0xef62a558, 0x2acc92f2, 0x9cd71aa1, 0x00000001, 0xb00001f0 },
FinalRegs = new uint[] { 0x83c9ef5a, 0xf30fffff, 0x2dc23d71, 0x5723ae27, 0x1218bc2c, 0x456f3dbd, 0xf6ee7d22, 0xde4df878, 0x3e800973, 0x39c4c131, 0x0676384d, 0xef62a558, 0x2acc92f2, 0x9cd71aa1, 0x00000001, 0x900001f0 },
},
// TEQ (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf49b, 0x2fe4, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xc87047c3, 0x99001273, 0xa963adc7, 0xaba3d1a1, 0x4b9c13a0, 0xc42566ba, 0xee0b7ab1, 0x3e4423ec, 0x5d874e97, 0xfffb5799, 0xdb88f462, 0xbdc4a9e2, 0x3933e52b, 0xe1839111, 0x00000001, 0xc00001f0 },
FinalRegs = new uint[] { 0xc87047c3, 0x99001273, 0xa963adc7, 0xaba3d1a1, 0x4b9c13a0, 0xc42566ba, 0xee0b7ab1, 0x3e4423ec, 0x5d874e97, 0xfffb5799, 0xdb88f462, 0xbdc4a9e2, 0x3933e52b, 0xe1839111, 0x00000001, 0x800001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf09b, 0x0f59, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x6d2c2ac7, 0xdd2b59f4, 0x3fc013f4, 0x567e744e, 0xc4feb096, 0x188454f3, 0xae13338b, 0x66a0a40b, 0xac995945, 0x7e27f097, 0x547cbd54, 0xd2abf0ab, 0x02c08b3e, 0xe6d1283f, 0x00000001, 0x500001f0 },
FinalRegs = new uint[] { 0x6d2c2ac7, 0xdd2b59f4, 0x3fc013f4, 0x567e744e, 0xc4feb096, 0x188454f3, 0xae13338b, 0x66a0a40b, 0xac995945, 0x7e27f097, 0x547cbd54, 0xd2abf0ab, 0x02c08b3e, 0xe6d1283f, 0x00000001, 0x900001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf494, 0x6f3d, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x16342d21, 0xff794fb0, 0x513ba230, 0x7b9e4b2b, 0x9a2d1ba9, 0xebce0dae, 0xe792f2b8, 0xf4932236, 0x0bcd9542, 0x12bcab94, 0x0110b845, 0xdde237b0, 0xa401d5b9, 0xc3162f6d, 0x00000001, 0xc00001f0 },
FinalRegs = new uint[] { 0x16342d21, 0xff794fb0, 0x513ba230, 0x7b9e4b2b, 0x9a2d1ba9, 0xebce0dae, 0xe792f2b8, 0xf4932236, 0x0bcd9542, 0x12bcab94, 0x0110b845, 0xdde237b0, 0xa401d5b9, 0xc3162f6d, 0x00000001, 0x800001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf09c, 0x6f59, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x8d9e2002, 0xfa519294, 0x700740d6, 0x29220c73, 0x8f0ad8b2, 0x6ce9d5e8, 0x12f9da7a, 0x286a9813, 0x2be49d73, 0x16241aa1, 0xe096f43b, 0x1fd0d3e2, 0x31791bb5, 0xa4943f4e, 0x00000001, 0xe00001f0 },
FinalRegs = new uint[] { 0x8d9e2002, 0xfa519294, 0x700740d6, 0x29220c73, 0x8f0ad8b2, 0x6ce9d5e8, 0x12f9da7a, 0x286a9813, 0x2be49d73, 0x16241aa1, 0xe096f43b, 0x1fd0d3e2, 0x31791bb5, 0xa4943f4e, 0x00000001, 0x000001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf094, 0x6f35, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x222e0e7c, 0xa89d1fdf, 0xa7d67bc3, 0x658e1ee9, 0x10b41780, 0x5cd566a4, 0xce03a58a, 0x63fb9a9e, 0x4f5cb2bd, 0x14e72619, 0x296a9bd5, 0xbf7b1fb1, 0x705a45cc, 0xba8540ae, 0x00000001, 0x000001f0 },
FinalRegs = new uint[] { 0x222e0e7c, 0xa89d1fdf, 0xa7d67bc3, 0x658e1ee9, 0x10b41780, 0x5cd566a4, 0xce03a58a, 0x63fb9a9e, 0x4f5cb2bd, 0x14e72619, 0x296a9bd5, 0xbf7b1fb1, 0x705a45cc, 0xba8540ae, 0x00000001, 0x000001f0 },
},
// EOR (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf496, 0x54fb, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x6267728b, 0xc834f7c7, 0xa136a1d6, 0xfd9533e9, 0x096db729, 0x8fff8a73, 0x6a45348e, 0xd52111ed, 0xa5640aff, 0xa4cf82a6, 0x5ab70b5c, 0x5b3c4563, 0xf1a91ab7, 0x5718fdd1, 0x00000001, 0x500001f0 },
FinalRegs = new uint[] { 0x6267728b, 0xc834f7c7, 0xa136a1d6, 0xfd9533e9, 0x6a452bee, 0x8fff8a73, 0x6a45348e, 0xd52111ed, 0xa5640aff, 0xa4cf82a6, 0x5ab70b5c, 0x5b3c4563, 0xf1a91ab7, 0x5718fdd1, 0x00000001, 0x100001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf08a, 0x339d, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xbf1e6da6, 0x2c10408a, 0xe961ddde, 0x5add8306, 0xc266064d, 0xa79569e1, 0x945c28ed, 0xb996f578, 0x68082b6e, 0x14cdd2c7, 0x7d0cc6a2, 0x8d6edfbf, 0x9151e24c, 0x63eaee32, 0x00000001, 0x300001f0 },
FinalRegs = new uint[] { 0xbf1e6da6, 0x2c10408a, 0xe961ddde, 0xe0915b3f, 0xc266064d, 0xa79569e1, 0x945c28ed, 0xb996f578, 0x68082b6e, 0x14cdd2c7, 0x7d0cc6a2, 0x8d6edfbf, 0x9151e24c, 0x63eaee32, 0x00000001, 0x300001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf490, 0x27d8, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xd6826a86, 0x39aa35f5, 0x2a8a913e, 0xd9dbf560, 0xcb1a9957, 0xe6779d2f, 0x0eeab3f9, 0xa463d4c2, 0xb3187660, 0xa51778c3, 0x73817179, 0x6d6dae92, 0x864a3e80, 0x43d8f181, 0x00000001, 0xe00001f0 },
FinalRegs = new uint[] { 0xd6826a86, 0x39aa35f5, 0x2a8a913e, 0xd9dbf560, 0xcb1a9957, 0xe6779d2f, 0x0eeab3f9, 0xd684aa86, 0xb3187660, 0xa51778c3, 0x73817179, 0x6d6dae92, 0x864a3e80, 0x43d8f181, 0x00000001, 0x800001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf485, 0x3d32, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x063885c0, 0xa183a44d, 0x5cb2f961, 0xe44b8670, 0x8ec25495, 0xb8f5a831, 0x1c2fecb4, 0xfc15fcff, 0x28dd902e, 0xf0c875f4, 0x0af03bb5, 0xefe4ba8b, 0x10e57000, 0x4cd51767, 0x00000001, 0xb00001f0 },
FinalRegs = new uint[] { 0x063885c0, 0xa183a44d, 0x5cb2f961, 0xe44b8670, 0x8ec25495, 0xb8f5a831, 0x1c2fecb4, 0xfc15fcff, 0x28dd902e, 0xf0c875f4, 0x0af03bb5, 0xefe4ba8b, 0x10e57000, 0xb8f76031, 0x00000001, 0xb00001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf095, 0x58e8, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x5a60610b, 0x4d178413, 0x3b12edd0, 0x23afc7fc, 0x47f0647d, 0x327bd294, 0x52351d80, 0x36733323, 0x490a0d2a, 0x75d5888c, 0x9b45f4e6, 0x89ebf7dc, 0xd278dd78, 0x1b9b0bbd, 0x00000001, 0x400001f0 },
FinalRegs = new uint[] { 0x5a60610b, 0x4d178413, 0x3b12edd0, 0x23afc7fc, 0x47f0647d, 0x327bd294, 0x52351d80, 0x36733323, 0x2f7bd294, 0x75d5888c, 0x9b45f4e6, 0x89ebf7dc, 0xd278dd78, 0x1b9b0bbd, 0x00000001, 0x000001f0 },
},
// CMN (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf514, 0x6f12, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xec864396, 0xe2f483b8, 0x18df08c9, 0xae7780ba, 0xd16bc913, 0x892037de, 0x84a3589e, 0x3a468960, 0x004f92e4, 0x6fd793c2, 0x81b048c6, 0xe044e7cf, 0x2199ccda, 0x4667415d, 0x00000001, 0x000001f0 },
FinalRegs = new uint[] { 0xec864396, 0xe2f483b8, 0x18df08c9, 0xae7780ba, 0xd16bc913, 0x892037de, 0x84a3589e, 0x3a468960, 0x004f92e4, 0x6fd793c2, 0x81b048c6, 0xe044e7cf, 0x2199ccda, 0x4667415d, 0x00000001, 0x800001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf517, 0x2f38, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x154548b0, 0x28aed64c, 0x533306b3, 0x8eace432, 0x9a6523f1, 0x22b08ccb, 0xe7fceaf6, 0x45429c2c, 0xf58378c1, 0x0ef49416, 0x88dbd472, 0xf6a35b6c, 0x46b19364, 0x52e4982d, 0x00000001, 0x900001f0 },
FinalRegs = new uint[] { 0x154548b0, 0x28aed64c, 0x533306b3, 0x8eace432, 0x9a6523f1, 0x22b08ccb, 0xe7fceaf6, 0x45429c2c, 0xf58378c1, 0x0ef49416, 0x88dbd472, 0xf6a35b6c, 0x46b19364, 0x52e4982d, 0x00000001, 0x000001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf116, 0x7fe2, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x30b90186, 0xec7b038f, 0xcb392feb, 0x10c09c2f, 0x8619521d, 0xcf8d7075, 0x108f8f49, 0x6e44275d, 0x1728faed, 0xf2a0b2a4, 0x783cf97f, 0x201d6d0b, 0x317f276d, 0x5a7186e2, 0x00000001, 0x200001f0 },
FinalRegs = new uint[] { 0x30b90186, 0xec7b038f, 0xcb392feb, 0x10c09c2f, 0x8619521d, 0xcf8d7075, 0x108f8f49, 0x6e44275d, 0x1728faed, 0xf2a0b2a4, 0x783cf97f, 0x201d6d0b, 0x317f276d, 0x5a7186e2, 0x00000001, 0x000001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf51b, 0x7f4a, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xedd3c03d, 0xd7cce5a2, 0xfc40b40a, 0x6a9c96f3, 0x40ca8c2d, 0xaa2973e1, 0xd7953408, 0xfa11d2df, 0x7cec28c2, 0x4e523380, 0x007a4ac6, 0x03890c29, 0xd1495b3e, 0xdf1af969, 0x00000001, 0x500001f0 },
FinalRegs = new uint[] { 0xedd3c03d, 0xd7cce5a2, 0xfc40b40a, 0x6a9c96f3, 0x40ca8c2d, 0xaa2973e1, 0xd7953408, 0xfa11d2df, 0x7cec28c2, 0x4e523380, 0x007a4ac6, 0x03890c29, 0xd1495b3e, 0xdf1af969, 0x00000001, 0x000001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf11c, 0x5f9c, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xd8c0c360, 0xd50bcc87, 0xe265e8b2, 0xca49cc71, 0xa6bb11c8, 0x13649388, 0x034a4c8c, 0xa3b4c570, 0x014d32ac, 0x1847d102, 0x7fc3678d, 0xb0e0f469, 0x9508a619, 0x2a2372e0, 0x00000001, 0xa00001f0 },
FinalRegs = new uint[] { 0xd8c0c360, 0xd50bcc87, 0xe265e8b2, 0xca49cc71, 0xa6bb11c8, 0x13649388, 0x034a4c8c, 0xa3b4c570, 0x014d32ac, 0x1847d102, 0x7fc3678d, 0xb0e0f469, 0x9508a619, 0x2a2372e0, 0x00000001, 0x800001f0 },
},
// ADD (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf10b, 0x00e0, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xadc2fe68, 0xa8a14518, 0x5baf5e87, 0x17e2b502, 0x638227c2, 0xba11428f, 0x98c5b963, 0x5b9cbcd3, 0xb4c11f97, 0x0ca6832e, 0xea26efa6, 0x7bb19ec8, 0x8ea04a89, 0x62d597c2, 0x00000001, 0x300001f0 },
FinalRegs = new uint[] { 0x7bb19fa8, 0xa8a14518, 0x5baf5e87, 0x17e2b502, 0x638227c2, 0xba11428f, 0x98c5b963, 0x5b9cbcd3, 0xb4c11f97, 0x0ca6832e, 0xea26efa6, 0x7bb19ec8, 0x8ea04a89, 0x62d597c2, 0x00000001, 0x300001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf114, 0x7b41, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x9366f694, 0x02670e58, 0x6f3e74b8, 0x567d3e30, 0xeebb29c4, 0xc25ce8e6, 0x942b94c8, 0xc7dccdd9, 0xccfe17a9, 0xeacc4db1, 0xbbbc0fde, 0x248b7093, 0x7f66c92d, 0xfc063cb6, 0x00000001, 0xe00001f0 },
FinalRegs = new uint[] { 0x9366f694, 0x02670e58, 0x6f3e74b8, 0x567d3e30, 0xeebb29c4, 0xc25ce8e6, 0x942b94c8, 0xc7dccdd9, 0xccfe17a9, 0xeacc4db1, 0xbbbc0fde, 0xf1bf29c4, 0x7f66c92d, 0xfc063cb6, 0x00000001, 0x800001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf51c, 0x21d1, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x2b53ae1e, 0x733046c3, 0xbcc33a3a, 0x2f7bbd50, 0xed2a39f2, 0xfee631ec, 0xeb6d3bc3, 0x9f9b502d, 0x30d20f7b, 0xdc75211b, 0xdb234e2b, 0x85008c86, 0x43beb508, 0x6a8303d5, 0x00000001, 0xd00001f0 },
FinalRegs = new uint[] { 0x2b53ae1e, 0x43c53d08, 0xbcc33a3a, 0x2f7bbd50, 0xed2a39f2, 0xfee631ec, 0xeb6d3bc3, 0x9f9b502d, 0x30d20f7b, 0xdc75211b, 0xdb234e2b, 0x85008c86, 0x43beb508, 0x6a8303d5, 0x00000001, 0x000001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf513, 0x22e8, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xbb3b52c1, 0x40ff59f3, 0x05ca09c5, 0x440114be, 0xec3a4022, 0x0ff93d8c, 0x38868879, 0x824d36d8, 0xf513a9d8, 0xf1d0ad5a, 0xc453fdd8, 0xe3dc8d52, 0x1fc5a9ef, 0x809dbe9b, 0x00000001, 0xc00001f0 },
FinalRegs = new uint[] { 0xbb3b52c1, 0x40ff59f3, 0x440854be, 0x440114be, 0xec3a4022, 0x0ff93d8c, 0x38868879, 0x824d36d8, 0xf513a9d8, 0xf1d0ad5a, 0xc453fdd8, 0xe3dc8d52, 0x1fc5a9ef, 0x809dbe9b, 0x00000001, 0x000001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf518, 0x68c7, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xf9c00a78, 0xf47ee408, 0xdc31e40b, 0x167902da, 0x03b23f2f, 0x6d41efdc, 0x9cb99b17, 0x21bfbf63, 0x9fbe8105, 0x250087d0, 0xe0588965, 0x0f0f669c, 0x2ed04b37, 0xc65c6e2e, 0x00000001, 0x100001f0 },
FinalRegs = new uint[] { 0xf9c00a78, 0xf47ee408, 0xdc31e40b, 0x167902da, 0x03b23f2f, 0x6d41efdc, 0x9cb99b17, 0x21bfbf63, 0x9fbe873d, 0x250087d0, 0xe0588965, 0x0f0f669c, 0x2ed04b37, 0xc65c6e2e, 0x00000001, 0x800001f0 },
},
// ADC (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf54d, 0x379a, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x09eb57e5, 0xc9981095, 0x94b0bf26, 0x27080c39, 0x9fba115a, 0xde0e1533, 0xaa5916aa, 0x1bfc2313, 0x32a96f13, 0x5b8f2d6c, 0x9098dcf2, 0x86143a3f, 0x5c004908, 0xd233cd08, 0x00000001, 0x300001f0 },
FinalRegs = new uint[] { 0x09eb57e5, 0xc9981095, 0x94b0bf26, 0x27080c39, 0x9fba115a, 0xde0e1533, 0xaa5916aa, 0xd2350109, 0x32a96f13, 0x5b8f2d6c, 0x9098dcf2, 0x86143a3f, 0x5c004908, 0xd233cd08, 0x00000001, 0x300001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf149, 0x3a77, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xe32aaf45, 0x05fe0eac, 0x9c782c15, 0x9301164b, 0xa2f59aea, 0xe6b2618b, 0xfceb237a, 0xcfeb98bd, 0xaaa75e8d, 0xbb57f750, 0xd282f40d, 0xa181d4d7, 0x93313b48, 0x9a64c67f, 0x00000001, 0xf00001f0 },
FinalRegs = new uint[] { 0xe32aaf45, 0x05fe0eac, 0x9c782c15, 0x9301164b, 0xa2f59aea, 0xe6b2618b, 0xfceb237a, 0xcfeb98bd, 0xaaa75e8d, 0xbb57f750, 0x32cf6ec8, 0xa181d4d7, 0x93313b48, 0x9a64c67f, 0x00000001, 0xf00001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf549, 0x57c8, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x67da941e, 0x5d744410, 0x1f93bf8f, 0xb52727e0, 0x77ce10fe, 0xe7a40291, 0x40ac5a1f, 0x127e801f, 0x68233546, 0xdbe8086f, 0x82b65e68, 0xcf35c09b, 0x8846e02d, 0x5fd54256, 0x00000001, 0x200001f0 },
FinalRegs = new uint[] { 0x67da941e, 0x5d744410, 0x1f93bf8f, 0xb52727e0, 0x77ce10fe, 0xe7a40291, 0x40ac5a1f, 0xdbe82170, 0x68233546, 0xdbe8086f, 0x82b65e68, 0xcf35c09b, 0x8846e02d, 0x5fd54256, 0x00000001, 0x200001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf15c, 0x1649, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x86cf07b1, 0x1c86e00f, 0x8dc39789, 0xe8fafb40, 0xb837bf22, 0xe9c2c765, 0xb9e8b84b, 0xdbc9663e, 0x979b81da, 0xfb7a5636, 0x9012981d, 0xf52ec47c, 0xf98f6294, 0xaf70ff24, 0x00000001, 0xe00001f0 },
FinalRegs = new uint[] { 0x86cf07b1, 0x1c86e00f, 0x8dc39789, 0xe8fafb40, 0xb837bf22, 0xe9c2c765, 0xf9d862de, 0xdbc9663e, 0x979b81da, 0xfb7a5636, 0x9012981d, 0xf52ec47c, 0xf98f6294, 0xaf70ff24, 0x00000001, 0x800001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf144, 0x6ab6, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x151549e7, 0xbdfa6ced, 0x47ba5025, 0xaba24048, 0x17c38ef8, 0xf92095ec, 0xdccd5b6f, 0xcb3878a5, 0x30d25594, 0x94886d84, 0xaec74633, 0xbe39725f, 0x439d8ef1, 0xcd66a204, 0x00000001, 0x000001f0 },
FinalRegs = new uint[] { 0x151549e7, 0xbdfa6ced, 0x47ba5025, 0xaba24048, 0x17c38ef8, 0xf92095ec, 0xdccd5b6f, 0xcb3878a5, 0x30d25594, 0x94886d84, 0x1d738ef8, 0xbe39725f, 0x439d8ef1, 0xcd66a204, 0x00000001, 0x000001f0 },
},
// SBC (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf565, 0x3beb, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x23efd21b, 0x78e2f658, 0x37a4e044, 0x8feab92a, 0x9795995f, 0x66c7ddab, 0x1c29040f, 0x10034172, 0x2eede540, 0x961c1400, 0x34cf45b9, 0xdb736f38, 0xd601c8ed, 0x99a714af, 0x00000001, 0xf00001f0 },
FinalRegs = new uint[] { 0x23efd21b, 0x78e2f658, 0x37a4e044, 0x8feab92a, 0x9795995f, 0x66c7ddab, 0x1c29040f, 0x10034172, 0x2eede540, 0x961c1400, 0x34cf45b9, 0x66c607ab, 0xd601c8ed, 0x99a714af, 0x00000001, 0xf00001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf172, 0x1b0d, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x596b63ec, 0xb659c798, 0x300ca58e, 0x52200fa5, 0x0db74ebe, 0x01e5b394, 0xed83d480, 0x1a524b19, 0x593d9bd1, 0x1152a751, 0xf3e1cb1c, 0xfb9392e3, 0x08fc2cd9, 0xc3910cf3, 0x00000001, 0x000001f0 },
FinalRegs = new uint[] { 0x596b63ec, 0xb659c798, 0x300ca58e, 0x52200fa5, 0x0db74ebe, 0x01e5b394, 0xed83d480, 0x1a524b19, 0x593d9bd1, 0x1152a751, 0xf3e1cb1c, 0x2fffa580, 0x08fc2cd9, 0xc3910cf3, 0x00000001, 0x200001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf57c, 0x14da, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x5eab5df9, 0x3cfdd390, 0xcfd20097, 0xc8986688, 0xa714c17c, 0xc9eee620, 0x6626498e, 0x2de48d3c, 0xc27c794f, 0xf7d0c67f, 0x75b6b9d9, 0xbaf9f630, 0x7bd89fad, 0xe5a2e298, 0x00000001, 0xe00001f0 },
FinalRegs = new uint[] { 0x5eab5df9, 0x3cfdd390, 0xcfd20097, 0xc8986688, 0x7bbd5fad, 0xc9eee620, 0x6626498e, 0x2de48d3c, 0xc27c794f, 0xf7d0c67f, 0x75b6b9d9, 0xbaf9f630, 0x7bd89fad, 0xe5a2e298, 0x00000001, 0x200001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf57a, 0x6bbf, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xaee56760, 0xa9f9b7d4, 0x9dd85a8c, 0x4c8cea6b, 0x7807b53d, 0xd1349b90, 0xcf320f62, 0x7af6d0c9, 0xc61fac5f, 0x23b43bbd, 0xef7466b3, 0x98e322a8, 0x1e10ae81, 0xb6987dcc, 0x00000001, 0xa00001f0 },
FinalRegs = new uint[] { 0xaee56760, 0xa9f9b7d4, 0x9dd85a8c, 0x4c8cea6b, 0x7807b53d, 0xd1349b90, 0xcf320f62, 0x7af6d0c9, 0xc61fac5f, 0x23b43bbd, 0xef7466b3, 0xef7460bb, 0x1e10ae81, 0xb6987dcc, 0x00000001, 0xa00001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf171, 0x47e8, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x4164d035, 0x72eecb21, 0xbb63329c, 0x8883a249, 0x230b524b, 0x40c059ae, 0x529e2950, 0xd0f7b958, 0xae900a4a, 0xa5a3f2b5, 0xe68da7f3, 0x68fececb, 0x91a2f476, 0x3986b8a0, 0x00000001, 0x400001f0 },
FinalRegs = new uint[] { 0x4164d035, 0x72eecb21, 0xbb63329c, 0x8883a249, 0x230b524b, 0x40c059ae, 0x529e2950, 0xfeeecb20, 0xae900a4a, 0xa5a3f2b5, 0xe68da7f3, 0x68fececb, 0x91a2f476, 0x3986b8a0, 0x00000001, 0x800001f0 },
},
// CMP (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf5ba, 0x7f0c, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x32876eff, 0x3127746f, 0x25274f4b, 0x50ba4fa5, 0xa3013fb5, 0x4985e2cb, 0x43dad09c, 0xfb6e47f2, 0x673ee708, 0x3beee172, 0x4866bb83, 0x9368060a, 0x565ecf8e, 0xecc22394, 0x00000001, 0xc00001f0 },
FinalRegs = new uint[] { 0x32876eff, 0x3127746f, 0x25274f4b, 0x50ba4fa5, 0xa3013fb5, 0x4985e2cb, 0x43dad09c, 0xfb6e47f2, 0x673ee708, 0x3beee172, 0x4866bb83, 0x9368060a, 0x565ecf8e, 0xecc22394, 0x00000001, 0x200001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf1b4, 0x5f0c, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xabb3ffca, 0x7dbdda85, 0xe413a0d4, 0xf2ea8958, 0x81be2593, 0x8b0997e0, 0x5319660b, 0xd4edc3d0, 0x4b147c71, 0xa60a6a5f, 0x9984a94a, 0xbabe5540, 0x24df8017, 0x1e97e9f5, 0x00000001, 0xd00001f0 },
FinalRegs = new uint[] { 0xabb3ffca, 0x7dbdda85, 0xe413a0d4, 0xf2ea8958, 0x81be2593, 0x8b0997e0, 0x5319660b, 0xd4edc3d0, 0x4b147c71, 0xa60a6a5f, 0x9984a94a, 0xbabe5540, 0x24df8017, 0x1e97e9f5, 0x00000001, 0x300001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf5b1, 0x0f4b, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xf6edbf76, 0xd3f53e21, 0x37679835, 0x6af58147, 0x143dd6be, 0x4f6339d1, 0x0261fa88, 0x38fe033f, 0x1b503fb3, 0x802af22b, 0x22901e74, 0xae61d40e, 0xe1e850ee, 0xe353701c, 0x00000001, 0x200001f0 },
FinalRegs = new uint[] { 0xf6edbf76, 0xd3f53e21, 0x37679835, 0x6af58147, 0x143dd6be, 0x4f6339d1, 0x0261fa88, 0x38fe033f, 0x1b503fb3, 0x802af22b, 0x22901e74, 0xae61d40e, 0xe1e850ee, 0xe353701c, 0x00000001, 0xa00001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf5b2, 0x7f57, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x350b2e14, 0xcc603c9e, 0xa7a56491, 0x1f4fe90b, 0x6bb14aba, 0x325154ef, 0xc7655249, 0xe1a6077b, 0x145fc2f0, 0x21e0bc5e, 0x18275d8b, 0x0d8f37f0, 0xfdb56518, 0x405f5649, 0x00000001, 0x200001f0 },
FinalRegs = new uint[] { 0x350b2e14, 0xcc603c9e, 0xa7a56491, 0x1f4fe90b, 0x6bb14aba, 0x325154ef, 0xc7655249, 0xe1a6077b, 0x145fc2f0, 0x21e0bc5e, 0x18275d8b, 0x0d8f37f0, 0xfdb56518, 0x405f5649, 0x00000001, 0xa00001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf1b7, 0x0fd0, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x5a7f551b, 0x624d7cb7, 0xdc3e4dab, 0xd242610e, 0x8b7213db, 0x3c4f81df, 0x353e713e, 0x0ffdfd5c, 0xe56efdf9, 0x59330bc2, 0x1b91689c, 0x5497152e, 0x7ce02ab7, 0x0127aeca, 0x00000001, 0xd00001f0 },
FinalRegs = new uint[] { 0x5a7f551b, 0x624d7cb7, 0xdc3e4dab, 0xd242610e, 0x8b7213db, 0x3c4f81df, 0x353e713e, 0x0ffdfd5c, 0xe56efdf9, 0x59330bc2, 0x1b91689c, 0x5497152e, 0x7ce02ab7, 0x0127aeca, 0x00000001, 0x200001f0 },
},
// SUB (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf5a6, 0x2902, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x688a6dd6, 0xcabb9832, 0xa187c464, 0xe4474634, 0x19316c88, 0x8b99d147, 0xd67bc441, 0x48cfa0cf, 0x4cd8b792, 0x9593d34d, 0x66b5a570, 0x9065cc35, 0x6ddf1e6f, 0xd49a2985, 0x00000001, 0xf00001f0 },
FinalRegs = new uint[] { 0x688a6dd6, 0xcabb9832, 0xa187c464, 0xe4474634, 0x19316c88, 0x8b99d147, 0xd67bc441, 0x48cfa0cf, 0x4cd8b792, 0xd673a441, 0x66b5a570, 0x9065cc35, 0x6ddf1e6f, 0xd49a2985, 0x00000001, 0xf00001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf1a5, 0x4730, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x69e8d900, 0x3ca9d66e, 0x91788f4e, 0x6e821399, 0xd710747f, 0xc8e72a37, 0xf9f9702f, 0x8e689c3f, 0x87ef1e3c, 0xc8270c3e, 0xd76f0d87, 0x5482900c, 0xec43f474, 0x72617560, 0x00000001, 0x000001f0 },
FinalRegs = new uint[] { 0x69e8d900, 0x3ca9d66e, 0x91788f4e, 0x6e821399, 0xd710747f, 0xc8e72a37, 0xf9f9702f, 0x18e72a37, 0x87ef1e3c, 0xc8270c3e, 0xd76f0d87, 0x5482900c, 0xec43f474, 0x72617560, 0x00000001, 0x000001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf5bd, 0x7d6b, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x56f27741, 0xdf3a0328, 0x49864f87, 0xd8b84caa, 0xd7a4cc2b, 0x85467faf, 0x6e972a47, 0xc2440b53, 0xa56fc6fa, 0xe86c3322, 0x19e1532d, 0x2984be63, 0xd7302738, 0xbf00369c, 0x00000001, 0xb00001f0 },
FinalRegs = new uint[] { 0x56f27741, 0xdf3a0328, 0x49864f87, 0xd8b84caa, 0xd7a4cc2b, 0x85467faf, 0x6e972a47, 0xc2440b53, 0xa56fc6fa, 0xe86c3322, 0x19e1532d, 0x2984be63, 0xd7302738, 0xbf0032f0, 0x00000001, 0xa00001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf5aa, 0x048c, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xc48ce68c, 0x33c654cc, 0xa31ea382, 0x398c4095, 0xfff680a5, 0x5886b5f4, 0xb1debf0b, 0x8bd529bb, 0x1354ba05, 0xcf80960a, 0x18582cbe, 0x37ca8996, 0x08f95e3c, 0xc87fdb04, 0x00000001, 0x200001f0 },
FinalRegs = new uint[] { 0xc48ce68c, 0x33c654cc, 0xa31ea382, 0x398c4095, 0x18122cbe, 0x5886b5f4, 0xb1debf0b, 0x8bd529bb, 0x1354ba05, 0xcf80960a, 0x18582cbe, 0x37ca8996, 0x08f95e3c, 0xc87fdb04, 0x00000001, 0x200001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf5ba, 0x13aa, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xd2de6567, 0x993624bf, 0xcfbd492f, 0x7b922424, 0x9fa01912, 0x04225225, 0x3a812a6d, 0xe62792b8, 0xb47cee9a, 0x5694288e, 0x6c669666, 0x213701a6, 0xe423ad2d, 0xc7d5362b, 0x00000001, 0xb00001f0 },
FinalRegs = new uint[] { 0xd2de6567, 0x993624bf, 0xcfbd492f, 0x6c515666, 0x9fa01912, 0x04225225, 0x3a812a6d, 0xe62792b8, 0xb47cee9a, 0x5694288e, 0x6c669666, 0x213701a6, 0xe423ad2d, 0xc7d5362b, 0x00000001, 0x200001f0 },
},
// RSB (imm)
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf5dc, 0x767d, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x8496100e, 0x93007a60, 0x0d33d3dc, 0xd932c4e1, 0x6e05ad8d, 0xde3cc68e, 0x74400ff8, 0xce309ee7, 0x188e0ebd, 0xe10837ab, 0x6b2534e2, 0x280add20, 0x3adc0489, 0x8ef32355, 0x00000001, 0x600001f0 },
FinalRegs = new uint[] { 0x8496100e, 0x93007a60, 0x0d33d3dc, 0xd932c4e1, 0x6e05ad8d, 0xde3cc68e, 0xc523ff6b, 0xce309ee7, 0x188e0ebd, 0xe10837ab, 0x6b2534e2, 0x280add20, 0x3adc0489, 0x8ef32355, 0x00000001, 0x800001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf1dc, 0x377d, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xc5d7fe20, 0xade81daf, 0xba65ccf8, 0xa101ee00, 0x3a2b70d9, 0xc90238d9, 0xc3b54049, 0x436bf83f, 0x99c96b58, 0xd134cb19, 0x4de47e7f, 0x6a175e2d, 0xd9e49229, 0x174d24ac, 0x00000001, 0x400001f0 },
FinalRegs = new uint[] { 0xc5d7fe20, 0xade81daf, 0xba65ccf8, 0xa101ee00, 0x3a2b70d9, 0xc90238d9, 0xc3b54049, 0xa398eb54, 0x99c96b58, 0xd134cb19, 0x4de47e7f, 0x6a175e2d, 0xd9e49229, 0x174d24ac, 0x00000001, 0x900001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf5c5, 0x34bd, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0xcea4f214, 0xdc15a8f8, 0xd22be9ef, 0x42c400c5, 0x2fd1fc9b, 0xca724b52, 0x5582071d, 0xd01b7816, 0xa4f5a435, 0xcfd50db5, 0x24e0c80b, 0x7b52178d, 0x11cd0449, 0xd6daa84a, 0x00000001, 0x800001f0 },
FinalRegs = new uint[] { 0xcea4f214, 0xdc15a8f8, 0xd22be9ef, 0x42c400c5, 0x358f2eae, 0xca724b52, 0x5582071d, 0xd01b7816, 0xa4f5a435, 0xcfd50db5, 0x24e0c80b, 0x7b52178d, 0x11cd0449, 0xd6daa84a, 0x00000001, 0x800001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf1ce, 0x7846, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x3c676ff3, 0x511ea0cb, 0x15e79c80, 0x51a3a8c1, 0x535cc233, 0x6ae729a3, 0x4e5726da, 0x81260fb9, 0x24dd423a, 0x9e81d6c0, 0x812b3bd1, 0x55bd0f44, 0x1871ec65, 0x87087126, 0x00000001, 0x200001f0 },
FinalRegs = new uint[] { 0x3c676ff3, 0x511ea0cb, 0x15e79c80, 0x51a3a8c1, 0x535cc233, 0x6ae729a3, 0x4e5726da, 0x81260fb9, 0x0317ffff, 0x9e81d6c0, 0x812b3bd1, 0x55bd0f44, 0x1871ec65, 0x87087126, 0x00000001, 0x200001f0 },
},
new PrecomputedThumbTestCase()
{
Instructions = new ushort[] { 0xf5c5, 0x2418, 0x4770, 0xe7fe },
StartRegs = new uint[] { 0x2bb00694, 0x1c56a4c0, 0xc5cc4a3e, 0xc627c1ab, 0x4e4a8dfc, 0x1f3d71a4, 0x897d57b8, 0x0d4a7208, 0x433b7b88, 0xaaf24fd6, 0x2438f5f8, 0x9875e64a, 0xda475f22, 0x66d5e2e7, 0x00000001, 0x700001f0 },
FinalRegs = new uint[] { 0x2bb00694, 0x1c56a4c0, 0xc5cc4a3e, 0xc627c1ab, 0xe0cc0e5c, 0x1f3d71a4, 0x897d57b8, 0x0d4a7208, 0x433b7b88, 0xaaf24fd6, 0x2438f5f8, 0x9875e64a, 0xda475f22, 0x66d5e2e7, 0x00000001, 0x700001f0 },
},
};
}
}

View File

@ -14,7 +14,7 @@ namespace Ryujinx.Configuration
/// <summary>
/// The current version of the file format
/// </summary>
public const int CurrentVersion = 36;
public const int CurrentVersion = 37;
/// <summary>
/// Version of the configuration file format
@ -236,6 +236,11 @@ namespace Ryujinx.Configuration
/// </summary>
public bool StartFullscreen { get; set; }
/// <summary>
/// Show console window
/// </summary>
public bool ShowConsole { get; set; }
/// <summary>
/// Enable or disable keyboard support (Independent from controllers binding)
/// </summary>

View File

@ -6,6 +6,7 @@ using Ryujinx.Common.Configuration.Hid.Keyboard;
using Ryujinx.Common.Logging;
using Ryujinx.Configuration.System;
using Ryujinx.Configuration.Ui;
using Ryujinx.Ui.Helper;
using System;
using System.Collections.Generic;
@ -88,6 +89,11 @@ namespace Ryujinx.Configuration
/// </summary>
public ReactiveObject<bool> StartFullscreen { get; private set; }
/// <summary>
/// Hide / Show Console Window
/// </summary>
public ReactiveObject<bool> ShowConsole { get; private set; }
public UiSection()
{
GuiColumns = new Columns();
@ -96,6 +102,8 @@ namespace Ryujinx.Configuration
EnableCustomTheme = new ReactiveObject<bool>();
CustomThemePath = new ReactiveObject<string>();
StartFullscreen = new ReactiveObject<bool>();
ShowConsole = new ReactiveObject<bool>();
ShowConsole.Event += static (s, e) => { ConsoleHelper.SetConsoleWindowState(e.NewValue); };
}
}
@ -508,6 +516,7 @@ namespace Ryujinx.Configuration
EnableCustomTheme = Ui.EnableCustomTheme,
CustomThemePath = Ui.CustomThemePath,
StartFullscreen = Ui.StartFullscreen,
ShowConsole = Ui.ShowConsole,
EnableKeyboard = Hid.EnableKeyboard,
EnableMouse = Hid.EnableMouse,
Hotkeys = Hid.Hotkeys,
@ -574,6 +583,7 @@ namespace Ryujinx.Configuration
Ui.EnableCustomTheme.Value = false;
Ui.CustomThemePath.Value = "";
Ui.StartFullscreen.Value = false;
Ui.ShowConsole.Value = true;
Hid.EnableKeyboard.Value = false;
Hid.EnableMouse.Value = false;
Hid.Hotkeys.Value = new KeyboardHotkeys
@ -995,7 +1005,7 @@ namespace Ryujinx.Configuration
controllerConfig.RangeRight = 1.0f;
}
}
configurationFileUpdated = true;
}
@ -1007,7 +1017,16 @@ namespace Ryujinx.Configuration
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 37)
{
Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 37.");
configurationFileFormat.ShowConsole = true;
configurationFileUpdated = true;
}
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
Graphics.BackendThreading.Value = configurationFileFormat.BackendThreading;
Graphics.ResScale.Value = configurationFileFormat.ResScale;
@ -1061,6 +1080,7 @@ namespace Ryujinx.Configuration
Ui.EnableCustomTheme.Value = configurationFileFormat.EnableCustomTheme;
Ui.CustomThemePath.Value = configurationFileFormat.CustomThemePath;
Ui.StartFullscreen.Value = configurationFileFormat.StartFullscreen;
Ui.ShowConsole.Value = configurationFileFormat.ShowConsole;
Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard;
Hid.EnableMouse.Value = configurationFileFormat.EnableMouse;
Hid.Hotkeys.Value = configurationFileFormat.Hotkeys;

View File

@ -0,0 +1,49 @@
using Ryujinx.Common.Logging;
using System;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
namespace Ryujinx.Ui.Helper
{
public static class ConsoleHelper
{
public static bool SetConsoleWindowStateSupported => OperatingSystem.IsWindows();
public static void SetConsoleWindowState(bool show)
{
if (OperatingSystem.IsWindows())
{
SetConsoleWindowStateWindows(show);
}
else if (show == false)
{
Logger.Warning?.Print(LogClass.Application, "OS doesn't support hiding console window");
}
}
[SupportedOSPlatform("windows")]
private static void SetConsoleWindowStateWindows(bool show)
{
const int SW_HIDE = 0;
const int SW_SHOW = 5;
IntPtr hWnd = GetConsoleWindow();
if (hWnd == IntPtr.Zero)
{
Logger.Warning?.Print(LogClass.Application, "Attempted to show/hide console window but console window does not exist");
return;
}
ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
}
[SupportedOSPlatform("windows")]
[DllImport("kernel32")]
static extern IntPtr GetConsoleWindow();
[SupportedOSPlatform("windows")]
[DllImport("user32")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
}
}

View File

@ -107,6 +107,7 @@ namespace Ryujinx.Ui
[GUI] MenuItem _hideUi;
[GUI] MenuItem _fullScreen;
[GUI] CheckMenuItem _startFullScreen;
[GUI] CheckMenuItem _showConsole;
[GUI] CheckMenuItem _favToggle;
[GUI] MenuItem _firmwareInstallDirectory;
[GUI] MenuItem _firmwareInstallFile;
@ -213,6 +214,9 @@ namespace Ryujinx.Ui
_startFullScreen.Active = true;
}
_showConsole.Active = ConfigurationState.Instance.Ui.ShowConsole.Value;
_showConsole.Visible = ConsoleHelper.SetConsoleWindowStateSupported;
_actionMenu.Sensitive = false;
_pauseEmulation.Sensitive = false;
_resumeEmulation.Sensitive = false;
@ -1535,6 +1539,13 @@ namespace Ryujinx.Ui
SaveConfig();
}
private void ShowConsole_Toggled(object sender, EventArgs args)
{
ConfigurationState.Instance.Ui.ShowConsole.Value = _showConsole.Active;
SaveConfig();
}
private void OptionMenu_StateChanged(object o, StateChangedArgs args)
{
_manageUserProfiles.Sensitive = _emulationContext == null;

View File

@ -142,6 +142,15 @@
<signal name="toggled" handler="StartFullScreen_Toggled" swapped="no"/>
</object>
</child>
<child>
<object class="GtkCheckMenuItem" id="_showConsole">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Show Log Console</property>
<property name="use_underline">True</property>
<signal name="toggled" handler="ShowConsole_Toggled" swapped="no"/>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem">
<property name="visible">True</property>

View File

@ -73,6 +73,7 @@ namespace Ryujinx.Ui.Windows
[GUI] ToggleButton _lStick;
[GUI] CheckButton _invertLStickX;
[GUI] CheckButton _invertLStickY;
[GUI] CheckButton _rotateL90CW;
[GUI] ToggleButton _lStickUp;
[GUI] ToggleButton _lStickDown;
[GUI] ToggleButton _lStickLeft;
@ -88,6 +89,7 @@ namespace Ryujinx.Ui.Windows
[GUI] ToggleButton _rStick;
[GUI] CheckButton _invertRStickX;
[GUI] CheckButton _invertRStickY;
[GUI] CheckButton _rotateR90CW;
[GUI] ToggleButton _rStickUp;
[GUI] ToggleButton _rStickDown;
[GUI] ToggleButton _rStickLeft;
@ -490,6 +492,7 @@ namespace Ryujinx.Ui.Windows
_lStick.Label = controllerConfig.LeftJoyconStick.Joystick.ToString();
_invertLStickX.Active = controllerConfig.LeftJoyconStick.InvertStickX;
_invertLStickY.Active = controllerConfig.LeftJoyconStick.InvertStickY;
_rotateL90CW.Active = controllerConfig.LeftJoyconStick.Rotate90CW;
_lStickButton.Label = controllerConfig.LeftJoyconStick.StickButton.ToString();
_dpadUp.Label = controllerConfig.LeftJoycon.DpadUp.ToString();
_dpadDown.Label = controllerConfig.LeftJoycon.DpadDown.ToString();
@ -503,6 +506,7 @@ namespace Ryujinx.Ui.Windows
_rStick.Label = controllerConfig.RightJoyconStick.Joystick.ToString();
_invertRStickX.Active = controllerConfig.RightJoyconStick.InvertStickX;
_invertRStickY.Active = controllerConfig.RightJoyconStick.InvertStickY;
_rotateR90CW.Active = controllerConfig.RightJoyconStick.Rotate90CW;
_rStickButton.Label = controllerConfig.RightJoyconStick.StickButton.ToString();
_a.Label = controllerConfig.RightJoycon.ButtonA.ToString();
_b.Label = controllerConfig.RightJoycon.ButtonB.ToString();
@ -718,6 +722,7 @@ namespace Ryujinx.Ui.Windows
Joystick = lStick,
InvertStickY = _invertLStickY.Active,
StickButton = lStickButton,
Rotate90CW = _rotateL90CW.Active,
},
RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
{
@ -737,6 +742,7 @@ namespace Ryujinx.Ui.Windows
Joystick = rStick,
InvertStickY = _invertRStickY.Active,
StickButton = rStickButton,
Rotate90CW = _rotateR90CW.Active,
},
Motion = motionConfig,
Rumble = new RumbleConfigController
@ -1056,6 +1062,7 @@ namespace Ryujinx.Ui.Windows
StickButton = ConfigGamepadInputId.LeftStick,
InvertStickX = false,
InvertStickY = false,
Rotate90CW = false,
},
RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
@ -1077,6 +1084,7 @@ namespace Ryujinx.Ui.Windows
StickButton = ConfigGamepadInputId.RightStick,
InvertStickX = false,
InvertStickY = false,
Rotate90CW = false,
},
Motion = new StandardMotionConfigController

View File

@ -740,6 +740,19 @@
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="_rotateL90CW">
<property name="label" translatable="yes">Rotate 90° Clockwise</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
@ -1697,6 +1710,19 @@
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="_rotateR90CW">
<property name="label" translatable="yes">Rotate 90° Clockwise</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>