Merge branch 'master' into aot
This commit is contained in:
commit
cda2b2d23c
13 changed files with 366 additions and 18 deletions
|
@ -1,5 +1,6 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
|
@ -32,6 +33,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
case 0b11_011_0000_0000_001: name = nameof(NativeInterface.GetCtrEl0); break;
|
||||
case 0b11_011_0000_0000_111: name = nameof(NativeInterface.GetDczidEl0); break;
|
||||
case 0b11_011_0100_0010_000: EmitGetNzcv(context); return;
|
||||
case 0b11_011_0100_0100_000: name = nameof(NativeInterface.GetFpcr); break;
|
||||
case 0b11_011_0100_0100_001: name = nameof(NativeInterface.GetFpsr); break;
|
||||
case 0b11_011_1101_0000_010: name = nameof(NativeInterface.GetTpidrEl0); break;
|
||||
|
@ -53,6 +55,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (GetPackedId(op))
|
||||
{
|
||||
case 0b11_011_0100_0010_000: EmitSetNzcv(context); return;
|
||||
case 0b11_011_0100_0100_000: name = nameof(NativeInterface.SetFpcr); break;
|
||||
case 0b11_011_0100_0100_001: name = nameof(NativeInterface.SetFpsr); break;
|
||||
case 0b11_011_1101_0000_010: name = nameof(NativeInterface.SetTpidrEl0); break;
|
||||
|
@ -110,5 +113,44 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
return id;
|
||||
}
|
||||
|
||||
private static void EmitGetNzcv(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
Operand vSh = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
|
||||
Operand cSh = context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag));
|
||||
Operand zSh = context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag));
|
||||
Operand nSh = context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag));
|
||||
|
||||
Operand nzcvSh = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
|
||||
|
||||
SetIntOrZR(context, op.Rt, nzcvSh);
|
||||
}
|
||||
|
||||
private static void EmitSetNzcv(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
Operand t = GetIntOrZR(context, op.Rt);
|
||||
t = context.ConvertI64ToI32(t);
|
||||
|
||||
Operand v = context.ShiftRightUI(t, Const((int)PState.VFlag));
|
||||
v = context.BitwiseAnd (v, Const(1));
|
||||
|
||||
Operand c = context.ShiftRightUI(t, Const((int)PState.CFlag));
|
||||
c = context.BitwiseAnd (c, Const(1));
|
||||
|
||||
Operand z = context.ShiftRightUI(t, Const((int)PState.ZFlag));
|
||||
z = context.BitwiseAnd (z, Const(1));
|
||||
|
||||
Operand n = context.ShiftRightUI(t, Const((int)PState.NFlag));
|
||||
n = context.BitwiseAnd (n, Const(1));
|
||||
|
||||
SetFlag(context, PState.VFlag, v);
|
||||
SetFlag(context, PState.CFlag, c);
|
||||
SetFlag(context, PState.ZFlag, z);
|
||||
SetFlag(context, PState.NFlag, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
29
Ryujinx.HLE/HOS/Applets/AppletManager.cs
Normal file
29
Ryujinx.HLE/HOS/Applets/AppletManager.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using Ryujinx.HLE.HOS.Services.Am.AppletAE;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Applets
|
||||
{
|
||||
static class AppletManager
|
||||
{
|
||||
private static Dictionary<AppletId, Type> _appletMapping;
|
||||
|
||||
static AppletManager()
|
||||
{
|
||||
_appletMapping = new Dictionary<AppletId, Type>
|
||||
{
|
||||
{ AppletId.PlayerSelect, typeof(PlayerSelectApplet) }
|
||||
};
|
||||
}
|
||||
|
||||
public static IApplet Create(AppletId applet, Horizon system)
|
||||
{
|
||||
if (_appletMapping.TryGetValue(applet, out Type appletClass))
|
||||
{
|
||||
return (IApplet)Activator.CreateInstance(appletClass, system);
|
||||
}
|
||||
|
||||
throw new NotImplementedException($"{applet} applet is not implemented.");
|
||||
}
|
||||
}
|
||||
}
|
13
Ryujinx.HLE/HOS/Applets/IApplet.cs
Normal file
13
Ryujinx.HLE/HOS/Applets/IApplet.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using Ryujinx.HLE.HOS.Services.Am.AppletAE;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Applets
|
||||
{
|
||||
interface IApplet
|
||||
{
|
||||
event EventHandler AppletStateChanged;
|
||||
|
||||
ResultCode Start(AppletFifo<byte[]> inData, AppletFifo<byte[]> outData);
|
||||
ResultCode GetResult();
|
||||
}
|
||||
}
|
55
Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectApplet.cs
Normal file
55
Ryujinx.HLE/HOS/Applets/PlayerSelect/PlayerSelectApplet.cs
Normal file
|
@ -0,0 +1,55 @@
|
|||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||
using Ryujinx.HLE.HOS.Services.Am.AppletAE;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Applets
|
||||
{
|
||||
internal class PlayerSelectApplet : IApplet
|
||||
{
|
||||
private Horizon _system;
|
||||
|
||||
private AppletFifo<byte[]> _inputData;
|
||||
private AppletFifo<byte[]> _outputData;
|
||||
|
||||
public event EventHandler AppletStateChanged;
|
||||
|
||||
public PlayerSelectApplet(Horizon system)
|
||||
{
|
||||
_system = system;
|
||||
}
|
||||
|
||||
public ResultCode Start(AppletFifo<byte[]> inData, AppletFifo<byte[]> outData)
|
||||
{
|
||||
_inputData = inData;
|
||||
_outputData = outData;
|
||||
|
||||
// TODO(jduncanator): Parse PlayerSelectConfig from input data
|
||||
_outputData.Push(BuildResponse());
|
||||
|
||||
AppletStateChanged?.Invoke(this, null);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
public ResultCode GetResult()
|
||||
{
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
private byte[] BuildResponse()
|
||||
{
|
||||
UserProfile currentUser = _system.State.Account.LastOpenedUser;
|
||||
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
using (BinaryWriter writer = new BinaryWriter(stream))
|
||||
{
|
||||
writer.Write((ulong)PlayerSelectResult.Success);
|
||||
|
||||
currentUser.UserId.Write(writer);
|
||||
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
namespace Ryujinx.HLE.HOS.Applets
|
||||
{
|
||||
enum PlayerSelectResult : ulong
|
||||
{
|
||||
Success = 0,
|
||||
Failure = 2
|
||||
}
|
||||
}
|
|
@ -162,6 +162,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
bool isAarch32 = (Owner.MmuFlags & 1) == 0;
|
||||
|
||||
Context.IsAarch32 = isAarch32;
|
||||
|
||||
Context.SetX(0, argsPtr);
|
||||
|
||||
if (isAarch32)
|
||||
|
|
|
@ -127,7 +127,7 @@ namespace Ryujinx.HLE.HOS
|
|||
{
|
||||
if (!metaData.Is64Bits)
|
||||
{
|
||||
Logger.PrintWarning(LogClass.Loader, "32-bits application detected!");
|
||||
Logger.PrintWarning(LogClass.Loader, "32-bits application detected.");
|
||||
}
|
||||
|
||||
ulong argsStart = 0;
|
||||
|
@ -309,4 +309,4 @@ namespace Ryujinx.HLE.HOS
|
|||
return SetProcessMemoryPermission(dataStart, end - dataStart, MemoryPermission.ReadAndWrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,37 @@
|
|||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.HOS.Applets;
|
||||
using Ryujinx.HLE.HOS.Ipc;
|
||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||
using Ryujinx.HLE.HOS.Services.Am.AppletAE.Storage;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletCreator
|
||||
{
|
||||
class ILibraryAppletAccessor : IpcService
|
||||
{
|
||||
private IApplet _applet;
|
||||
|
||||
private AppletFifo<byte[]> _inData;
|
||||
private AppletFifo<byte[]> _outData;
|
||||
|
||||
private KEvent _stateChangedEvent;
|
||||
|
||||
public ILibraryAppletAccessor(Horizon system)
|
||||
public ILibraryAppletAccessor(AppletId appletId, Horizon system)
|
||||
{
|
||||
_stateChangedEvent = new KEvent(system);
|
||||
|
||||
_applet = AppletManager.Create(appletId, system);
|
||||
_inData = new AppletFifo<byte[]>();
|
||||
_outData = new AppletFifo<byte[]>();
|
||||
|
||||
_applet.AppletStateChanged += OnAppletStateChanged;
|
||||
|
||||
Logger.PrintInfo(LogClass.ServiceAm, $"Applet '{appletId}' created.");
|
||||
}
|
||||
|
||||
private void OnAppletStateChanged(object sender, EventArgs e)
|
||||
{
|
||||
_stateChangedEvent.ReadableEvent.Signal();
|
||||
}
|
||||
|
||||
[Command(0)]
|
||||
|
@ -29,8 +47,6 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
|
|||
|
||||
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
|
||||
|
||||
Logger.PrintStub(LogClass.ServiceAm);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
|
@ -38,25 +54,23 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
|
|||
// Start()
|
||||
public ResultCode Start(ServiceCtx context)
|
||||
{
|
||||
Logger.PrintStub(LogClass.ServiceAm);
|
||||
|
||||
return ResultCode.Success;
|
||||
return (ResultCode)_applet.Start(_inData, _outData);
|
||||
}
|
||||
|
||||
[Command(30)]
|
||||
// GetResult()
|
||||
public ResultCode GetResult(ServiceCtx context)
|
||||
{
|
||||
Logger.PrintStub(LogClass.ServiceAm);
|
||||
|
||||
return ResultCode.Success;
|
||||
return (ResultCode)_applet.GetResult();
|
||||
}
|
||||
|
||||
[Command(100)]
|
||||
// PushInData(object<nn::am::service::IStorage>)
|
||||
public ResultCode PushInData(ServiceCtx context)
|
||||
{
|
||||
Logger.PrintStub(LogClass.ServiceAm);
|
||||
IStorage data = GetObject<IStorage>(context, 0);
|
||||
|
||||
_inData.Push(data.Data);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
@ -65,9 +79,11 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
|
|||
// PopOutData() -> object<nn::am::service::IStorage>
|
||||
public ResultCode PopOutData(ServiceCtx context)
|
||||
{
|
||||
MakeObject(context, new IStorage(StorageHelper.MakeLaunchParams()));
|
||||
byte[] data = _outData.Pop();
|
||||
|
||||
MakeObject(context, new IStorage(data));
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using Ryujinx.HLE.HOS.Applets;
|
||||
using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletCreator;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
||||
|
@ -10,7 +11,10 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
|||
// CreateLibraryApplet(u32, u32) -> object<nn::am::service::ILibraryAppletAccessor>
|
||||
public ResultCode CreateLibraryApplet(ServiceCtx context)
|
||||
{
|
||||
MakeObject(context, new ILibraryAppletAccessor(context.Device.System));
|
||||
AppletId appletId = (AppletId)context.RequestData.ReadInt32();
|
||||
int libraryAppletMode = context.RequestData.ReadInt32();
|
||||
|
||||
MakeObject(context, new ILibraryAppletAccessor(appletId, context.Device.System));
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
|
79
Ryujinx.HLE/HOS/Services/Am/AppletAE/AppletFifo.cs
Normal file
79
Ryujinx.HLE/HOS/Services/Am/AppletAE/AppletFifo.cs
Normal file
|
@ -0,0 +1,79 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
|
||||
{
|
||||
internal class AppletFifo<T> : IEnumerable<T>
|
||||
{
|
||||
private ConcurrentQueue<T> _dataQueue;
|
||||
|
||||
public int Count => _dataQueue.Count;
|
||||
|
||||
public AppletFifo()
|
||||
{
|
||||
_dataQueue = new ConcurrentQueue<T>();
|
||||
}
|
||||
|
||||
public void Push(T item)
|
||||
{
|
||||
_dataQueue.Enqueue(item);
|
||||
}
|
||||
|
||||
public T Pop()
|
||||
{
|
||||
if (_dataQueue.TryDequeue(out T result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("FIFO empty.");
|
||||
}
|
||||
|
||||
public bool TryPop(out T result)
|
||||
{
|
||||
return _dataQueue.TryDequeue(out result);
|
||||
}
|
||||
|
||||
public T Peek()
|
||||
{
|
||||
if (_dataQueue.TryPeek(out T result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("FIFO empty.");
|
||||
}
|
||||
|
||||
public bool TryPeek(out T result)
|
||||
{
|
||||
return _dataQueue.TryPeek(out result);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_dataQueue.Clear();
|
||||
}
|
||||
|
||||
public T[] ToArray()
|
||||
{
|
||||
return _dataQueue.ToArray();
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
_dataQueue.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return _dataQueue.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return _dataQueue.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
27
Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/AppletId.cs
Normal file
27
Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/AppletId.cs
Normal file
|
@ -0,0 +1,27 @@
|
|||
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
|
||||
{
|
||||
enum AppletId
|
||||
{
|
||||
Application = 0x01,
|
||||
OverlayDisplay = 0x02,
|
||||
QLaunch = 0x03,
|
||||
Starter = 0x04,
|
||||
Auth = 0x0A,
|
||||
Cabinet = 0x0B,
|
||||
Controller = 0x0C,
|
||||
DataErase = 0x0D,
|
||||
Error = 0x0E,
|
||||
NetConnect = 0x0F,
|
||||
PlayerSelect = 0x10,
|
||||
SoftwareKeyboard = 0x11,
|
||||
MiiEdit = 0x12,
|
||||
LibAppletWeb = 0x13,
|
||||
LibAppletShop = 0x14,
|
||||
PhotoViewer = 0x15,
|
||||
Settings = 0x16,
|
||||
LibAppletOff = 0x17,
|
||||
LibAppletWhitelisted = 0x18,
|
||||
LibAppletAuth = 0x19,
|
||||
MyPage = 0x1A
|
||||
}
|
||||
}
|
|
@ -134,11 +134,11 @@ namespace Ryujinx.HLE.HOS.Services.Audio
|
|||
}
|
||||
|
||||
[Command(4)] // 4.0.0+
|
||||
// GetAudioDeviceServiceWithRevisionInfo(nn::applet::AppletResourceUserId, u32) -> object<nn::audio::detail::IAudioDevice>
|
||||
// GetAudioDeviceServiceWithRevisionInfo(u32 revision_info, nn::applet::AppletResourceUserId) -> object<nn::audio::detail::IAudioDevice>
|
||||
public ResultCode GetAudioDeviceServiceWithRevisionInfo(ServiceCtx context)
|
||||
{
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
int revisionInfo = context.RequestData.ReadInt32();
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
Logger.PrintStub(LogClass.ServiceAudio, new { appletResourceUserId, revisionInfo });
|
||||
|
||||
|
|
73
Ryujinx.Tests/Cpu/CpuTestSystem.cs
Normal file
73
Ryujinx.Tests/Cpu/CpuTestSystem.cs
Normal file
|
@ -0,0 +1,73 @@
|
|||
#define System
|
||||
|
||||
using ARMeilleure.State;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Tests.Cpu
|
||||
{
|
||||
[Category("System")]
|
||||
public sealed class CpuTestSystem : CpuTest
|
||||
{
|
||||
#if System
|
||||
|
||||
#region "ValueSource (Types)"
|
||||
private static IEnumerable<ulong> _GenNzcv_()
|
||||
{
|
||||
yield return 0x0000000000000000ul;
|
||||
yield return 0x7FFFFFFFFFFFFFFFul;
|
||||
yield return 0x8000000000000000ul;
|
||||
yield return 0xFFFFFFFFFFFFFFFFul;
|
||||
|
||||
bool v = TestContext.CurrentContext.Random.NextBool();
|
||||
bool c = TestContext.CurrentContext.Random.NextBool();
|
||||
bool z = TestContext.CurrentContext.Random.NextBool();
|
||||
bool n = TestContext.CurrentContext.Random.NextBool();
|
||||
|
||||
ulong rnd = 0UL;
|
||||
|
||||
rnd |= (v ? 1UL : 0UL) << (int)PState.VFlag;
|
||||
rnd |= (c ? 1UL : 0UL) << (int)PState.CFlag;
|
||||
rnd |= (z ? 1UL : 0UL) << (int)PState.ZFlag;
|
||||
rnd |= (n ? 1UL : 0UL) << (int)PState.NFlag;
|
||||
|
||||
yield return rnd;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region "ValueSource (Opcodes)"
|
||||
private static uint[] _MrsMsr_Nzcv_()
|
||||
{
|
||||
return new uint[]
|
||||
{
|
||||
0xD53B4200u, // MRS X0, NZCV
|
||||
0xD51B4200u // MSR NZCV, X0
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
private const int RndCnt = 2;
|
||||
|
||||
[Test, Pairwise]
|
||||
public void MrsMsr_Nzcv([ValueSource("_MrsMsr_Nzcv_")] uint opcodes,
|
||||
[Values(0u, 1u, 31u)] uint rt,
|
||||
[ValueSource("_GenNzcv_")] [Random(RndCnt)] ulong xt)
|
||||
{
|
||||
opcodes |= (rt & 31) << 0;
|
||||
|
||||
bool v = TestContext.CurrentContext.Random.NextBool();
|
||||
bool c = TestContext.CurrentContext.Random.NextBool();
|
||||
bool z = TestContext.CurrentContext.Random.NextBool();
|
||||
bool n = TestContext.CurrentContext.Random.NextBool();
|
||||
|
||||
ulong x31 = TestContext.CurrentContext.Random.NextULong();
|
||||
|
||||
SingleOpcode(opcodes, x0: xt, x1: xt, x31: x31, overflow: v, carry: c, zero: z, negative: n);
|
||||
|
||||
CompareAgainstUnicorn();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue