Merge branch 'master' into aot

This commit is contained in:
LDj3SNuD 2019-11-14 21:17:09 +01:00
commit cda2b2d23c
13 changed files with 366 additions and 18 deletions

View file

@ -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);
}
}
}

View 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.");
}
}
}

View 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();
}
}

View 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();
}
}
}
}

View file

@ -0,0 +1,8 @@
namespace Ryujinx.HLE.HOS.Applets
{
enum PlayerSelectResult : ulong
{
Success = 0,
Failure = 2
}
}

View file

@ -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)

View file

@ -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);
}
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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;
}

View 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();
}
}
}

View 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
}
}

View file

@ -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 });

View 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
}
}