From 9e8f02b66dabd70cfe6ec425f194119f1cb15542 Mon Sep 17 00:00:00 2001 From: Ac_K Date: Fri, 9 Feb 2018 01:43:22 +0100 Subject: [PATCH 1/7] Add internal Logging support (#3) * Add internal Logging support Add class Logging. Replace all Console.WriteLine() to looks better. Add informations inside Windows Titles. * Revert "Add internal Logging support" This reverts commit 275d363aaf30011f238010572cfdb320bd7b627f. * Add internal Logging support Add Logging Class. Replace all Console.WriteLine() to looks better. Add debug informations of IpcMessage. Add informations inside Windows Titles. * Add internal Logging support2 Add Logging Class. Replace all Console.WriteLine() to looks better. Add debug informations of IpcMessage. Add informations inside Windows Titles. --- GLScreen.cs | 4 +- Program.cs | 13 ++- Ryujinx/Logging.cs | 128 +++++++++++++++++++++++++ Ryujinx/OsHle/Ipc/IpcHandler.cs | 2 + Ryujinx/OsHle/Objects/AudIAudioOut.cs | 16 ++-- Ryujinx/OsHle/Services/ServiceNvDrv.cs | 2 +- Ryujinx/OsHle/Svc/SvcSystem.cs | 2 +- 7 files changed, 150 insertions(+), 17 deletions(-) create mode 100644 Ryujinx/Logging.cs diff --git a/GLScreen.cs b/GLScreen.cs index 3e16f7f1d..982816931 100644 --- a/GLScreen.cs +++ b/GLScreen.cs @@ -351,7 +351,9 @@ void main(void) { protected override void OnRenderFrame(FrameEventArgs e) { GL.Viewport(0, 0, 1280, 720); - + + Title = $"Ryujinx Screen - (Vsync: {VSync} - FPS: {1f / e.Time:0})"; + GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); RenderFb(); diff --git a/Program.cs b/Program.cs index 44dc67c1f..79a4f7071 100644 --- a/Program.cs +++ b/Program.cs @@ -9,6 +9,8 @@ namespace Ryujinx { static void Main(string[] args) { + Console.Title = "Ryujinx Console"; + IGalRenderer Renderer = new OpenGLRenderer(); Switch Ns = new Switch(Renderer); @@ -21,27 +23,30 @@ namespace Ryujinx if (RomFsFiles.Length > 0) { - Console.WriteLine("Loading as cart with RomFS."); + Logging.Info("Loading as cart with RomFS."); + Console.Title += " - Cart (with RomFS) - " + args[0]; Ns.Os.LoadCart(args[0], RomFsFiles[0]); } else { - Console.WriteLine("Loading as cart WITHOUT RomFS."); + Logging.Info("Loading as cart WITHOUT RomFS."); + Console.Title += " - Cart (without RomFS) - " + args[0]; Ns.Os.LoadCart(args[0]); } } else if (File.Exists(args[0])) { - Console.WriteLine("Loading as homebrew."); + Logging.Info("Loading as homebrew."); + Console.Title += " - Homebrew - " + args[0]; Ns.Os.LoadProgram(args[0]); } } else { - Console.WriteLine("Please specify the folder with the NSOs/IStorage or a NSO/NRO."); + Logging.Error("Please specify the folder with the NSOs/IStorage or a NSO/NRO."); } using (GLScreen Screen = new GLScreen(Ns, Renderer)) diff --git a/Ryujinx/Logging.cs b/Ryujinx/Logging.cs new file mode 100644 index 000000000..bdb6ad06a --- /dev/null +++ b/Ryujinx/Logging.cs @@ -0,0 +1,128 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Text; + +namespace Ryujinx +{ + public static class Logging + { + private static Stopwatch ExecutionTime = new Stopwatch(); + private static string LogFileName = "Ryujinx.log"; + + public static bool EnableInfo = true; + public static bool EnableTrace = true; + public static bool EnableDebug = true; + public static bool EnableWarn = true; + public static bool EnableError = true; + public static bool EnableFatal = true; + public static bool EnableLogFile = false; + + static Logging() + { + ExecutionTime.Start(); + + if (File.Exists(LogFileName)) File.Delete(LogFileName); + } + + public static string GetExecutionTime() + { + return ExecutionTime.ElapsedMilliseconds.ToString().PadLeft(8, '0') + "ms"; + } + + private static void LogFile(string Message) + { + if (EnableLogFile) + { + using (StreamWriter Writer = File.AppendText(LogFileName)) + { + Writer.WriteLine(Message); + } + } + } + + public static void Info(string Message) + { + if (EnableInfo) + { + string Text = $"{GetExecutionTime()} | INFO > {Message}"; + + Console.ForegroundColor = ConsoleColor.White; + Console.WriteLine(Text.PadLeft(Text.Length + 1, ' ')); + Console.ResetColor(); + + LogFile(Text); + } + } + + public static void Trace(string Message) + { + if (EnableTrace) + { + string Text = $"{GetExecutionTime()} | TRACE > {Message}"; + + Console.ForegroundColor = ConsoleColor.DarkGray; + Console.WriteLine(Text.PadLeft(Text.Length + 1, ' ')); + Console.ResetColor(); + + LogFile(Text); + } + } + + public static void Debug(string Message) + { + if (EnableDebug) + { + string Text = $"{GetExecutionTime()} | DEBUG > {Message}"; + + Console.ForegroundColor = ConsoleColor.Gray; + Console.WriteLine(Text.PadLeft(Text.Length + 1, ' ')); + Console.ResetColor(); + + LogFile(Text); + } + } + + public static void Warn(string Message) + { + if (EnableWarn) + { + string Text = $"{GetExecutionTime()} | WARN > {Message}"; + + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine(Text.PadLeft(Text.Length + 1, ' ')); + Console.ResetColor(); + + LogFile(Text); + } + } + + public static void Error(string Message) + { + if (EnableError) + { + string Text = $"{GetExecutionTime()} | ERROR > {Message}"; + + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine(Text.PadLeft(Text.Length + 1, ' ')); + Console.ResetColor(); + + LogFile(Text); + } + } + + public static void Fatal(string Message) + { + if (EnableFatal) + { + string Text = $"{GetExecutionTime()} | FATAL > {Message}"; + + Console.ForegroundColor = ConsoleColor.Magenta; + Console.WriteLine(Text.PadLeft(Text.Length + 1, ' ')); + Console.ResetColor(); + + LogFile(Text); + } + } + } +} diff --git a/Ryujinx/OsHle/Ipc/IpcHandler.cs b/Ryujinx/OsHle/Ipc/IpcHandler.cs index 4e57889a4..c8b26dba6 100644 --- a/Ryujinx/OsHle/Ipc/IpcHandler.cs +++ b/Ryujinx/OsHle/Ipc/IpcHandler.cs @@ -262,6 +262,8 @@ namespace Ryujinx.OsHle.Ipc } } + Logging.Debug($"IpcMessage: {DbgServiceName}"); + if (ProcReq != null) { using (MemoryStream ResMS = new MemoryStream()) diff --git a/Ryujinx/OsHle/Objects/AudIAudioOut.cs b/Ryujinx/OsHle/Objects/AudIAudioOut.cs index 965e840d4..c04a23ad1 100644 --- a/Ryujinx/OsHle/Objects/AudIAudioOut.cs +++ b/Ryujinx/OsHle/Objects/AudIAudioOut.cs @@ -22,7 +22,7 @@ namespace Ryujinx.OsHle.Objects //IAudioOut private static AudioOutState State = AudioOutState.Stopped; - private static List KeysQueue = new List(); + private static Queue KeysQueue = new Queue(); //OpenAL private static bool OpenALInstalled = true; @@ -48,9 +48,9 @@ namespace Ryujinx.OsHle.Objects { AudioCtx = new AudioContext(); //Create the audio context } - catch (Exception ex) + catch (Exception) { - Console.WriteLine("OpenAL Error! PS: Install OpenAL Core SDK!"); + Logging.Warning("OpenAL Error! PS: Install OpenAL Core SDK!"); OpenALInstalled = false; } @@ -82,7 +82,7 @@ namespace Ryujinx.OsHle.Objects { long BufferId = Context.RequestData.ReadInt64(); - KeysQueue.Insert(0, BufferId); + KeysQueue.Enqueue(BufferId); byte[] AudioOutBuffer = AMemoryHelper.ReadBytes(Context.Memory, Context.Request.SendBuff[0].Position, 0x28); using (MemoryStream MS = new MemoryStream(AudioOutBuffer)) @@ -125,13 +125,9 @@ namespace Ryujinx.OsHle.Objects { long TempKey = 0; - if (KeysQueue.Count > 0) - { - TempKey = KeysQueue[KeysQueue.Count - 1]; - KeysQueue.Remove(KeysQueue[KeysQueue.Count - 1]); - } + if (KeysQueue.Count > 0) TempKey = KeysQueue.Dequeue(); - AMemoryHelper.WriteBytes(Context.Memory, Context.Request.ReceiveBuff[0].Position, System.BitConverter.GetBytes(TempKey)); + AMemoryHelper.WriteBytes(Context.Memory, Context.Request.ReceiveBuff[0].Position, BitConverter.GetBytes(TempKey)); Context.ResponseData.Write((int)TempKey); diff --git a/Ryujinx/OsHle/Services/ServiceNvDrv.cs b/Ryujinx/OsHle/Services/ServiceNvDrv.cs index f410e1ab0..405eace2b 100644 --- a/Ryujinx/OsHle/Services/ServiceNvDrv.cs +++ b/Ryujinx/OsHle/Services/ServiceNvDrv.cs @@ -563,7 +563,7 @@ namespace Ryujinx.OsHle.Services NvMap.Kind = Kind; } - Console.WriteLine($"NvMapIocAlloc at {NvMap.Address:x16}"); + Logging.Debug($"NvMapIocAlloc at {NvMap.Address:x16}"); return 0; } diff --git a/Ryujinx/OsHle/Svc/SvcSystem.cs b/Ryujinx/OsHle/Svc/SvcSystem.cs index fa39f5181..3c541381b 100644 --- a/Ryujinx/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx/OsHle/Svc/SvcSystem.cs @@ -121,7 +121,7 @@ namespace Ryujinx.OsHle.Svc string Str = AMemoryHelper.ReadAsciiString(Memory, Position, (int)Size); - Console.WriteLine($"SvcOutputDebugString: {Str}"); + Logging.Info($"SvcOutputDebugString: {Str}"); Registers.X0 = (int)SvcResult.Success; } From aba75186e92f2dd0dd459642f58edf159ab51f86 Mon Sep 17 00:00:00 2001 From: Ac_K Date: Fri, 9 Feb 2018 01:51:13 +0100 Subject: [PATCH 2/7] Copy Paste mistake (#4) Logging.Warn instead of Logging.Warning --- Ryujinx/OsHle/Objects/AudIAudioOut.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ryujinx/OsHle/Objects/AudIAudioOut.cs b/Ryujinx/OsHle/Objects/AudIAudioOut.cs index c04a23ad1..319d17fe7 100644 --- a/Ryujinx/OsHle/Objects/AudIAudioOut.cs +++ b/Ryujinx/OsHle/Objects/AudIAudioOut.cs @@ -50,7 +50,7 @@ namespace Ryujinx.OsHle.Objects } catch (Exception) { - Logging.Warning("OpenAL Error! PS: Install OpenAL Core SDK!"); + Logging.Warn("OpenAL Error! PS: Install OpenAL Core SDK!"); OpenALInstalled = false; } From 5ecfb5c6576a473870bbc8e25ae34ccf916e5a0a Mon Sep 17 00:00:00 2001 From: Ac_K Date: Fri, 9 Feb 2018 03:47:32 +0100 Subject: [PATCH 3/7] Add internal Config support (#5) * Add internal Logging support Add class Logging. Replace all Console.WriteLine() to looks better. Add informations inside Windows Titles. * Revert "Add internal Logging support" This reverts commit 275d363aaf30011f238010572cfdb320bd7b627f. * Add internal Logging support Add Logging Class. Replace all Console.WriteLine() to looks better. Add debug informations of IpcMessage. Add informations inside Windows Titles. * Add internal Logging support2 Add Logging Class. Replace all Console.WriteLine() to looks better. Add debug informations of IpcMessage. Add informations inside Windows Titles. * Add internal Config support Add Config Class. Add Ryujinx.conf file (Ini file). Use the Config Class inside Logging. * Add internal Config support Add Config Class. Add Ryujinx.conf file (Ini file). Use the Config Class inside Logging. --- Program.cs | 2 ++ Ryujinx.conf | 20 +++++++++++++++++ Ryujinx/Config.cs | 54 ++++++++++++++++++++++++++++++++++++++++++++++ Ryujinx/Logging.cs | 14 ++++++------ 4 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 Ryujinx.conf create mode 100644 Ryujinx/Config.cs diff --git a/Program.cs b/Program.cs index 79a4f7071..5569cd49d 100644 --- a/Program.cs +++ b/Program.cs @@ -9,6 +9,8 @@ namespace Ryujinx { static void Main(string[] args) { + Config.Read(); + Console.Title = "Ryujinx Console"; IGalRenderer Renderer = new OpenGLRenderer(); diff --git a/Ryujinx.conf b/Ryujinx.conf new file mode 100644 index 000000000..590318fe7 --- /dev/null +++ b/Ryujinx.conf @@ -0,0 +1,20 @@ +#Enabled print informations logs +Logging_Enable_Info = true + +#Enabled print trace logs +Logging_Enable_Trace = true + +#Enabled print debug logs +Logging_Enable_Debug = true + +#Enabled print warning logs +Logging_Enable_Warn = true + +#Enabled print error logs +Logging_Enable_Error = true + +#Enabled print fatal logs +Logging_Enable_Fatal = true + +#Saved logs into Ryujinx.log +Logging_Enable_LogFile = false diff --git a/Ryujinx/Config.cs b/Ryujinx/Config.cs new file mode 100644 index 000000000..2e4e56953 --- /dev/null +++ b/Ryujinx/Config.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Ryujinx +{ + public static class Config + { + public static bool LoggingEnableInfo { get; private set; } + public static bool LoggingEnableTrace { get; private set; } + public static bool LoggingEnableDebug { get; private set; } + public static bool LoggingEnableWarn { get; private set; } + public static bool LoggingEnableError { get; private set; } + public static bool LoggingEnableFatal { get; private set; } + public static bool LoggingEnableLogFile { get; private set; } + + public static void Read() + { + IniParser Parser = new IniParser("Ryujinx.conf"); + + LoggingEnableInfo = Convert.ToBoolean(Parser.Value("Logging_Enable_Info")); + LoggingEnableTrace = Convert.ToBoolean(Parser.Value("Logging_Enable_Trace")); + LoggingEnableDebug = Convert.ToBoolean(Parser.Value("Logging_Enable_Debug")); + LoggingEnableWarn = Convert.ToBoolean(Parser.Value("Logging_Enable_Warn")); + LoggingEnableError = Convert.ToBoolean(Parser.Value("Logging_Enable_Error")); + LoggingEnableFatal = Convert.ToBoolean(Parser.Value("Logging_Enable_Fatal")); + LoggingEnableLogFile = Convert.ToBoolean(Parser.Value("Logging_Enable_LogFile")); + } + } + + // https://stackoverflow.com/a/37772571 + public class IniParser + { + private Dictionary Values; + + public IniParser(string Path) + { + Values = File.ReadLines(Path) + .Where(Line => (!String.IsNullOrWhiteSpace(Line) && !Line.StartsWith("#"))) + .Select(Line => Line.Split(new char[] { '=' }, 2, 0)) + .ToDictionary(Parts => Parts[0].Trim(), Parts => Parts.Length > 1 ? Parts[1].Trim() : null); + } + + public string Value(string Name, string Value = null) + { + if (Values != null && Values.ContainsKey(Name)) + { + return Values[Name]; + } + return Value; + } + } +} diff --git a/Ryujinx/Logging.cs b/Ryujinx/Logging.cs index bdb6ad06a..f575549eb 100644 --- a/Ryujinx/Logging.cs +++ b/Ryujinx/Logging.cs @@ -10,13 +10,13 @@ namespace Ryujinx private static Stopwatch ExecutionTime = new Stopwatch(); private static string LogFileName = "Ryujinx.log"; - public static bool EnableInfo = true; - public static bool EnableTrace = true; - public static bool EnableDebug = true; - public static bool EnableWarn = true; - public static bool EnableError = true; - public static bool EnableFatal = true; - public static bool EnableLogFile = false; + public static bool EnableInfo = Config.LoggingEnableInfo; + public static bool EnableTrace = Config.LoggingEnableTrace; + public static bool EnableDebug = Config.LoggingEnableDebug; + public static bool EnableWarn = Config.LoggingEnableWarn; + public static bool EnableError = Config.LoggingEnableError; + public static bool EnableFatal = Config.LoggingEnableFatal; + public static bool EnableLogFile = Config.LoggingEnableLogFile; static Logging() { From ebbccfcdbfe2927e1cfdb2fd6abc0502c9a52aed Mon Sep 17 00:00:00 2001 From: Ac_K Date: Fri, 9 Feb 2018 04:23:20 +0100 Subject: [PATCH 4/7] config bugfix (#6) Include Ryujinx.conf file to the build folder. Fix the Ryujinx.conf filepath. --- Ryujinx.csproj | 5 +++++ Ryujinx/Config.cs | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Ryujinx.csproj b/Ryujinx.csproj index 2c25afc0f..9ad696d89 100644 --- a/Ryujinx.csproj +++ b/Ryujinx.csproj @@ -9,4 +9,9 @@ + + + PreserveNewest + + \ No newline at end of file diff --git a/Ryujinx/Config.cs b/Ryujinx/Config.cs index 2e4e56953..c27060d2c 100644 --- a/Ryujinx/Config.cs +++ b/Ryujinx/Config.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; namespace Ryujinx { @@ -17,7 +18,7 @@ namespace Ryujinx public static void Read() { - IniParser Parser = new IniParser("Ryujinx.conf"); + IniParser Parser = new IniParser(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Ryujinx.conf")); LoggingEnableInfo = Convert.ToBoolean(Parser.Value("Logging_Enable_Info")); LoggingEnableTrace = Convert.ToBoolean(Parser.Value("Logging_Enable_Trace")); From 6a3aa6cd88cfb01436f036297d08cfe815b52469 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 9 Feb 2018 00:26:20 -0300 Subject: [PATCH 5/7] Add FVCTZS (fixed point variant) and LD1 (single structure variant) instructions --- Ryujinx/Cpu/AOpCodeTable.cs | 11 +- Ryujinx/Cpu/AOptimizations.cs | 4 + ...CodeSimdMemMult.cs => AOpCodeSimdMemMs.cs} | 4 +- Ryujinx/Cpu/Decoder/AOpCodeSimdMemSs.cs | 104 ++++++++++++++++++ Ryujinx/Cpu/Instruction/AInstEmitSimd.cs | 98 ++++++++++++++++- Ryujinx/Cpu/Instruction/ASoftFallback.cs | 14 +-- Ryujinx/Cpu/Memory/AMemory.cs | 53 ++++++++- Ryujinx/Cpu/Memory/AMemoryMgr.cs | 9 +- Ryujinx/Loaders/Executable.cs | 4 +- 9 files changed, 279 insertions(+), 22 deletions(-) create mode 100644 Ryujinx/Cpu/AOptimizations.cs rename Ryujinx/Cpu/Decoder/{AOpCodeSimdMemMult.cs => AOpCodeSimdMemMs.cs} (91%) create mode 100644 Ryujinx/Cpu/Decoder/AOpCodeSimdMemSs.cs diff --git a/Ryujinx/Cpu/AOpCodeTable.cs b/Ryujinx/Cpu/AOpCodeTable.cs index a7deb2c7f..bf1ceec7d 100644 --- a/Ryujinx/Cpu/AOpCodeTable.cs +++ b/Ryujinx/Cpu/AOpCodeTable.cs @@ -153,6 +153,7 @@ namespace ChocolArm64 Set("x0011110xx101000000000xxxxxxxxxx", AInstEmit.Fcvtps_S, typeof(AOpCodeSimdCvt)); Set("x0011110xx111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_S, typeof(AOpCodeSimdCvt)); Set("0x0011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimd)); + Set("0x0011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzs_V_Fix, typeof(AOpCodeSimdShImm)); Set("x0011110xx111001000000xxxxxxxxxx", AInstEmit.Fcvtzu_S, typeof(AOpCodeSimdCvt)); Set("0x1011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimd)); Set("0x1011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzu_V_Fix, typeof(AOpCodeSimdShImm)); @@ -186,8 +187,10 @@ namespace ChocolArm64 Set("0x0011101x1xxxxx110101xxxxxxxxxx", AInstEmit.Fsub_V, typeof(AOpCodeSimdReg)); Set("01001110000xxxxx000111xxxxxxxxxx", AInstEmit.Ins_Gp, typeof(AOpCodeSimdIns)); Set("01101110000xxxxx0xxxx1xxxxxxxxxx", AInstEmit.Ins_V, typeof(AOpCodeSimdIns)); - Set("0x00110001000000xxxxxxxxxxxxxxxx", AInstEmit.Ld__V, typeof(AOpCodeSimdMemMult)); - Set("0x001100110xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ld__V, typeof(AOpCodeSimdMemMult)); + Set("0x00110001000000xxxxxxxxxxxxxxxx", AInstEmit.Ld__Vms, typeof(AOpCodeSimdMemMs)); + Set("0x001100110xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ld__Vms, typeof(AOpCodeSimdMemMs)); + Set("0x00110101000000xx0xxxxxxxxxxxxx", AInstEmit.Ld__Vss, typeof(AOpCodeSimdMemSs)); + Set("0x001101110xxxxxxx0xxxxxxxxxxxxx", AInstEmit.Ld__Vss, typeof(AOpCodeSimdMemSs)); Set("xx10110xx1xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldp, typeof(AOpCodeSimdMemPair)); Set("xx111100x10xxxxxxxxx00xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm)); Set("xx111100x10xxxxxxxxx01xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm)); @@ -218,8 +221,8 @@ namespace ChocolArm64 Set("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm)); Set("010111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm)); Set("0x0011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm)); - Set("0x00110000000000xxxxxxxxxxxxxxxx", AInstEmit.St__V, typeof(AOpCodeSimdMemMult)); - Set("0x001100100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.St__V, typeof(AOpCodeSimdMemMult)); + Set("0x00110000000000xxxxxxxxxxxxxxxx", AInstEmit.St__V, typeof(AOpCodeSimdMemMs)); + Set("0x001100100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.St__V, typeof(AOpCodeSimdMemMs)); Set("xx10110xx0xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Stp, typeof(AOpCodeSimdMemPair)); Set("xx111100x00xxxxxxxxx00xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm)); Set("xx111100x00xxxxxxxxx01xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm)); diff --git a/Ryujinx/Cpu/AOptimizations.cs b/Ryujinx/Cpu/AOptimizations.cs new file mode 100644 index 000000000..cbfd1ce51 --- /dev/null +++ b/Ryujinx/Cpu/AOptimizations.cs @@ -0,0 +1,4 @@ +public static class AOptimizations +{ + +} \ No newline at end of file diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdMemMult.cs b/Ryujinx/Cpu/Decoder/AOpCodeSimdMemMs.cs similarity index 91% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdMemMult.cs rename to Ryujinx/Cpu/Decoder/AOpCodeSimdMemMs.cs index 9731c7e74..0e8480b03 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeSimdMemMult.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeSimdMemMs.cs @@ -3,7 +3,7 @@ using ChocolArm64.State; namespace ChocolArm64.Decoder { - class AOpCodeSimdMemMult : AOpCode, IAOpCodeSimd + class AOpCodeSimdMemMs : AOpCode, IAOpCodeSimd { public int Rt { get; private set; } public int Rn { get; private set; } @@ -14,7 +14,7 @@ namespace ChocolArm64.Decoder public int Elems { get; private set; } public bool WBack { get; private set; } - public AOpCodeSimdMemMult(AInst Inst, long Position, int OpCode) : base(Inst, Position) + public AOpCodeSimdMemMs(AInst Inst, long Position, int OpCode) : base(Inst, Position) { switch ((OpCode >> 12) & 0xf) { diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdMemSs.cs b/Ryujinx/Cpu/Decoder/AOpCodeSimdMemSs.cs new file mode 100644 index 000000000..c2917dfc8 --- /dev/null +++ b/Ryujinx/Cpu/Decoder/AOpCodeSimdMemSs.cs @@ -0,0 +1,104 @@ +using ChocolArm64.Instruction; +using ChocolArm64.State; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdMemSs : AOpCode, IAOpCodeSimd + { + public int Rt { get; private set; } + public int Rn { get; private set; } + public int Size { get; private set; } + public int Rm { get; private set; } + public int SElems { get; private set; } + public int Index { get; private set; } + public bool Replicate { get; private set; } + public bool WBack { get; private set; } + + public AOpCodeSimdMemSs(AInst Inst, long Position, int OpCode) : base(Inst, Position) + { + int Size = (OpCode >> 10) & 3; + int S = (OpCode >> 12) & 1; + int SElems = (OpCode >> 12) & 2; + int Scale = (OpCode >> 14) & 3; + int L = (OpCode >> 22) & 1; + int Q = (OpCode >> 30) & 1; + + SElems |= (OpCode >> 21) & 1; + + SElems++; + + int Index = (Q << 3) | (S << 2) | Size; + + switch (Scale) + { + case 0: Index >>= 0; break; + + case 1: + { + if ((Index & 1) != 0) + { + Inst = AInst.Undefined; + + return; + } + + Index >>= 1; + + break; + } + + case 2: + { + if ((Index & 2) != 0 || + ((Index & 1) != 0 && S != 0)) + { + Inst = AInst.Undefined; + + return; + } + + if ((Index & 1) != 0) + { + Index >>= 3; + } + else + { + Index >>= 2; + + Scale = 3; + } + + break; + } + + case 3: + { + if (L == 0 || S != 0) + { + Inst = AInst.Undefined; + + return; + } + + Scale = Size; + + Replicate = true; + + break; + } + } + + this.SElems = SElems; + this.Size = Scale; + + Rt = (OpCode >> 0) & 0x1f; + Rn = (OpCode >> 5) & 0x1f; + Rm = (OpCode >> 16) & 0x1f; + WBack = ((OpCode >> 23) & 0x1) != 0; + + RegisterSize = Q != 0 + ? ARegisterSize.SIMD128 + : ARegisterSize.SIMD64; + } + } +} \ No newline at end of file diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs index 8d4ade3a1..9ba75bc85 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs @@ -122,6 +122,7 @@ namespace ChocolArm64.Instruction AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; Context.EmitLdvec(Op.Rn); + Context.EmitLdc_I4(0); Context.EmitLdc_I4(Op.SizeF); ASoftFallback.EmitCall(Context, @@ -131,6 +132,21 @@ namespace ChocolArm64.Instruction Context.EmitStvec(Op.Rd); } + public static void Fcvtzs_V_Fix(AILEmitterCtx Context) + { + AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; + + Context.EmitLdvec(Op.Rn); + Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm); + Context.EmitLdc_I4(Op.Size - 2); + + ASoftFallback.EmitCall(Context, + nameof(ASoftFallback.Fcvtzs_V64), + nameof(ASoftFallback.Fcvtzs_V128)); + + Context.EmitStvec(Op.Rd); + } + public static void Fcvtzu_V(AILEmitterCtx Context) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; @@ -283,7 +299,8 @@ namespace ChocolArm64.Instruction Context.EmitStvec(Op.Rd); } - public static void Ld__V(AILEmitterCtx Context) => EmitSimdMultLdSt(Context, IsLoad: true); + public static void Ld__Vms(AILEmitterCtx Context) => EmitSimdMemMs(Context, IsLoad: true); + public static void Ld__Vss(AILEmitterCtx Context) => EmitSimdMemSs(Context, IsLoad: true); public static void Mla_V(AILEmitterCtx Context) => EmitVectorMla(Context); @@ -391,7 +408,7 @@ namespace ChocolArm64.Instruction EmitVectorImmBinarySx(Context, OpCodes.Shr, (8 << (Op.Size + 1)) - Op.Imm); } - public static void St__V(AILEmitterCtx Context) => EmitSimdMultLdSt(Context, IsLoad: false); + public static void St__V(AILEmitterCtx Context) => EmitSimdMemMs(Context, IsLoad: false); public static void Sub_V(AILEmitterCtx Context) => EmitVectorBinaryZx(Context, OpCodes.Sub); @@ -571,9 +588,9 @@ namespace ChocolArm64.Instruction Context.EmitStvec(Op.Rd); } - private static void EmitSimdMultLdSt(AILEmitterCtx Context, bool IsLoad) + private static void EmitSimdMemMs(AILEmitterCtx Context, bool IsLoad) { - AOpCodeSimdMemMult Op = (AOpCodeSimdMemMult)Context.CurrOp; + AOpCodeSimdMemMs Op = (AOpCodeSimdMemMs)Context.CurrOp; int Offset = 0; @@ -644,6 +661,79 @@ namespace ChocolArm64.Instruction } } + private static void EmitSimdMemSs(AILEmitterCtx Context, bool IsLoad) + { + AOpCodeSimdMemSs Op = (AOpCodeSimdMemSs)Context.CurrOp; + + //TODO: Replicate mode. + + int Offset = 0; + + for (int SElem = 0; SElem < Op.SElems; SElem++) + { + int Rt = (Op.Rt + SElem) & 0x1f; + + if (IsLoad) + { + Context.EmitLdvec(Rt); + Context.EmitLdc_I4(Op.Index); + Context.EmitLdc_I4(Op.Size); + Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); + Context.EmitLdint(Op.Rn); + Context.EmitLdc_I8(Offset); + + Context.Emit(OpCodes.Add); + + EmitReadZxCall(Context, Op.Size); + + ASoftFallback.EmitCall(Context, nameof(ASoftFallback.InsertVec)); + + Context.EmitStvec(Rt); + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Rt); + } + } + else + { + Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); + Context.EmitLdint(Op.Rn); + Context.EmitLdc_I8(Offset); + + Context.Emit(OpCodes.Add); + + Context.EmitLdvec(Rt); + Context.EmitLdc_I4(Op.Index); + Context.EmitLdc_I4(Op.Size); + + ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ExtractVec)); + + EmitWriteCall(Context, Op.Size); + } + + Offset += 1 << Op.Size; + } + + if (Op.WBack) + { + Context.EmitLdint(Op.Rn); + + if (Op.Rm != ARegisters.ZRIndex) + { + Context.EmitLdint(Op.Rm); + } + else + { + Context.EmitLdc_I8(Offset); + } + + Context.Emit(OpCodes.Add); + + Context.EmitStint(Op.Rn); + } + } + private static void EmitVectorAddv(AILEmitterCtx Context) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; diff --git a/Ryujinx/Cpu/Instruction/ASoftFallback.cs b/Ryujinx/Cpu/Instruction/ASoftFallback.cs index 0d5271320..caf3cfca7 100644 --- a/Ryujinx/Cpu/Instruction/ASoftFallback.cs +++ b/Ryujinx/Cpu/Instruction/ASoftFallback.cs @@ -405,17 +405,17 @@ namespace ChocolArm64.Instruction return Res; } - public static AVec Fcvtzs_V64(AVec Vector, int Size) + public static AVec Fcvtzs_V64(AVec Vector, int FBits, int Size) { - return Fcvtzs_V(Vector, Size, 2); + return Fcvtzs_V(Vector, FBits, Size, 2); } - public static AVec Fcvtzs_V128(AVec Vector, int Size) + public static AVec Fcvtzs_V128(AVec Vector, int FBits, int Size) { - return Fcvtzs_V(Vector, Size, 4); + return Fcvtzs_V(Vector, FBits, Size, 4); } - private static AVec Fcvtzs_V(AVec Vector, int Size, int Bytes) + private static AVec Fcvtzs_V(AVec Vector, int FBits, int Size, int Bytes) { AVec Res = new AVec(); @@ -427,7 +427,7 @@ namespace ChocolArm64.Instruction { float Value = Vector.ExtractSingle(Index); - Res = InsertSVec(Res, Index, Size + 2, SatSingleToInt32(Value)); + Res = InsertSVec(Res, Index, Size + 2, SatSingleToInt32(Value, FBits)); } } else @@ -436,7 +436,7 @@ namespace ChocolArm64.Instruction { double Value = Vector.ExtractDouble(Index); - Res = InsertSVec(Res, Index, Size + 2, SatDoubleToInt64(Value)); + Res = InsertSVec(Res, Index, Size + 2, SatDoubleToInt64(Value, FBits)); } } diff --git a/Ryujinx/Cpu/Memory/AMemory.cs b/Ryujinx/Cpu/Memory/AMemory.cs index 8159b341e..7952186d5 100644 --- a/Ryujinx/Cpu/Memory/AMemory.cs +++ b/Ryujinx/Cpu/Memory/AMemory.cs @@ -1,3 +1,4 @@ +using ChocolArm64.Exceptions; using ChocolArm64.State; using System; using System.Collections.Generic; @@ -119,26 +120,46 @@ namespace ChocolArm64.Memory public byte ReadByte(long Position) { +#if DEBUG + EnsureAccessIsValid(Position, AMemoryPerm.Read); +#endif + return *((byte*)(RamPtr + (uint)Position)); } public ushort ReadUInt16(long Position) { +#if DEBUG + EnsureAccessIsValid(Position, AMemoryPerm.Read); +#endif + return *((ushort*)(RamPtr + (uint)Position)); } public uint ReadUInt32(long Position) { +#if DEBUG + EnsureAccessIsValid(Position, AMemoryPerm.Read); +#endif + return *((uint*)(RamPtr + (uint)Position)); } public ulong ReadUInt64(long Position) { +#if DEBUG + EnsureAccessIsValid(Position, AMemoryPerm.Read); +#endif + return *((ulong*)(RamPtr + (uint)Position)); } public AVec ReadVector128(long Position) { +#if DEBUG + EnsureAccessIsValid(Position, AMemoryPerm.Read); +#endif + return new AVec() { X0 = ReadUInt64(Position + 0), @@ -153,33 +174,61 @@ namespace ChocolArm64.Memory public void WriteByte(long Position, byte Value) { +#if DEBUG + EnsureAccessIsValid(Position, AMemoryPerm.Write); +#endif + *((byte*)(RamPtr + (uint)Position)) = Value; } public void WriteUInt16(long Position, ushort Value) { +#if DEBUG + EnsureAccessIsValid(Position, AMemoryPerm.Write); +#endif + *((ushort*)(RamPtr + (uint)Position)) = Value; } public void WriteUInt32(long Position, uint Value) { +#if DEBUG + EnsureAccessIsValid(Position, AMemoryPerm.Write); +#endif + *((uint*)(RamPtr + (uint)Position)) = Value; } public void WriteUInt64(long Position, ulong Value) { +#if DEBUG + EnsureAccessIsValid(Position, AMemoryPerm.Write); +#endif + *((ulong*)(RamPtr + (uint)Position)) = Value; } public void WriteVector128(long Position, AVec Value) { +#if DEBUG + EnsureAccessIsValid(Position, AMemoryPerm.Write); +#endif + WriteUInt64(Position + 0, Value.X0); WriteUInt64(Position + 8, Value.X1); } - private bool IsPageCrossed(long Position, int Size) + private void EnsureAccessIsValid(long Position, AMemoryPerm Perm) { - return (Position & AMemoryMgr.PageMask) + Size > AMemoryMgr.PageSize; + if (!Manager.IsMapped(Position)) + { + throw new VmmPageFaultException(Position); + } + + if (!Manager.HasPermission(Position, Perm)) + { + throw new VmmAccessViolationException(Position, Perm); + } } } } \ No newline at end of file diff --git a/Ryujinx/Cpu/Memory/AMemoryMgr.cs b/Ryujinx/Cpu/Memory/AMemoryMgr.cs index 0c2c5a50b..cd983e78b 100644 --- a/Ryujinx/Cpu/Memory/AMemoryMgr.cs +++ b/Ryujinx/Cpu/Memory/AMemoryMgr.cs @@ -163,7 +163,7 @@ namespace ChocolArm64.Memory { while (Size > 0) { - if (!HasPTEntry(Position)) + if (!IsMapped(Position)) { long PhysPos = Allocator.Alloc(PageSize); @@ -254,8 +254,13 @@ namespace ChocolArm64.Memory return new AMemoryMapInfo(Start, Size, BaseEntry.Type, BaseEntry.Perm); } + public bool HasPermission(long Position, AMemoryPerm Perm) + { + return GetPTEntry(Position).Perm.HasFlag(Perm); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool HasPTEntry(long Position) + public bool IsMapped(long Position) { if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0) { diff --git a/Ryujinx/Loaders/Executable.cs b/Ryujinx/Loaders/Executable.cs index 785a8c723..650436589 100644 --- a/Ryujinx/Loaders/Executable.cs +++ b/Ryujinx/Loaders/Executable.cs @@ -73,12 +73,14 @@ namespace Ryujinx.Loaders MemoryType Type, AMemoryPerm Perm) { - Memory.Manager.MapPhys(Position, Data.Count, (int)Type, Perm); + Memory.Manager.MapPhys(Position, Data.Count, (int)Type, AMemoryPerm.Write); for (int Index = 0; Index < Data.Count; Index++) { Memory.WriteByte(Position + Index, Data[Index]); } + + Memory.Manager.Reprotect(Position, Data.Count, Perm); } private void MapBss(long Position, long Size) From 12e263f8b279c61dfc61e0a3081dc89ad91e711a Mon Sep 17 00:00:00 2001 From: Ac_K Date: Fri, 9 Feb 2018 20:39:50 +0100 Subject: [PATCH 6/7] Logging Improvements (#7) * Logging Improvements Add Trace functions to SVC. Add function to get the function name who called. --- Ryujinx/Logging.cs | 16 +++++++++++----- Ryujinx/OsHle/Svc/SvcHandler.cs | 2 ++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Ryujinx/Logging.cs b/Ryujinx/Logging.cs index f575549eb..e96fd9578 100644 --- a/Ryujinx/Logging.cs +++ b/Ryujinx/Logging.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.IO; +using System.Reflection; using System.Text; namespace Ryujinx @@ -30,6 +31,11 @@ namespace Ryujinx return ExecutionTime.ElapsedMilliseconds.ToString().PadLeft(8, '0') + "ms"; } + private static string WhoCalledMe() + { + return new StackTrace().GetFrame(2).GetMethod().Name; + } + private static void LogFile(string Message) { if (EnableLogFile) @@ -59,7 +65,7 @@ namespace Ryujinx { if (EnableTrace) { - string Text = $"{GetExecutionTime()} | TRACE > {Message}"; + string Text = $"{GetExecutionTime()} | TRACE > {WhoCalledMe()} - {Message}"; Console.ForegroundColor = ConsoleColor.DarkGray; Console.WriteLine(Text.PadLeft(Text.Length + 1, ' ')); @@ -73,7 +79,7 @@ namespace Ryujinx { if (EnableDebug) { - string Text = $"{GetExecutionTime()} | DEBUG > {Message}"; + string Text = $"{GetExecutionTime()} | DEBUG > {WhoCalledMe()} - {Message}"; Console.ForegroundColor = ConsoleColor.Gray; Console.WriteLine(Text.PadLeft(Text.Length + 1, ' ')); @@ -87,7 +93,7 @@ namespace Ryujinx { if (EnableWarn) { - string Text = $"{GetExecutionTime()} | WARN > {Message}"; + string Text = $"{GetExecutionTime()} | WARN > {WhoCalledMe()} - {Message}"; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine(Text.PadLeft(Text.Length + 1, ' ')); @@ -101,7 +107,7 @@ namespace Ryujinx { if (EnableError) { - string Text = $"{GetExecutionTime()} | ERROR > {Message}"; + string Text = $"{GetExecutionTime()} | ERROR > {WhoCalledMe()} - {Message}"; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(Text.PadLeft(Text.Length + 1, ' ')); @@ -115,7 +121,7 @@ namespace Ryujinx { if (EnableFatal) { - string Text = $"{GetExecutionTime()} | FATAL > {Message}"; + string Text = $"{GetExecutionTime()} | FATAL > {WhoCalledMe()} - {Message}"; Console.ForegroundColor = ConsoleColor.Magenta; Console.WriteLine(Text.PadLeft(Text.Length + 1, ' ')); diff --git a/Ryujinx/OsHle/Svc/SvcHandler.cs b/Ryujinx/OsHle/Svc/SvcHandler.cs index 937c341e5..9aea2dedb 100644 --- a/Ryujinx/OsHle/Svc/SvcHandler.cs +++ b/Ryujinx/OsHle/Svc/SvcHandler.cs @@ -69,7 +69,9 @@ namespace Ryujinx.OsHle.Svc if (SvcFuncs.TryGetValue(e.Id, out SvcFunc Func)) { + Logging.Trace($"{Func.Method.Name} called."); Func(Ns, Registers, Memory); + Logging.Trace($"{Func.Method.Name} ended."); } else { From ccc9ce1908b383e4de506a5c1575436b0df7d46c Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 9 Feb 2018 17:14:47 -0300 Subject: [PATCH 7/7] Move a few more SIMD instructions to emit CIL directly instead of a method call --- Ryujinx/Cpu/AOpCodeTable.cs | 10 +- Ryujinx/Cpu/Decoder/AOpCodeSimdShImm.cs | 16 +- Ryujinx/Cpu/Instruction/AInstEmitSimd.cs | 265 ++++++++++++++--------- Ryujinx/Cpu/Instruction/ASoftFallback.cs | 229 +++----------------- Ryujinx/Cpu/Memory/AMemoryMgr.cs | 2 - Ryujinx/Logging.cs | 2 - Ryujinx/OsHle/Objects/AudIAudioOut.cs | 7 +- 7 files changed, 207 insertions(+), 324 deletions(-) diff --git a/Ryujinx/Cpu/AOpCodeTable.cs b/Ryujinx/Cpu/AOpCodeTable.cs index bf1ceec7d..14c249950 100644 --- a/Ryujinx/Cpu/AOpCodeTable.cs +++ b/Ryujinx/Cpu/AOpCodeTable.cs @@ -152,13 +152,13 @@ namespace ChocolArm64 Set("x0011110xx110000000000xxxxxxxxxx", AInstEmit.Fcvtms_S, typeof(AOpCodeSimdCvt)); Set("x0011110xx101000000000xxxxxxxxxx", AInstEmit.Fcvtps_S, typeof(AOpCodeSimdCvt)); Set("x0011110xx111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_S, typeof(AOpCodeSimdCvt)); - Set("0x0011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimd)); - Set("0x0011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzs_V_Fix, typeof(AOpCodeSimdShImm)); - Set("x0011110xx111001000000xxxxxxxxxx", AInstEmit.Fcvtzu_S, typeof(AOpCodeSimdCvt)); - Set("0x1011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimd)); - Set("0x1011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzu_V_Fix, typeof(AOpCodeSimdShImm)); Set("x0011110xx011000xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzs_Fix, typeof(AOpCodeSimdCvt)); + Set("0x0011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimd)); + Set("0x0011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimdShImm)); + Set("x0011110xx111001000000xxxxxxxxxx", AInstEmit.Fcvtzu_S, typeof(AOpCodeSimdCvt)); Set("x0011110xx011001xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzu_Fix, typeof(AOpCodeSimdCvt)); + Set("0x1011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimd)); + Set("0x1011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimdShImm)); Set("00011110xx1xxxxx000110xxxxxxxxxx", AInstEmit.Fdiv_S, typeof(AOpCodeSimdReg)); Set("00011111xx0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Fmadd_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx010010xxxxxxxxxx", AInstEmit.Fmax_S, typeof(AOpCodeSimdReg)); diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdShImm.cs b/Ryujinx/Cpu/Decoder/AOpCodeSimdShImm.cs index a677e579b..6c8398817 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeSimdShImm.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeSimdShImm.cs @@ -1,26 +1,16 @@ using ChocolArm64.Instruction; -using ChocolArm64.State; namespace ChocolArm64.Decoder { - class AOpCodeSimdShImm : AOpCode, IAOpCodeSimd + class AOpCodeSimdShImm : AOpCodeSimd { - public int Rd { get; private set; } - public int Rn { get; private set; } - public int Imm { get; private set; } - public int Size { get; private set; } + public int Imm { get; private set; } - public AOpCodeSimdShImm(AInst Inst, long Position, int OpCode) : base(Inst, Position) + public AOpCodeSimdShImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) { - Rd = (OpCode >> 0) & 0x1f; - Rn = (OpCode >> 5) & 0x1f; Imm = (OpCode >> 16) & 0x7f; Size = ABitUtils.HighestBitSet32(Imm >> 3); - - RegisterSize = ((OpCode >> 30) & 1) != 0 - ? ARegisterSize.SIMD128 - : ARegisterSize.SIMD64; } } } \ No newline at end of file diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs index 9ba75bc85..75c308c35 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitSimd.cs @@ -102,80 +102,10 @@ namespace ChocolArm64.Instruction public static void Eor_V(AILEmitterCtx Context) => EmitVectorBinaryZx(Context, OpCodes.Xor); - public static void Fadd_V(AILEmitterCtx Context) - { - AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + public static void Fadd_V(AILEmitterCtx Context) => EmitVectorBinaryFOp(Context, OpCodes.Add); - Context.EmitLdvec(Op.Rn); - Context.EmitLdvec(Op.Rm); - Context.EmitLdc_I4(Op.SizeF); - - ASoftFallback.EmitCall(Context, - nameof(ASoftFallback.Fadd64), - nameof(ASoftFallback.Fadd128)); - - Context.EmitStvec(Op.Rd); - } - - public static void Fcvtzs_V(AILEmitterCtx Context) - { - AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; - - Context.EmitLdvec(Op.Rn); - Context.EmitLdc_I4(0); - Context.EmitLdc_I4(Op.SizeF); - - ASoftFallback.EmitCall(Context, - nameof(ASoftFallback.Fcvtzs_V64), - nameof(ASoftFallback.Fcvtzs_V128)); - - Context.EmitStvec(Op.Rd); - } - - public static void Fcvtzs_V_Fix(AILEmitterCtx Context) - { - AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; - - Context.EmitLdvec(Op.Rn); - Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm); - Context.EmitLdc_I4(Op.Size - 2); - - ASoftFallback.EmitCall(Context, - nameof(ASoftFallback.Fcvtzs_V64), - nameof(ASoftFallback.Fcvtzs_V128)); - - Context.EmitStvec(Op.Rd); - } - - public static void Fcvtzu_V(AILEmitterCtx Context) - { - AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; - - Context.EmitLdvec(Op.Rn); - Context.EmitLdc_I4(0); - Context.EmitLdc_I4(Op.SizeF); - - ASoftFallback.EmitCall(Context, - nameof(ASoftFallback.Fcvtzu_V_64), - nameof(ASoftFallback.Fcvtzu_V_128)); - - Context.EmitStvec(Op.Rd); - } - - public static void Fcvtzu_V_Fix(AILEmitterCtx Context) - { - AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; - - Context.EmitLdvec(Op.Rn); - Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm); - Context.EmitLdc_I4(Op.Size - 2); - - ASoftFallback.EmitCall(Context, - nameof(ASoftFallback.Fcvtzu_V_64), - nameof(ASoftFallback.Fcvtzu_V_128)); - - Context.EmitStvec(Op.Rd); - } + public static void Fcvtzs_V(AILEmitterCtx Context) => EmitVectorFcvtS(Context); + public static void Fcvtzu_V(AILEmitterCtx Context) => EmitVectorFcvtU(Context); public static void Fmla_V(AILEmitterCtx Context) { @@ -224,20 +154,7 @@ namespace ChocolArm64.Instruction Context.EmitStvec(Op.Rd); } - public static void Fmul_V(AILEmitterCtx Context) - { - AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; - - Context.EmitLdvec(Op.Rn); - Context.EmitLdvec(Op.Rm); - Context.EmitLdc_I4(Op.SizeF); - - ASoftFallback.EmitCall(Context, - nameof(ASoftFallback.Fmul64), - nameof(ASoftFallback.Fmul128)); - - Context.EmitStvec(Op.Rd); - } + public static void Fmul_V(AILEmitterCtx Context) => EmitVectorBinaryFOp(Context, OpCodes.Mul); public static void Fmul_Vs(AILEmitterCtx Context) { @@ -255,20 +172,7 @@ namespace ChocolArm64.Instruction Context.EmitStvec(Op.Rd); } - public static void Fsub_V(AILEmitterCtx Context) - { - AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; - - Context.EmitLdvec(Op.Rn); - Context.EmitLdvec(Op.Rm); - Context.EmitLdc_I4(Op.SizeF); - - ASoftFallback.EmitCall(Context, - nameof(ASoftFallback.Fsub64), - nameof(ASoftFallback.Fsub128)); - - Context.EmitStvec(Op.Rd); - } + public static void Fsub_V(AILEmitterCtx Context) => EmitVectorBinaryFOp(Context, OpCodes.Sub); public static void Ins_Gp(AILEmitterCtx Context) { @@ -870,6 +774,114 @@ namespace ChocolArm64.Instruction }); } + private static void EmitVectorFcvtS(AILEmitterCtx Context) + { + EmitVectorCvtOp(Context, CvtDir.Fcvt, true); + } + + private static void EmitVectorFcvtU(AILEmitterCtx Context) + { + EmitVectorCvtOp(Context, CvtDir.Fcvt, false); + } + + private static void EmitVectorCvtfS(AILEmitterCtx Context) + { + EmitVectorCvtOp(Context, CvtDir.Cvtf, true); + } + + private static void EmitVectorCvtfU(AILEmitterCtx Context) + { + EmitVectorCvtOp(Context, CvtDir.Cvtf, false); + } + + private enum CvtDir + { + Fcvt, + Cvtf + } + + private static void EmitVectorCvtOp(AILEmitterCtx Context, CvtDir Dir, bool Signed) + { + AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; + + int SizeF = Op.Size & 1; + int SizeI = SizeF + 2; + + int FBits = 0; + + if (Op is AOpCodeSimdShImm OpImm) + { + FBits = (8 << (Op.Size + 1)) - OpImm.Imm; + } + + int Bytes = Context.CurrOp.GetBitsCount() >> 3; + + for (int Index = 0; Index < (Bytes >> SizeI); Index++) + { + EmitVectorExtractF(Context, Op.Rn, Index, SizeF); + + Context.EmitLdc_I4(FBits); + + if (Dir == CvtDir.Fcvt) + { + //Float to Integer. + if (SizeF == 0) + { + ASoftFallback.EmitCall(Context, Signed + ? nameof(ASoftFallback.SatSingleToInt32) + : nameof(ASoftFallback.SatSingleToUInt32)); + } + else if (SizeF == 1) + { + ASoftFallback.EmitCall(Context, Signed + ? nameof(ASoftFallback.SatDoubleToInt64) + : nameof(ASoftFallback.SatDoubleToUInt64)); + } + } + else if (Dir == CvtDir.Cvtf) + { + //Integer to Float. + //TODO. + } + + EmitVectorInsert(Context, Op.Rd, Index, SizeI); + } + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Op.Rd); + } + } + + private static void EmitVectorBinaryFOp(AILEmitterCtx Context, OpCode ILOp) + { + EmitVectorBinaryFOp(Context, () => Context.Emit(ILOp)); + } + + private static void EmitVectorBinaryFOp(AILEmitterCtx Context, Action Emit) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + int SizeF = Op.Size & 1; + + int Bytes = Context.CurrOp.GetBitsCount() >> 3; + + for (int Index = 0; Index < (Bytes >> SizeF + 2); Index++) + { + EmitVectorExtractF(Context, Op.Rn, Index, SizeF); + EmitVectorExtractF(Context, Op.Rm, Index, SizeF); + + Emit(); + + EmitVectorInsertF(Context, Op.Rd, Index, SizeF); + } + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Op.Rd); + } + } + private static void EmitVectorUnarySx(AILEmitterCtx Context, OpCode ILOp) { EmitVectorUnarySx(Context, () => Context.Emit(ILOp)); @@ -1047,6 +1059,25 @@ namespace ChocolArm64.Instruction } } + private static void EmitVectorExtractF(AILEmitterCtx Context, int Reg, int Index, int Size) + { + Context.EmitLdvec(Reg); + Context.EmitLdc_I4(Index); + + if (Size == 0) + { + ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorExtractSingle)); + } + else if (Size == 1) + { + ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorExtractDouble)); + } + else + { + throw new ArgumentOutOfRangeException(nameof(Size)); + } + } + private static void EmitVectorExtractSx(AILEmitterCtx Context, int Reg, int Index) { EmitVectorExtract(Context, Reg, Index, true); @@ -1070,6 +1101,27 @@ namespace ChocolArm64.Instruction : nameof(ASoftFallback.ExtractVec)); } + private static void EmitVectorInsertF(AILEmitterCtx Context, int Reg, int Index, int Size) + { + Context.EmitLdvec(Reg); + Context.EmitLdc_I4(Index); + + if (Size == 0) + { + ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorInsertSingle)); + } + else if (Size == 1) + { + ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorInsertDouble)); + } + else + { + throw new ArgumentOutOfRangeException(nameof(Size)); + } + + Context.EmitStvec(Reg); + } + private static void EmitVectorZeroLower(AILEmitterCtx Context, int Rd) { EmitVectorInsert(Context, Rd, 0, 3, 0); @@ -1080,6 +1132,17 @@ namespace ChocolArm64.Instruction EmitVectorInsert(Context, Rd, 1, 3, 0); } + private static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size) + { + Context.EmitLdvec(Reg); + Context.EmitLdc_I4(Index); + Context.EmitLdc_I4(Size); + + ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorInsertInt)); + + Context.EmitStvec(Reg); + } + private static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size, long Value) { Context.EmitLdvec(Reg); diff --git a/Ryujinx/Cpu/Instruction/ASoftFallback.cs b/Ryujinx/Cpu/Instruction/ASoftFallback.cs index caf3cfca7..a7508d7f3 100644 --- a/Ryujinx/Cpu/Instruction/ASoftFallback.cs +++ b/Ryujinx/Cpu/Instruction/ASoftFallback.cs @@ -365,122 +365,6 @@ namespace ChocolArm64.Instruction return Res; } - public static AVec Fadd64(AVec LHS, AVec RHS, int Size) - { - return Fadd(LHS, RHS, Size, 2); - } - - public static AVec Fadd128(AVec LHS, AVec RHS, int Size) - { - return Fadd(LHS, RHS, Size, 4); - } - - private static AVec Fadd(AVec LHS, AVec RHS, int Size, int Bytes) - { - AVec Res = new AVec(); - - int Elems = Bytes >> Size; - - if (Size == 0) - { - for (int Index = 0; Index < Elems; Index++) - { - float L = LHS.ExtractSingle(Index); - float R = RHS.ExtractSingle(Index); - - Res = AVec.InsertSingle(Res, Index, L + R); - } - } - else - { - for (int Index = 0; Index < Elems; Index++) - { - double L = LHS.ExtractDouble(Index); - double R = RHS.ExtractDouble(Index); - - Res = AVec.InsertDouble(Res, Index, L + R); - } - } - - return Res; - } - - public static AVec Fcvtzs_V64(AVec Vector, int FBits, int Size) - { - return Fcvtzs_V(Vector, FBits, Size, 2); - } - - public static AVec Fcvtzs_V128(AVec Vector, int FBits, int Size) - { - return Fcvtzs_V(Vector, FBits, Size, 4); - } - - private static AVec Fcvtzs_V(AVec Vector, int FBits, int Size, int Bytes) - { - AVec Res = new AVec(); - - int Elems = Bytes >> Size; - - if (Size == 0) - { - for (int Index = 0; Index < Elems; Index++) - { - float Value = Vector.ExtractSingle(Index); - - Res = InsertSVec(Res, Index, Size + 2, SatSingleToInt32(Value, FBits)); - } - } - else - { - for (int Index = 0; Index < Elems; Index++) - { - double Value = Vector.ExtractDouble(Index); - - Res = InsertSVec(Res, Index, Size + 2, SatDoubleToInt64(Value, FBits)); - } - } - - return Res; - } - - public static AVec Fcvtzu_V_64(AVec Vector, int FBits, int Size) - { - return Fcvtzu_V(Vector, FBits, Size, 2); - } - - public static AVec Fcvtzu_V_128(AVec Vector, int FBits, int Size) - { - return Fcvtzu_V(Vector, FBits, Size, 4); - } - - private static AVec Fcvtzu_V(AVec Vector, int FBits, int Size, int Bytes) - { - AVec Res = new AVec(); - - int Elems = Bytes >> Size; - - if (Size == 0) - { - for (int Index = 0; Index < Elems; Index++) - { - float Value = Vector.ExtractSingle(Index); - - Res = InsertVec(Res, Index, Size + 2, SatSingleToUInt32(Value, FBits)); - } - } - else - { - for (int Index = 0; Index < Elems; Index++) - { - double Value = Vector.ExtractDouble(Index); - - Res = InsertVec(Res, Index, Size + 2, SatDoubleToUInt64(Value, FBits)); - } - } - - return Res; - } - public static AVec Fmla64(AVec Res, AVec LHS, AVec RHS, int Size) { return Fmla(Res, LHS, RHS, Size, 2); @@ -568,46 +452,6 @@ namespace ChocolArm64.Instruction return InsertVec(new AVec(), Elem, Size, Value); } - public static AVec Fmul64(AVec LHS, AVec RHS, int Size) - { - return Fmul(LHS, RHS, Size, 2); - } - - public static AVec Fmul128(AVec LHS, AVec RHS, int Size) - { - return Fmul(LHS, RHS, Size, 4); - } - - private static AVec Fmul(AVec LHS, AVec RHS, int Size, int Bytes) - { - AVec Res = new AVec(); - - int Elems = Bytes >> Size; - - if (Size == 0) - { - for (int Index = 0; Index < Elems; Index++) - { - float L = LHS.ExtractSingle(Index); - float R = RHS.ExtractSingle(Index); - - Res = AVec.InsertSingle(Res, Index, L * R); - } - } - else - { - for (int Index = 0; Index < Elems; Index++) - { - double L = LHS.ExtractDouble(Index); - double R = RHS.ExtractDouble(Index); - - Res = AVec.InsertDouble(Res, Index, L * R); - } - } - - return Res; - } - public static AVec Fmul_Ve64(AVec LHS, AVec RHS, int SIdx, int Size) { return Fmul_Ve(LHS, RHS, SIdx, Size, 2); @@ -650,46 +494,6 @@ namespace ChocolArm64.Instruction return Res; } - public static AVec Fsub64(AVec LHS, AVec RHS, int Size) - { - return Fsub(LHS, RHS, Size, 2); - } - - public static AVec Fsub128(AVec LHS, AVec RHS, int Size) - { - return Fsub(LHS, RHS, Size, 4); - } - - private static AVec Fsub(AVec LHS, AVec RHS, int Size, int Bytes) - { - AVec Res = new AVec(); - - int Elems = Bytes >> Size; - - if (Size == 0) - { - for (int Index = 0; Index < Elems; Index++) - { - float L = LHS.ExtractSingle(Index); - float R = RHS.ExtractSingle(Index); - - Res = AVec.InsertSingle(Res, Index, L - R); - } - } - else - { - for (int Index = 0; Index < Elems; Index++) - { - double L = LHS.ExtractDouble(Index); - double R = RHS.ExtractDouble(Index); - - Res = AVec.InsertDouble(Res, Index, L - R); - } - } - - return Res; - } - public static AVec Ins_Gp(AVec Res, ulong Value, int Elem, int Size) { return InsertVec(Res, Elem, Size, Value); @@ -1126,6 +930,39 @@ namespace ChocolArm64.Instruction throw new ArgumentOutOfRangeException(nameof(Size)); } + public static float VectorExtractSingle(AVec Vector, int Index) + { + return Vector.ExtractSingle(Index); + } + + public static double VectorExtractDouble(AVec Vector, int Index) + { + return Vector.ExtractDouble(Index); + } + + public static AVec VectorInsertSingle(float Value, AVec Vector, int Index) + { + return AVec.InsertSingle(Vector, Index, Value); + } + + public static AVec VectorInsertDouble(double Value, AVec Vector, int Index) + { + return AVec.InsertDouble(Vector, Index, Value); + } + + public static AVec VectorInsertInt(ulong Value, AVec Vector, int Index, int Size) + { + switch (Size) + { + case 0: return AVec.InsertByte (Vector, Index, (byte)Value); + case 1: return AVec.InsertUInt16(Vector, Index, (ushort)Value); + case 2: return AVec.InsertUInt32(Vector, Index, (uint)Value); + case 3: return AVec.InsertUInt64(Vector, Index, (ulong)Value); + } + + throw new ArgumentOutOfRangeException(nameof(Size)); + } + public static AVec InsertVec(AVec Vector, int Index, int Size, ulong Value) { switch (Size) diff --git a/Ryujinx/Cpu/Memory/AMemoryMgr.cs b/Ryujinx/Cpu/Memory/AMemoryMgr.cs index cd983e78b..544e51302 100644 --- a/Ryujinx/Cpu/Memory/AMemoryMgr.cs +++ b/Ryujinx/Cpu/Memory/AMemoryMgr.cs @@ -1,5 +1,3 @@ -using ChocolArm64.Exceptions; -using System; using System.Runtime.CompilerServices; namespace ChocolArm64.Memory diff --git a/Ryujinx/Logging.cs b/Ryujinx/Logging.cs index e96fd9578..308f068f8 100644 --- a/Ryujinx/Logging.cs +++ b/Ryujinx/Logging.cs @@ -1,8 +1,6 @@ using System; using System.Diagnostics; using System.IO; -using System.Reflection; -using System.Text; namespace Ryujinx { diff --git a/Ryujinx/OsHle/Objects/AudIAudioOut.cs b/Ryujinx/OsHle/Objects/AudIAudioOut.cs index 319d17fe7..029c058f2 100644 --- a/Ryujinx/OsHle/Objects/AudIAudioOut.cs +++ b/Ryujinx/OsHle/Objects/AudIAudioOut.cs @@ -1,15 +1,12 @@ using ChocolArm64.Memory; +using OpenTK.Audio; +using OpenTK.Audio.OpenAL; using Ryujinx.OsHle.Handles; using Ryujinx.OsHle.Ipc; -using static Ryujinx.OsHle.Objects.ObjHelper; - using System; using System.Collections.Generic; using System.IO; -using OpenTK.Audio; -using OpenTK.Audio.OpenAL; - namespace Ryujinx.OsHle.Objects { class AudIAudioOut