From 3936c934482a587635bc5a1e47962551aeb53aeb Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 23 Feb 2018 21:59:38 -0300 Subject: [PATCH] Map heap on heap base region, fix for thread start on homebrew, add FCVTMU and FCVTPU (general) instructions, fix FMOV (higher 64 bits) encodings, improve emit code for FCVT* (general) instructions --- ChocolArm64/AOpCodeTable.cs | 6 +- ChocolArm64/Instruction/AInstEmitSimdCvt.cs | 105 ++++++++++-------- Ryujinx.Core/Loaders/Executable.cs | 3 - .../Loaders/Executables/IExecutable.cs | 8 -- Ryujinx.Core/Loaders/Executables/Nro.cs | 4 - Ryujinx.Core/Loaders/Executables/Nso.cs | 4 - Ryujinx.Core/OsHle/Horizon.cs | 16 ++- Ryujinx.Core/OsHle/MemoryRegions.cs | 13 +++ .../OsHle/Objects/Android/NvFlinger.cs | 2 +- .../OsHle/Objects/FspSrv/IFileSystem.cs | 13 ++- Ryujinx.Core/OsHle/Process.cs | 19 ++-- Ryujinx.Core/OsHle/Svc/SvcSystem.cs | 8 +- Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs | 5 +- Ryujinx/Ui/Program.cs | 4 +- 14 files changed, 109 insertions(+), 101 deletions(-) create mode 100644 Ryujinx.Core/OsHle/MemoryRegions.cs diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index d4d6dd7c3..b8fe278dd 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -156,7 +156,9 @@ namespace ChocolArm64 Set("x00111100x100100000000xxxxxxxxxx", AInstEmit.Fcvtas_Gp, typeof(AOpCodeSimdCvt)); Set("x00111100x100101000000xxxxxxxxxx", AInstEmit.Fcvtau_Gp, typeof(AOpCodeSimdCvt)); Set("x00111100x110000000000xxxxxxxxxx", AInstEmit.Fcvtms_Gp, typeof(AOpCodeSimdCvt)); + Set("x00111100x110001000000xxxxxxxxxx", AInstEmit.Fcvtmu_Gp, typeof(AOpCodeSimdCvt)); Set("x00111100x101000000000xxxxxxxxxx", AInstEmit.Fcvtps_Gp, typeof(AOpCodeSimdCvt)); + Set("x00111100x101001000000xxxxxxxxxx", AInstEmit.Fcvtpu_Gp, typeof(AOpCodeSimdCvt)); Set("x00111100x111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_Gp, typeof(AOpCodeSimdCvt)); Set("x00111100x011000xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzs_Gp_Fix, typeof(AOpCodeSimdCvt)); Set("0>0011101<100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimd)); @@ -179,8 +181,8 @@ namespace ChocolArm64 Set("0xx0111100000xxx111101xxxxxxxxxx", AInstEmit.Fmov_V, typeof(AOpCodeSimdImm)); Set("x00111100x100110000000xxxxxxxxxx", AInstEmit.Fmov_Ftoi, typeof(AOpCodeSimdCvt)); Set("x00111100x100111000000xxxxxxxxxx", AInstEmit.Fmov_Itof, typeof(AOpCodeSimdCvt)); - Set("x00111100x101110000000xxxxxxxxxx", AInstEmit.Fmov_Ftoi1, typeof(AOpCodeSimdCvt)); - Set("x00111100x101111000000xxxxxxxxxx", AInstEmit.Fmov_Itof1, typeof(AOpCodeSimdCvt)); + Set("1001111010101110000000xxxxxxxxxx", AInstEmit.Fmov_Ftoi1, typeof(AOpCodeSimdCvt)); + Set("1001111010101111000000xxxxxxxxxx", AInstEmit.Fmov_Itof1, typeof(AOpCodeSimdCvt)); Set("000111110x0xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Fmsub_S, typeof(AOpCodeSimdReg)); Set("000111100x1xxxxx000010xxxxxxxxxx", AInstEmit.Fmul_S, typeof(AOpCodeSimdReg)); Set("0>1011100<1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg)); diff --git a/ChocolArm64/Instruction/AInstEmitSimdCvt.cs b/ChocolArm64/Instruction/AInstEmitSimdCvt.cs index 00c2fe9b5..688f05a20 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdCvt.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdCvt.cs @@ -23,52 +23,62 @@ namespace ChocolArm64.Instruction public static void Fcvtas_Gp(AILEmitterCtx Context) { - Fcvta__Gp(Context, Signed: true); + EmitFcvt_s_Gp(Context, () => EmitRoundMathCall(Context, MidpointRounding.AwayFromZero)); } public static void Fcvtau_Gp(AILEmitterCtx Context) { - Fcvta__Gp(Context, Signed: false); + EmitFcvt_u_Gp(Context, () => EmitRoundMathCall(Context, MidpointRounding.AwayFromZero)); } public static void Fcvtms_Gp(AILEmitterCtx Context) { - EmitFcvt_s_Gp(Context, nameof(Math.Floor)); + EmitFcvt_s_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Floor))); + } + + public static void Fcvtmu_Gp(AILEmitterCtx Context) + { + EmitFcvt_u_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Floor))); } public static void Fcvtps_Gp(AILEmitterCtx Context) { - EmitFcvt_s_Gp(Context, nameof(Math.Ceiling)); + EmitFcvt_s_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Ceiling))); + } + + public static void Fcvtpu_Gp(AILEmitterCtx Context) + { + EmitFcvt_u_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Ceiling))); } public static void Fcvtzs_Gp(AILEmitterCtx Context) { - EmitFcvtz__Gp(Context, Signed: true); + EmitFcvt_s_Gp(Context, () => { }); } public static void Fcvtzs_Gp_Fix(AILEmitterCtx Context) { - EmitFcvtz__Gp_Fix(Context, Signed: true); + EmitFcvtzs_Gp_Fix(Context); } public static void Fcvtzs_V(AILEmitterCtx Context) { - EmitVectorFcvt(Context, Signed: true); + EmitVectorFcvtzs(Context); } public static void Fcvtzu_Gp(AILEmitterCtx Context) { - EmitFcvtz__Gp(Context, Signed: false); + EmitFcvt_u_Gp(Context, () => { }); } public static void Fcvtzu_Gp_Fix(AILEmitterCtx Context) { - EmitFcvtz__Gp_Fix(Context, Signed: false); + EmitFcvtzu_Gp_Fix(Context); } public static void Fcvtzu_V(AILEmitterCtx Context) { - EmitVectorFcvt(Context, Signed: false); + EmitVectorFcvtzu(Context); } public static void Scvtf_Gp(AILEmitterCtx Context) @@ -165,13 +175,23 @@ namespace ChocolArm64.Instruction } } - private static void Fcvta__Gp(AILEmitterCtx Context, bool Signed) + private static void EmitFcvt_s_Gp(AILEmitterCtx Context, Action Emit) + { + EmitFcvt___Gp(Context, Emit, true); + } + + private static void EmitFcvt_u_Gp(AILEmitterCtx Context, Action Emit) + { + EmitFcvt___Gp(Context, Emit, false); + } + + private static void EmitFcvt___Gp(AILEmitterCtx Context, Action Emit, bool Signed) { AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; EmitVectorExtractF(Context, Op.Rn, 0, Op.Size); - EmitRoundMathCall(Context, MidpointRounding.AwayFromZero); + Emit(); if (Signed) { @@ -190,45 +210,14 @@ namespace ChocolArm64.Instruction Context.EmitStintzr(Op.Rd); } - private static void EmitFcvt_s_Gp(AILEmitterCtx Context, string Name) + private static void EmitFcvtzs_Gp_Fix(AILEmitterCtx Context) { - AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; - - EmitVectorExtractF(Context, Op.Rn, 0, Op.Size); - - EmitUnaryMathCall(Context, Name); - - EmitScalarFcvts(Context, Op.Size, 0); - - if (Context.CurrOp.RegisterSize == ARegisterSize.Int32) - { - Context.Emit(OpCodes.Conv_U8); - } - - Context.EmitStintzr(Op.Rd); + EmitFcvtz__Gp_Fix(Context, true); } - private static void EmitFcvtz__Gp(AILEmitterCtx Context, bool Signed) + private static void EmitFcvtzu_Gp_Fix(AILEmitterCtx Context) { - AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; - - EmitVectorExtractF(Context, Op.Rn, 0, Op.Size); - - if (Signed) - { - EmitScalarFcvts(Context, Op.Size, 0); - } - else - { - EmitScalarFcvtu(Context, Op.Size, 0); - } - - if (Context.CurrOp.RegisterSize == ARegisterSize.Int32) - { - Context.Emit(OpCodes.Conv_U8); - } - - Context.EmitStintzr(Op.Rd); + EmitFcvtz__Gp_Fix(Context, false); } private static void EmitFcvtz__Gp_Fix(AILEmitterCtx Context, bool Signed) @@ -254,6 +243,16 @@ namespace ChocolArm64.Instruction Context.EmitStintzr(Op.Rd); } + private static void EmitVectorScvtf(AILEmitterCtx Context) + { + EmitVectorCvtf(Context, true); + } + + private static void EmitVectorUcvtf(AILEmitterCtx Context) + { + EmitVectorCvtf(Context, false); + } + private static void EmitVectorCvtf(AILEmitterCtx Context, bool Signed) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; @@ -289,7 +288,17 @@ namespace ChocolArm64.Instruction } } - private static void EmitVectorFcvt(AILEmitterCtx Context, bool Signed) + private static void EmitVectorFcvtzs(AILEmitterCtx Context) + { + EmitVectorFcvtz(Context, true); + } + + private static void EmitVectorFcvtzu(AILEmitterCtx Context) + { + EmitVectorFcvtz(Context, false); + } + + private static void EmitVectorFcvtz(AILEmitterCtx Context, bool Signed) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; diff --git a/Ryujinx.Core/Loaders/Executable.cs b/Ryujinx.Core/Loaders/Executable.cs index 25a621362..e26608389 100644 --- a/Ryujinx.Core/Loaders/Executable.cs +++ b/Ryujinx.Core/Loaders/Executable.cs @@ -13,7 +13,6 @@ namespace Ryujinx.Core.Loaders public long ImageBase { get; private set; } public long ImageEnd { get; private set; } - public Extensions Extension { get; private set; } public Executable(IExecutable Exe, AMemory Memory, long ImageBase) { @@ -47,8 +46,6 @@ namespace Ryujinx.Core.Loaders long EhHdrEndOffset = Memory.ReadInt32(Mod0Offset + 0x14) + Mod0Offset; long ModObjOffset = Memory.ReadInt32(Mod0Offset + 0x18) + Mod0Offset; - Extension = Exe.Extension; - MapBss(BssStartOffset, BssEndOffset - BssStartOffset); ImageEnd = BssEndOffset; diff --git a/Ryujinx.Core/Loaders/Executables/IExecutable.cs b/Ryujinx.Core/Loaders/Executables/IExecutable.cs index f6aa31aca..73787b1d2 100644 --- a/Ryujinx.Core/Loaders/Executables/IExecutable.cs +++ b/Ryujinx.Core/Loaders/Executables/IExecutable.cs @@ -2,12 +2,6 @@ using System.Collections.ObjectModel; namespace Ryujinx.Core.Loaders.Executables { - public enum Extensions - { - NRO, - NSO - } - public interface IExecutable { ReadOnlyCollection Text { get; } @@ -19,7 +13,5 @@ namespace Ryujinx.Core.Loaders.Executables int ROOffset { get; } int DataOffset { get; } int BssSize { get; } - - Extensions Extension { get; } } } \ No newline at end of file diff --git a/Ryujinx.Core/Loaders/Executables/Nro.cs b/Ryujinx.Core/Loaders/Executables/Nro.cs index 7f492cc2b..3cbc4c5d4 100644 --- a/Ryujinx.Core/Loaders/Executables/Nro.cs +++ b/Ryujinx.Core/Loaders/Executables/Nro.cs @@ -20,8 +20,6 @@ namespace Ryujinx.Core.Loaders.Executables public int DataOffset { get; private set; } public int BssSize { get; private set; } - public Extensions Extension { get; private set; } - public Nro(Stream Input) { BinaryReader Reader = new BinaryReader(Input); @@ -49,8 +47,6 @@ namespace Ryujinx.Core.Loaders.Executables this.DataOffset = DataOffset; this.BssSize = BssSize; - this.Extension = Extensions.NRO; - byte[] Read(long Position, int Size) { Input.Seek(Position, SeekOrigin.Begin); diff --git a/Ryujinx.Core/Loaders/Executables/Nso.cs b/Ryujinx.Core/Loaders/Executables/Nso.cs index 63ae08aea..7b8bf253a 100644 --- a/Ryujinx.Core/Loaders/Executables/Nso.cs +++ b/Ryujinx.Core/Loaders/Executables/Nso.cs @@ -21,8 +21,6 @@ namespace Ryujinx.Core.Loaders.Executables public int DataOffset { get; private set; } public int BssSize { get; private set; } - public Extensions Extension { get; private set; } - [Flags] private enum NsoFlags { @@ -81,8 +79,6 @@ namespace Ryujinx.Core.Loaders.Executables this.DataOffset = DataMemOffset; this.BssSize = BssSize; - this.Extension = Extensions.NSO; - //Text segment Input.Seek(TextOffset, SeekOrigin.Begin); diff --git a/Ryujinx.Core/OsHle/Horizon.cs b/Ryujinx.Core/OsHle/Horizon.cs index e2d38d522..9929102d6 100644 --- a/Ryujinx.Core/OsHle/Horizon.cs +++ b/Ryujinx.Core/OsHle/Horizon.cs @@ -114,25 +114,22 @@ namespace Ryujinx.Core.OsHle public void LoadProgram(string FileName) { + bool IsNro = Path.GetExtension(FileName).ToLower() == ".nro"; + int ProcessId = IdGen.GenerateId(); Process MainProcess = new Process(Ns, Allocator, ProcessId); using (FileStream Input = new FileStream(FileName, FileMode.Open)) { - if (Path.GetExtension(FileName).ToLower() == ".nro") - { - MainProcess.LoadProgram(new Nro(Input)); - } - else - { - MainProcess.LoadProgram(new Nso(Input)); - } + MainProcess.LoadProgram(IsNro + ? (IExecutable)new Nro(Input) + : (IExecutable)new Nso(Input)); } MainProcess.SetEmptyArgs(); MainProcess.InitializeHeap(); - MainProcess.Run(); + MainProcess.Run(IsNro); Processes.TryAdd(ProcessId, MainProcess); } @@ -190,6 +187,7 @@ namespace Ryujinx.Core.OsHle if (SharedMem.TryGetLastVirtualPosition(out long Position)) { Logging.Info($"HID shared memory successfully mapped to {Position:x16}!"); + Ns.Hid.Init(Position); } } diff --git a/Ryujinx.Core/OsHle/MemoryRegions.cs b/Ryujinx.Core/OsHle/MemoryRegions.cs new file mode 100644 index 000000000..e8ededc8f --- /dev/null +++ b/Ryujinx.Core/OsHle/MemoryRegions.cs @@ -0,0 +1,13 @@ +using ChocolArm64.Memory; + +namespace Ryujinx.Core.OsHle +{ + static class MemoryRegions + { + public const long MapRegionAddress = 0x80000000; + public const long MapRegionSize = 0x40000000; + + public const long HeapRegionAddress = MapRegionAddress + MapRegionSize; + public const long HeapRegionSize = 0x40000000; + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs b/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs index 238630992..545883836 100644 --- a/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs +++ b/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs @@ -245,7 +245,7 @@ namespace Ryujinx.Core.OsHle.Objects.Android HNvMap NvMap = GetNvMap(Context, Slot); - if (NvMap.Address < 0 || NvMap.Address + FbSize > AMemoryMgr.AddrSize) + if (FbSize < 0 || NvMap.Address < 0 || NvMap.Address + FbSize > AMemoryMgr.AddrSize) { Logging.Error($"Frame buffer address {NvMap.Address:x16} is invalid!"); diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs index e18c1dafd..6b86a4739 100644 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs +++ b/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs @@ -273,7 +273,16 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv FileStream Stream = new FileStream(FileName, FileMode.Open); - MakeObject(Context, new IFile(Stream, FileName)); + IFile FileInterface = new IFile(Stream, FileName); + + FileInterface.Disposed += RemoveFileInUse; + + lock (OpenPaths) + { + OpenPaths.Add(FileName); + } + + MakeObject(Context, FileInterface); return 0; } @@ -353,7 +362,7 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv lock (OpenPaths) { - FileInterface.Disposed -= RemoveDirectoryInUse; + FileInterface.Disposed -= RemoveFileInUse; OpenPaths.Remove(FileInterface.HostPath); } diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs index 022dc0f9a..3e265ed34 100644 --- a/Ryujinx.Core/OsHle/Process.cs +++ b/Ryujinx.Core/OsHle/Process.cs @@ -86,10 +86,10 @@ namespace Ryujinx.Core.OsHle public void InitializeHeap() { - Memory.Manager.SetHeapAddr((ImageBase + 0x3fffffff) & ~0x3fffffff); + Memory.Manager.SetHeapAddr(MemoryRegions.HeapRegionAddress); } - public bool Run() + public bool Run(bool UseHbAbi = false) { if (Executables.Count == 0) { @@ -109,6 +109,14 @@ namespace Ryujinx.Core.OsHle MainThread = Ns.Os.Handles.GetData(Handle); + if (UseHbAbi) + { + Homebrew Homebrew_ABI = new Homebrew(Memory, Executables[0].ImageEnd, (long)Handle); + + MainThread.Thread.ThreadState.X0 = (ulong)Executables[0].ImageEnd; + MainThread.Thread.ThreadState.X1 = ulong.MaxValue; + } + Scheduler.StartThread(MainThread); return true; @@ -186,13 +194,6 @@ namespace Ryujinx.Core.OsHle Thread.ThreadState.X1 = (ulong)Handle; Thread.ThreadState.X31 = (ulong)StackTop; - if (Executables[0].Extension == Extensions.NRO) - { - Homebrew Homebrew_ABI = new Homebrew(Memory, Executables[0].ImageEnd, (long)Handle); - Thread.ThreadState.X0 = (ulong)Executables[0].ImageEnd; - Thread.ThreadState.X1 = 0xFFFFFFFFFFFFFFFF; - } - Thread.WorkFinished += ThreadFinished; ThreadsByTpidr.TryAdd(Thread.ThreadState.Tpidr, ThreadHnd); diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs index f33d2ac8e..71edfbd69 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs @@ -182,22 +182,22 @@ namespace Ryujinx.Core.OsHle.Svc private ulong GetMapRegionBaseAddr() { - return 0x80000000; + return MemoryRegions.MapRegionAddress; } private ulong GetMapRegionSize() { - return 0x40000000; + return MemoryRegions.MapRegionSize; } private ulong GetHeapRegionBaseAddr() { - return GetMapRegionBaseAddr() + GetMapRegionSize(); + return MemoryRegions.HeapRegionAddress; } private ulong GetHeapRegionSize() { - return 0x40000000; + return MemoryRegions.HeapRegionSize; } private ulong GetTotalMem() diff --git a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs index 6bf17d094..5ae5e2259 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs @@ -3,7 +3,6 @@ using OpenTK.Graphics.OpenGL; using System; using System.Collections.Generic; - namespace Ryujinx.Graphics.Gal.OpenGL { public class OpenGLRenderer : IGalRenderer @@ -29,8 +28,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL private FrameBuffer FbRenderer; - public long FrameBufferPtr { get; set; } - public OpenGLRenderer() { VertexBuffers = new List(); @@ -58,7 +55,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL { ActionsQueue.Dequeue()(); } - } + } public void Render() { diff --git a/Ryujinx/Ui/Program.cs b/Ryujinx/Ui/Program.cs index 7912147ee..b5f8cb976 100644 --- a/Ryujinx/Ui/Program.cs +++ b/Ryujinx/Ui/Program.cs @@ -59,9 +59,7 @@ namespace Ryujinx Screen.Run(60.0); } - Ns.FinalizeAllProcesses(); - - Ns.Dispose(); + Environment.Exit(0); } } }