From cee712105850ac3385cd0091a923438167433f9f Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Sat, 8 Apr 2023 01:22:00 +0200 Subject: Move solution and projects to src --- Ryujinx.Graphics.Gpu/Engine/MME/AluOperation.cs | 15 - Ryujinx.Graphics.Gpu/Engine/MME/AluRegOperation.cs | 18 - .../Engine/MME/AssignmentOperation.cs | 17 - Ryujinx.Graphics.Gpu/Engine/MME/IMacroEE.cs | 52 --- Ryujinx.Graphics.Gpu/Engine/MME/Macro.cs | 101 ---- Ryujinx.Graphics.Gpu/Engine/MME/MacroHLE.cs | 341 -------------- .../Engine/MME/MacroHLEFunctionName.cs | 16 - Ryujinx.Graphics.Gpu/Engine/MME/MacroHLETable.cs | 113 ----- .../Engine/MME/MacroInterpreter.cs | 400 ---------------- Ryujinx.Graphics.Gpu/Engine/MME/MacroJit.cs | 39 -- .../Engine/MME/MacroJitCompiler.cs | 517 --------------------- Ryujinx.Graphics.Gpu/Engine/MME/MacroJitContext.cs | 55 --- 12 files changed, 1684 deletions(-) delete mode 100644 Ryujinx.Graphics.Gpu/Engine/MME/AluOperation.cs delete mode 100644 Ryujinx.Graphics.Gpu/Engine/MME/AluRegOperation.cs delete mode 100644 Ryujinx.Graphics.Gpu/Engine/MME/AssignmentOperation.cs delete mode 100644 Ryujinx.Graphics.Gpu/Engine/MME/IMacroEE.cs delete mode 100644 Ryujinx.Graphics.Gpu/Engine/MME/Macro.cs delete mode 100644 Ryujinx.Graphics.Gpu/Engine/MME/MacroHLE.cs delete mode 100644 Ryujinx.Graphics.Gpu/Engine/MME/MacroHLEFunctionName.cs delete mode 100644 Ryujinx.Graphics.Gpu/Engine/MME/MacroHLETable.cs delete mode 100644 Ryujinx.Graphics.Gpu/Engine/MME/MacroInterpreter.cs delete mode 100644 Ryujinx.Graphics.Gpu/Engine/MME/MacroJit.cs delete mode 100644 Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs delete mode 100644 Ryujinx.Graphics.Gpu/Engine/MME/MacroJitContext.cs (limited to 'Ryujinx.Graphics.Gpu/Engine/MME') diff --git a/Ryujinx.Graphics.Gpu/Engine/MME/AluOperation.cs b/Ryujinx.Graphics.Gpu/Engine/MME/AluOperation.cs deleted file mode 100644 index eeef9c67..00000000 --- a/Ryujinx.Graphics.Gpu/Engine/MME/AluOperation.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Ryujinx.Graphics.Gpu.Engine.MME -{ - /// - /// GPU Macro Arithmetic and Logic unit operation. - /// - enum AluOperation - { - AluReg = 0, - AddImmediate = 1, - BitfieldReplace = 2, - BitfieldExtractLslImm = 3, - BitfieldExtractLslReg = 4, - ReadImmediate = 5 - } -} diff --git a/Ryujinx.Graphics.Gpu/Engine/MME/AluRegOperation.cs b/Ryujinx.Graphics.Gpu/Engine/MME/AluRegOperation.cs deleted file mode 100644 index f3e05d38..00000000 --- a/Ryujinx.Graphics.Gpu/Engine/MME/AluRegOperation.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Ryujinx.Graphics.Gpu.Engine.MME -{ - /// - /// GPU Macro Arithmetic and Logic unit binary register-to-register operation. - /// - enum AluRegOperation - { - Add = 0, - AddWithCarry = 1, - Subtract = 2, - SubtractWithBorrow = 3, - BitwiseExclusiveOr = 8, - BitwiseOr = 9, - BitwiseAnd = 10, - BitwiseAndNot = 11, - BitwiseNotAnd = 12 - } -} diff --git a/Ryujinx.Graphics.Gpu/Engine/MME/AssignmentOperation.cs b/Ryujinx.Graphics.Gpu/Engine/MME/AssignmentOperation.cs deleted file mode 100644 index dc336026..00000000 --- a/Ryujinx.Graphics.Gpu/Engine/MME/AssignmentOperation.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Ryujinx.Graphics.Gpu.Engine.MME -{ - /// - /// GPU Macro assignment operation. - /// - enum AssignmentOperation - { - IgnoreAndFetch = 0, - Move = 1, - MoveAndSetMaddr = 2, - FetchAndSend = 3, - MoveAndSend = 4, - FetchAndSetMaddr = 5, - MoveAndSetMaddrThenFetchAndSend = 6, - MoveAndSetMaddrThenSendHigh = 7 - } -} diff --git a/Ryujinx.Graphics.Gpu/Engine/MME/IMacroEE.cs b/Ryujinx.Graphics.Gpu/Engine/MME/IMacroEE.cs deleted file mode 100644 index 117961db..00000000 --- a/Ryujinx.Graphics.Gpu/Engine/MME/IMacroEE.cs +++ /dev/null @@ -1,52 +0,0 @@ -using Ryujinx.Graphics.Device; -using System; -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Gpu.Engine.MME -{ - /// - /// FIFO word. - /// - readonly struct FifoWord - { - /// - /// GPU virtual address where the word is located in memory. - /// - public ulong GpuVa { get; } - - /// - /// Word value. - /// - public int Word { get; } - - /// - /// Creates a new FIFO word. - /// - /// GPU virtual address where the word is located in memory - /// Word value - public FifoWord(ulong gpuVa, int word) - { - GpuVa = gpuVa; - Word = word; - } - } - - /// - /// Macro Execution Engine interface. - /// - interface IMacroEE - { - /// - /// Arguments FIFO. - /// - Queue Fifo { get; } - - /// - /// Should execute the GPU Macro code being passed. - /// - /// Code to be executed - /// GPU state at the time of the call - /// First argument to be passed to the GPU Macro - void Execute(ReadOnlySpan code, IDeviceState state, int arg0); - } -} diff --git a/Ryujinx.Graphics.Gpu/Engine/MME/Macro.cs b/Ryujinx.Graphics.Gpu/Engine/MME/Macro.cs deleted file mode 100644 index 12a3ac02..00000000 --- a/Ryujinx.Graphics.Gpu/Engine/MME/Macro.cs +++ /dev/null @@ -1,101 +0,0 @@ -using Ryujinx.Graphics.Device; -using Ryujinx.Graphics.Gpu.Engine.GPFifo; -using System; - -namespace Ryujinx.Graphics.Gpu.Engine.MME -{ - /// - /// GPU macro program. - /// - struct Macro - { - /// - /// Word offset of the code on the code memory. - /// - public int Position { get; } - - private IMacroEE _executionEngine; - private bool _executionPending; - private int _argument; - private MacroHLEFunctionName _hleFunction; - - /// - /// Creates a new instance of the GPU cached macro program. - /// - /// Macro code start position - public Macro(int position) - { - Position = position; - - _executionEngine = null; - _executionPending = false; - _argument = 0; - _hleFunction = MacroHLEFunctionName.None; - } - - /// - /// Sets the first argument for the macro call. - /// - /// GPU context where the macro code is being executed - /// GPU GP FIFO command processor - /// Code to be executed - /// First argument - public void StartExecution(GpuContext context, GPFifoProcessor processor, ReadOnlySpan code, int argument) - { - _argument = argument; - - _executionPending = true; - - if (_executionEngine == null) - { - if (GraphicsConfig.EnableMacroHLE && MacroHLETable.TryGetMacroHLEFunction(code.Slice(Position), context.Capabilities, out _hleFunction)) - { - _executionEngine = new MacroHLE(processor, _hleFunction); - } - else if (GraphicsConfig.EnableMacroJit) - { - _executionEngine = new MacroJit(); - } - else - { - _executionEngine = new MacroInterpreter(); - } - } - - // We don't consume the parameter buffer value, so we don't need to flush it. - // Doing so improves performance if the value was written by a GPU shader. - if (_hleFunction == MacroHLEFunctionName.DrawElementsIndirect) - { - context.GPFifo.SetFlushSkips(1); - } - else if (_hleFunction == MacroHLEFunctionName.MultiDrawElementsIndirectCount) - { - context.GPFifo.SetFlushSkips(2); - } - } - - /// - /// Starts executing the macro program code. - /// - /// Program code - /// Current GPU state - public void Execute(ReadOnlySpan code, IDeviceState state) - { - if (_executionPending) - { - _executionPending = false; - _executionEngine?.Execute(code.Slice(Position), state, _argument); - } - } - - /// - /// Pushes an argument to the macro call argument FIFO. - /// - /// GPU virtual address where the command word is located - /// Argument to be pushed - public void PushArgument(ulong gpuVa, int argument) - { - _executionEngine?.Fifo.Enqueue(new FifoWord(gpuVa, argument)); - } - } -} diff --git a/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLE.cs b/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLE.cs deleted file mode 100644 index 8630bbc4..00000000 --- a/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLE.cs +++ /dev/null @@ -1,341 +0,0 @@ -using Ryujinx.Common.Logging; -using Ryujinx.Graphics.Device; -using Ryujinx.Graphics.GAL; -using Ryujinx.Graphics.Gpu.Engine.GPFifo; -using System; -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Gpu.Engine.MME -{ - /// - /// Macro High-level emulation. - /// - class MacroHLE : IMacroEE - { - private const int ColorLayerCountOffset = 0x818; - private const int ColorStructSize = 0x40; - private const int ZetaLayerCountOffset = 0x1230; - - private const int IndirectDataEntrySize = 0x10; - private const int IndirectIndexedDataEntrySize = 0x14; - - private readonly GPFifoProcessor _processor; - private readonly MacroHLEFunctionName _functionName; - - /// - /// Arguments FIFO. - /// - public Queue Fifo { get; } - - /// - /// Creates a new instance of the HLE macro handler. - /// - /// GPU GP FIFO command processor - /// Name of the HLE macro function to be called - public MacroHLE(GPFifoProcessor processor, MacroHLEFunctionName functionName) - { - _processor = processor; - _functionName = functionName; - - Fifo = new Queue(); - } - - /// - /// Executes a macro program until it exits. - /// - /// Code of the program to execute - /// GPU state at the time of the call - /// Optional argument passed to the program, 0 if not used - public void Execute(ReadOnlySpan code, IDeviceState state, int arg0) - { - switch (_functionName) - { - case MacroHLEFunctionName.ClearColor: - ClearColor(state, arg0); - break; - case MacroHLEFunctionName.ClearDepthStencil: - ClearDepthStencil(state, arg0); - break; - case MacroHLEFunctionName.DrawArraysInstanced: - DrawArraysInstanced(state, arg0); - break; - case MacroHLEFunctionName.DrawElementsInstanced: - DrawElementsInstanced(state, arg0); - break; - case MacroHLEFunctionName.DrawElementsIndirect: - DrawElementsIndirect(state, arg0); - break; - case MacroHLEFunctionName.MultiDrawElementsIndirectCount: - MultiDrawElementsIndirectCount(state, arg0); - break; - default: - throw new NotImplementedException(_functionName.ToString()); - } - - // It should be empty at this point, but clear it just to be safe. - Fifo.Clear(); - } - - /// - /// Clears one bound color target. - /// - /// GPU state at the time of the call - /// First argument of the call - private void ClearColor(IDeviceState state, int arg0) - { - int index = (arg0 >> 6) & 0xf; - int layerCount = state.Read(ColorLayerCountOffset + index * ColorStructSize); - - _processor.ThreedClass.Clear(arg0, layerCount); - } - - /// - /// Clears the current depth-stencil target. - /// - /// GPU state at the time of the call - /// First argument of the call - private void ClearDepthStencil(IDeviceState state, int arg0) - { - int layerCount = state.Read(ZetaLayerCountOffset); - - _processor.ThreedClass.Clear(arg0, layerCount); - } - - /// - /// Performs a draw. - /// - /// GPU state at the time of the call - /// First argument of the call - private void DrawArraysInstanced(IDeviceState state, int arg0) - { - var topology = (PrimitiveTopology)arg0; - - var count = FetchParam(); - var instanceCount = FetchParam(); - var firstVertex = FetchParam(); - var firstInstance = FetchParam(); - - if (ShouldSkipDraw(state, instanceCount.Word)) - { - return; - } - - _processor.ThreedClass.Draw( - topology, - count.Word, - instanceCount.Word, - 0, - firstVertex.Word, - firstInstance.Word, - indexed: false); - } - - /// - /// Performs a indexed draw. - /// - /// GPU state at the time of the call - /// First argument of the call - private void DrawElementsInstanced(IDeviceState state, int arg0) - { - var topology = (PrimitiveTopology)arg0; - - var count = FetchParam(); - var instanceCount = FetchParam(); - var firstIndex = FetchParam(); - var firstVertex = FetchParam(); - var firstInstance = FetchParam(); - - if (ShouldSkipDraw(state, instanceCount.Word)) - { - return; - } - - _processor.ThreedClass.Draw( - topology, - count.Word, - instanceCount.Word, - firstIndex.Word, - firstVertex.Word, - firstInstance.Word, - indexed: true); - } - - /// - /// Performs a indirect indexed draw, with parameters from a GPU buffer. - /// - /// GPU state at the time of the call - /// First argument of the call - private void DrawElementsIndirect(IDeviceState state, int arg0) - { - var topology = (PrimitiveTopology)arg0; - - var count = FetchParam(); - var instanceCount = FetchParam(); - var firstIndex = FetchParam(); - var firstVertex = FetchParam(); - var firstInstance = FetchParam(); - - ulong indirectBufferGpuVa = count.GpuVa; - - var bufferCache = _processor.MemoryManager.Physical.BufferCache; - - bool useBuffer = bufferCache.CheckModified(_processor.MemoryManager, indirectBufferGpuVa, IndirectIndexedDataEntrySize, out ulong indirectBufferAddress); - - if (useBuffer) - { - int indexCount = firstIndex.Word + count.Word; - - _processor.ThreedClass.DrawIndirect( - topology, - indirectBufferAddress, - 0, - 1, - IndirectIndexedDataEntrySize, - indexCount, - Threed.IndirectDrawType.DrawIndexedIndirect); - } - else - { - if (ShouldSkipDraw(state, instanceCount.Word)) - { - return; - } - - _processor.ThreedClass.Draw( - topology, - count.Word, - instanceCount.Word, - firstIndex.Word, - firstVertex.Word, - firstInstance.Word, - indexed: true); - } - } - - /// - /// Performs a indirect indexed multi-draw, with parameters from a GPU buffer. - /// - /// GPU state at the time of the call - /// First argument of the call - private void MultiDrawElementsIndirectCount(IDeviceState state, int arg0) - { - int arg1 = FetchParam().Word; - int arg2 = FetchParam().Word; - int arg3 = FetchParam().Word; - - int startDraw = arg0; - int endDraw = arg1; - var topology = (PrimitiveTopology)arg2; - int paddingWords = arg3; - int stride = paddingWords * 4 + 0x14; - - ulong parameterBufferGpuVa = FetchParam().GpuVa; - - int maxDrawCount = endDraw - startDraw; - - if (startDraw != 0) - { - int drawCount = _processor.MemoryManager.Read(parameterBufferGpuVa, tracked: true); - - // Calculate maximum draw count based on the previous draw count and current draw count. - if ((uint)drawCount <= (uint)startDraw) - { - // The start draw is past our total draw count, so all draws were already performed. - maxDrawCount = 0; - } - else - { - // Perform just the missing number of draws. - maxDrawCount = (int)Math.Min((uint)maxDrawCount, (uint)(drawCount - startDraw)); - } - } - - if (maxDrawCount == 0) - { - Fifo.Clear(); - return; - } - - ulong indirectBufferGpuVa = 0; - int indexCount = 0; - - for (int i = 0; i < maxDrawCount; i++) - { - var count = FetchParam(); - var instanceCount = FetchParam(); - var firstIndex = FetchParam(); - var firstVertex = FetchParam(); - var firstInstance = FetchParam(); - - if (i == 0) - { - indirectBufferGpuVa = count.GpuVa; - } - - indexCount = Math.Max(indexCount, count.Word + firstIndex.Word); - - if (i != maxDrawCount - 1) - { - for (int j = 0; j < paddingWords; j++) - { - FetchParam(); - } - } - } - - var bufferCache = _processor.MemoryManager.Physical.BufferCache; - - ulong indirectBufferSize = (ulong)maxDrawCount * (ulong)stride; - - ulong indirectBufferAddress = bufferCache.TranslateAndCreateBuffer(_processor.MemoryManager, indirectBufferGpuVa, indirectBufferSize); - ulong parameterBufferAddress = bufferCache.TranslateAndCreateBuffer(_processor.MemoryManager, parameterBufferGpuVa, 4); - - _processor.ThreedClass.DrawIndirect( - topology, - indirectBufferAddress, - parameterBufferAddress, - maxDrawCount, - stride, - indexCount, - Threed.IndirectDrawType.DrawIndexedIndirectCount); - } - - /// - /// Checks if the draw should be skipped, because the masked instance count is zero. - /// - /// Current GPU state - /// Draw instance count - /// True if the draw should be skipped, false otherwise - private static bool ShouldSkipDraw(IDeviceState state, int instanceCount) - { - return (Read(state, 0xd1b) & instanceCount) == 0; - } - - /// - /// Fetches a arguments from the arguments FIFO. - /// - /// The call argument, or a 0 value with null address if the FIFO is empty - private FifoWord FetchParam() - { - if (!Fifo.TryDequeue(out var value)) - { - Logger.Warning?.Print(LogClass.Gpu, "Macro attempted to fetch an inexistent argument."); - - return new FifoWord(0UL, 0); - } - - return value; - } - - /// - /// Reads data from a GPU register. - /// - /// Current GPU state - /// Register offset to read - /// GPU register value - private static int Read(IDeviceState state, int reg) - { - return state.Read(reg * 4); - } - } -} diff --git a/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLEFunctionName.cs b/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLEFunctionName.cs deleted file mode 100644 index 751867fc..00000000 --- a/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLEFunctionName.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Ryujinx.Graphics.Gpu.Engine.MME -{ - /// - /// Name of the High-level implementation of a Macro function. - /// - enum MacroHLEFunctionName - { - None, - ClearColor, - ClearDepthStencil, - DrawArraysInstanced, - DrawElementsInstanced, - DrawElementsIndirect, - MultiDrawElementsIndirectCount - } -} diff --git a/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLETable.cs b/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLETable.cs deleted file mode 100644 index 719e170f..00000000 --- a/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLETable.cs +++ /dev/null @@ -1,113 +0,0 @@ -using Ryujinx.Common; -using Ryujinx.Graphics.GAL; -using System; -using System.Runtime.InteropServices; - -namespace Ryujinx.Graphics.Gpu.Engine.MME -{ - /// - /// Table with information about High-level implementations of GPU Macro code. - /// - static class MacroHLETable - { - /// - /// Macroo High-level implementation table entry. - /// - readonly struct TableEntry - { - /// - /// Name of the Macro function. - /// - public MacroHLEFunctionName Name { get; } - - /// - /// Hash of the original binary Macro function code. - /// - public Hash128 Hash { get; } - - /// - /// Size (in bytes) of the original binary Macro function code. - /// - public int Length { get; } - - /// - /// Creates a new table entry. - /// - /// Name of the Macro function - /// Hash of the original binary Macro function code - /// Size (in bytes) of the original binary Macro function code - public TableEntry(MacroHLEFunctionName name, Hash128 hash, int length) - { - Name = name; - Hash = hash; - Length = length; - } - } - - private static readonly TableEntry[] _table = new TableEntry[] - { - new TableEntry(MacroHLEFunctionName.ClearColor, new Hash128(0xA9FB28D1DC43645A, 0xB177E5D2EAE67FB0), 0x28), - new TableEntry(MacroHLEFunctionName.ClearDepthStencil, new Hash128(0x1B96CB77D4879F4F, 0x8557032FE0C965FB), 0x24), - new TableEntry(MacroHLEFunctionName.DrawArraysInstanced, new Hash128(0x197FB416269DBC26, 0x34288C01DDA82202), 0x48), - new TableEntry(MacroHLEFunctionName.DrawElementsInstanced, new Hash128(0x1A501FD3D54EC8E0, 0x6CF570CF79DA74D6), 0x5c), - new TableEntry(MacroHLEFunctionName.DrawElementsIndirect, new Hash128(0x86A3E8E903AF8F45, 0xD35BBA07C23860A4), 0x7c), - new TableEntry(MacroHLEFunctionName.MultiDrawElementsIndirectCount, new Hash128(0x890AF57ED3FB1C37, 0x35D0C95C61F5386F), 0x19C) - }; - - /// - /// Checks if the host supports all features required by the HLE macro. - /// - /// Host capabilities - /// Name of the HLE macro to be checked - /// True if the host supports the HLE macro, false otherwise - private static bool IsMacroHLESupported(Capabilities caps, MacroHLEFunctionName name) - { - if (name == MacroHLEFunctionName.ClearColor || - name == MacroHLEFunctionName.ClearDepthStencil || - name == MacroHLEFunctionName.DrawArraysInstanced || - name == MacroHLEFunctionName.DrawElementsInstanced || - name == MacroHLEFunctionName.DrawElementsIndirect) - { - return true; - } - else if (name == MacroHLEFunctionName.MultiDrawElementsIndirectCount) - { - return caps.SupportsIndirectParameters; - } - - return false; - } - - /// - /// Checks if there's a fast, High-level implementation of the specified Macro code available. - /// - /// Macro code to be checked - /// Renderer capabilities to check for this macro HLE support - /// Name of the function if a implementation is available and supported, otherwise - /// True if there is a implementation available and supported, false otherwise - public static bool TryGetMacroHLEFunction(ReadOnlySpan code, Capabilities caps, out MacroHLEFunctionName name) - { - var mc = MemoryMarshal.Cast(code); - - for (int i = 0; i < _table.Length; i++) - { - ref var entry = ref _table[i]; - - var hash = XXHash128.ComputeHash(mc.Slice(0, entry.Length)); - if (hash == entry.Hash) - { - if (IsMacroHLESupported(caps, entry.Name)) - { - name = entry.Name; - return true; - } - - break; - } - } - - name = MacroHLEFunctionName.None; - return false; - } - } -} diff --git a/Ryujinx.Graphics.Gpu/Engine/MME/MacroInterpreter.cs b/Ryujinx.Graphics.Gpu/Engine/MME/MacroInterpreter.cs deleted file mode 100644 index df6ee040..00000000 --- a/Ryujinx.Graphics.Gpu/Engine/MME/MacroInterpreter.cs +++ /dev/null @@ -1,400 +0,0 @@ -using Ryujinx.Common.Logging; -using Ryujinx.Graphics.Device; -using System; -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Gpu.Engine.MME -{ - /// - /// Macro code interpreter. - /// - class MacroInterpreter : IMacroEE - { - /// - /// Arguments FIFO. - /// - public Queue Fifo { get; } - - private int[] _gprs; - - private int _methAddr; - private int _methIncr; - - private bool _carry; - - private int _opCode; - private int _pipeOp; - - private bool _ignoreExitFlag; - - private int _pc; - - /// - /// Creates a new instance of the macro code interpreter. - /// - public MacroInterpreter() - { - Fifo = new Queue(); - - _gprs = new int[8]; - } - - /// - /// Executes a macro program until it exits. - /// - /// Code of the program to execute - /// Current GPU state - /// Optional argument passed to the program, 0 if not used - public void Execute(ReadOnlySpan code, IDeviceState state, int arg0) - { - Reset(); - - _gprs[1] = arg0; - - _pc = 0; - - FetchOpCode(code); - - while (Step(code, state)) - { - } - - // Due to the delay slot, we still need to execute - // one more instruction before we actually exit. - Step(code, state); - } - - /// - /// Resets the internal interpreter state. - /// Call each time you run a new program. - /// - private void Reset() - { - for (int index = 0; index < _gprs.Length; index++) - { - _gprs[index] = 0; - } - - _methAddr = 0; - _methIncr = 0; - - _carry = false; - } - - /// - /// Executes a single instruction of the program. - /// - /// Program code to execute - /// Current GPU state - /// True to continue execution, false if the program exited - private bool Step(ReadOnlySpan code, IDeviceState state) - { - int baseAddr = _pc - 1; - - FetchOpCode(code); - - if ((_opCode & 7) < 7) - { - // Operation produces a value. - AssignmentOperation asgOp = (AssignmentOperation)((_opCode >> 4) & 7); - - int result = GetAluResult(state); - - switch (asgOp) - { - // Fetch parameter and ignore result. - case AssignmentOperation.IgnoreAndFetch: - SetDstGpr(FetchParam()); - break; - // Move result. - case AssignmentOperation.Move: - SetDstGpr(result); - break; - // Move result and use as Method Address. - case AssignmentOperation.MoveAndSetMaddr: - SetDstGpr(result); - SetMethAddr(result); - break; - // Fetch parameter and send result. - case AssignmentOperation.FetchAndSend: - SetDstGpr(FetchParam()); - Send(state, result); - break; - // Move and send result. - case AssignmentOperation.MoveAndSend: - SetDstGpr(result); - Send(state, result); - break; - // Fetch parameter and use result as Method Address. - case AssignmentOperation.FetchAndSetMaddr: - SetDstGpr(FetchParam()); - SetMethAddr(result); - break; - // Move result and use as Method Address, then fetch and send parameter. - case AssignmentOperation.MoveAndSetMaddrThenFetchAndSend: - SetDstGpr(result); - SetMethAddr(result); - Send(state, FetchParam()); - break; - // Move result and use as Method Address, then send bits 17:12 of result. - case AssignmentOperation.MoveAndSetMaddrThenSendHigh: - SetDstGpr(result); - SetMethAddr(result); - Send(state, (result >> 12) & 0x3f); - break; - } - } - else - { - // Branch. - bool onNotZero = ((_opCode >> 4) & 1) != 0; - - bool taken = onNotZero - ? GetGprA() != 0 - : GetGprA() == 0; - - if (taken) - { - _pc = baseAddr + GetImm(); - - bool noDelays = (_opCode & 0x20) != 0; - - if (noDelays) - { - FetchOpCode(code); - } - else - { - // The delay slot instruction exit flag should be ignored. - _ignoreExitFlag = true; - } - - return true; - } - } - - bool exit = (_opCode & 0x80) != 0 && !_ignoreExitFlag; - - _ignoreExitFlag = false; - - return !exit; - } - - /// - /// Fetches a single operation code from the program code. - /// - /// Program code - private void FetchOpCode(ReadOnlySpan code) - { - _opCode = _pipeOp; - _pipeOp = code[_pc++]; - } - - /// - /// Gets the result of the current Arithmetic and Logic unit operation. - /// - /// Current GPU state - /// Operation result - private int GetAluResult(IDeviceState state) - { - AluOperation op = (AluOperation)(_opCode & 7); - - switch (op) - { - case AluOperation.AluReg: - return GetAluResult((AluRegOperation)((_opCode >> 17) & 0x1f), GetGprA(), GetGprB()); - - case AluOperation.AddImmediate: - return GetGprA() + GetImm(); - - case AluOperation.BitfieldReplace: - case AluOperation.BitfieldExtractLslImm: - case AluOperation.BitfieldExtractLslReg: - int bfSrcBit = (_opCode >> 17) & 0x1f; - int bfSize = (_opCode >> 22) & 0x1f; - int bfDstBit = (_opCode >> 27) & 0x1f; - - int bfMask = (1 << bfSize) - 1; - - int dst = GetGprA(); - int src = GetGprB(); - - switch (op) - { - case AluOperation.BitfieldReplace: - src = (int)((uint)src >> bfSrcBit) & bfMask; - - dst &= ~(bfMask << bfDstBit); - - dst |= src << bfDstBit; - - return dst; - - case AluOperation.BitfieldExtractLslImm: - src = (int)((uint)src >> dst) & bfMask; - - return src << bfDstBit; - - case AluOperation.BitfieldExtractLslReg: - src = (int)((uint)src >> bfSrcBit) & bfMask; - - return src << dst; - } - - break; - - case AluOperation.ReadImmediate: - return Read(state, GetGprA() + GetImm()); - } - - throw new InvalidOperationException($"Invalid operation \"{op}\" on instruction 0x{_opCode:X8}."); - } - - /// - /// Gets the result of an Arithmetic and Logic operation using registers. - /// - /// Arithmetic and Logic unit operation with registers - /// First operand value - /// Second operand value - /// Operation result - private int GetAluResult(AluRegOperation aluOp, int a, int b) - { - ulong result; - - switch (aluOp) - { - case AluRegOperation.Add: - result = (ulong)a + (ulong)b; - - _carry = result > 0xffffffff; - - return (int)result; - - case AluRegOperation.AddWithCarry: - result = (ulong)a + (ulong)b + (_carry ? 1UL : 0UL); - - _carry = result > 0xffffffff; - - return (int)result; - - case AluRegOperation.Subtract: - result = (ulong)a - (ulong)b; - - _carry = result < 0x100000000; - - return (int)result; - - case AluRegOperation.SubtractWithBorrow: - result = (ulong)a - (ulong)b - (_carry ? 0UL : 1UL); - - _carry = result < 0x100000000; - - return (int)result; - - case AluRegOperation.BitwiseExclusiveOr: return a ^ b; - case AluRegOperation.BitwiseOr: return a | b; - case AluRegOperation.BitwiseAnd: return a & b; - case AluRegOperation.BitwiseAndNot: return a & ~b; - case AluRegOperation.BitwiseNotAnd: return ~(a & b); - } - - throw new InvalidOperationException($"Invalid operation \"{aluOp}\" on instruction 0x{_opCode:X8}."); - } - - /// - /// Extracts a 32-bits signed integer constant from the current operation code. - /// - /// The 32-bits immediate value encoded at the current operation code - private int GetImm() - { - // Note: The immediate is signed, the sign-extension is intended here. - return _opCode >> 14; - } - - /// - /// Sets the current method address, for method calls. - /// - /// Packed address and increment value - private void SetMethAddr(int value) - { - _methAddr = (value >> 0) & 0xfff; - _methIncr = (value >> 12) & 0x3f; - } - - /// - /// Sets the destination register value. - /// - /// Value to set (usually the operation result) - private void SetDstGpr(int value) - { - _gprs[(_opCode >> 8) & 7] = value; - } - - /// - /// Gets first operand value from the respective register. - /// - /// Operand value - private int GetGprA() - { - return GetGprValue((_opCode >> 11) & 7); - } - - /// - /// Gets second operand value from the respective register. - /// - /// Operand value - private int GetGprB() - { - return GetGprValue((_opCode >> 14) & 7); - } - - /// - /// Gets the value from a register, or 0 if the R0 register is specified. - /// - /// Index of the register - /// Register value - private int GetGprValue(int index) - { - return index != 0 ? _gprs[index] : 0; - } - - /// - /// Fetches a call argument from the call argument FIFO. - /// - /// The call argument, or 0 if the FIFO is empty - private int FetchParam() - { - if (!Fifo.TryDequeue(out var value)) - { - Logger.Warning?.Print(LogClass.Gpu, "Macro attempted to fetch an inexistent argument."); - - return 0; - } - - return value.Word; - } - - /// - /// Reads data from a GPU register. - /// - /// Current GPU state - /// Register offset to read - /// GPU register value - private int Read(IDeviceState state, int reg) - { - return state.Read(reg * 4); - } - - /// - /// Performs a GPU method call. - /// - /// Current GPU state - /// Call argument - private void Send(IDeviceState state, int value) - { - state.Write(_methAddr * 4, value); - - _methAddr += _methIncr; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Engine/MME/MacroJit.cs b/Ryujinx.Graphics.Gpu/Engine/MME/MacroJit.cs deleted file mode 100644 index 4077f74e..00000000 --- a/Ryujinx.Graphics.Gpu/Engine/MME/MacroJit.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Ryujinx.Graphics.Device; -using System; -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Gpu.Engine.MME -{ - /// - /// Represents a execution engine that uses a Just-in-Time compiler for fast execution. - /// - class MacroJit : IMacroEE - { - private readonly MacroJitContext _context = new MacroJitContext(); - - /// - /// Arguments FIFO. - /// - public Queue Fifo => _context.Fifo; - - private MacroJitCompiler.MacroExecute _execute; - - /// - /// Executes a macro program until it exits. - /// - /// Code of the program to execute - /// Current GPU state - /// Optional argument passed to the program, 0 if not used - public void Execute(ReadOnlySpan code, IDeviceState state, int arg0) - { - if (_execute == null) - { - MacroJitCompiler compiler = new MacroJitCompiler(); - - _execute = compiler.Compile(code); - } - - _execute(_context, state, arg0); - } - } -} diff --git a/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs b/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs deleted file mode 100644 index f8d839fa..00000000 --- a/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitCompiler.cs +++ /dev/null @@ -1,517 +0,0 @@ -using Ryujinx.Graphics.Device; -using System; -using System.Collections.Generic; -using System.Reflection.Emit; - -namespace Ryujinx.Graphics.Gpu.Engine.MME -{ - /// - /// Represents a Macro Just-in-Time compiler. - /// R - class MacroJitCompiler - { - private readonly DynamicMethod _meth; - private readonly ILGenerator _ilGen; - private readonly LocalBuilder[] _gprs; - private readonly LocalBuilder _carry; - private readonly LocalBuilder _methAddr; - private readonly LocalBuilder _methIncr; - - /// - /// Creates a new instance of the Macro Just-in-Time compiler. - /// - public MacroJitCompiler() - { - _meth = new DynamicMethod("Macro", typeof(void), new Type[] { typeof(MacroJitContext), typeof(IDeviceState), typeof(int) }); - _ilGen = _meth.GetILGenerator(); - _gprs = new LocalBuilder[8]; - - for (int i = 1; i < 8; i++) - { - _gprs[i] = _ilGen.DeclareLocal(typeof(int)); - } - - _carry = _ilGen.DeclareLocal(typeof(int)); - _methAddr = _ilGen.DeclareLocal(typeof(int)); - _methIncr = _ilGen.DeclareLocal(typeof(int)); - - _ilGen.Emit(OpCodes.Ldarg_2); - _ilGen.Emit(OpCodes.Stloc, _gprs[1]); - } - - public delegate void MacroExecute(MacroJitContext context, IDeviceState state, int arg0); - - /// - /// Translates a new piece of GPU Macro code into host executable code. - /// - /// Code to be translated - /// Delegate of the host compiled code - public MacroExecute Compile(ReadOnlySpan code) - { - Dictionary labels = new Dictionary(); - - int lastTarget = 0; - int i; - - // Collect all branch targets. - for (i = 0; i < code.Length; i++) - { - int opCode = code[i]; - - if ((opCode & 7) == 7) - { - int target = i + (opCode >> 14); - - if (!labels.ContainsKey(target)) - { - labels.Add(target, _ilGen.DefineLabel()); - } - - if (lastTarget < target) - { - lastTarget = target; - } - } - - bool exit = (opCode & 0x80) != 0; - - if (exit && i >= lastTarget) - { - break; - } - } - - // Code generation. - for (i = 0; i < code.Length; i++) - { - if (labels.TryGetValue(i, out Label label)) - { - _ilGen.MarkLabel(label); - } - - Emit(code, i, labels); - - int opCode = code[i]; - - bool exit = (opCode & 0x80) != 0; - - if (exit) - { - Emit(code, i + 1, labels); - _ilGen.Emit(OpCodes.Ret); - - if (i >= lastTarget) - { - break; - } - } - } - - if (i == code.Length) - { - _ilGen.Emit(OpCodes.Ret); - } - - return _meth.CreateDelegate(); - } - - /// - /// Emits IL equivalent to the Macro instruction at a given offset. - /// - /// GPU Macro code - /// Offset, in words, where the instruction is located - /// Labels for Macro branch targets, used by branch instructions - private void Emit(ReadOnlySpan code, int offset, Dictionary labels) - { - int opCode = code[offset]; - - if ((opCode & 7) < 7) - { - // Operation produces a value. - AssignmentOperation asgOp = (AssignmentOperation)((opCode >> 4) & 7); - - EmitAluOp(opCode); - - switch (asgOp) - { - // Fetch parameter and ignore result. - case AssignmentOperation.IgnoreAndFetch: - _ilGen.Emit(OpCodes.Pop); - EmitFetchParam(); - EmitStoreDstGpr(opCode); - break; - // Move result. - case AssignmentOperation.Move: - EmitStoreDstGpr(opCode); - break; - // Move result and use as Method Address. - case AssignmentOperation.MoveAndSetMaddr: - _ilGen.Emit(OpCodes.Dup); - EmitStoreDstGpr(opCode); - EmitStoreMethAddr(); - break; - // Fetch parameter and send result. - case AssignmentOperation.FetchAndSend: - EmitFetchParam(); - EmitStoreDstGpr(opCode); - EmitSend(); - break; - // Move and send result. - case AssignmentOperation.MoveAndSend: - _ilGen.Emit(OpCodes.Dup); - EmitStoreDstGpr(opCode); - EmitSend(); - break; - // Fetch parameter and use result as Method Address. - case AssignmentOperation.FetchAndSetMaddr: - EmitFetchParam(); - EmitStoreDstGpr(opCode); - EmitStoreMethAddr(); - break; - // Move result and use as Method Address, then fetch and send parameter. - case AssignmentOperation.MoveAndSetMaddrThenFetchAndSend: - _ilGen.Emit(OpCodes.Dup); - EmitStoreDstGpr(opCode); - EmitStoreMethAddr(); - EmitFetchParam(); - EmitSend(); - break; - // Move result and use as Method Address, then send bits 17:12 of result. - case AssignmentOperation.MoveAndSetMaddrThenSendHigh: - _ilGen.Emit(OpCodes.Dup); - _ilGen.Emit(OpCodes.Dup); - EmitStoreDstGpr(opCode); - EmitStoreMethAddr(); - _ilGen.Emit(OpCodes.Ldc_I4, 12); - _ilGen.Emit(OpCodes.Shr_Un); - _ilGen.Emit(OpCodes.Ldc_I4, 0x3f); - _ilGen.Emit(OpCodes.And); - EmitSend(); - break; - } - } - else - { - // Branch. - bool onNotZero = ((opCode >> 4) & 1) != 0; - - EmitLoadGprA(opCode); - - Label lblSkip = _ilGen.DefineLabel(); - - if (onNotZero) - { - _ilGen.Emit(OpCodes.Brfalse, lblSkip); - } - else - { - _ilGen.Emit(OpCodes.Brtrue, lblSkip); - } - - bool noDelays = (opCode & 0x20) != 0; - - if (!noDelays) - { - Emit(code, offset + 1, labels); - } - - int target = offset + (opCode >> 14); - - _ilGen.Emit(OpCodes.Br, labels[target]); - - _ilGen.MarkLabel(lblSkip); - } - } - - /// - /// Emits IL for a Arithmetic and Logic Unit instruction. - /// - /// Instruction to be translated - /// Throw when the instruction encoding is invalid - private void EmitAluOp(int opCode) - { - AluOperation op = (AluOperation)(opCode & 7); - - switch (op) - { - case AluOperation.AluReg: - EmitAluOp((AluRegOperation)((opCode >> 17) & 0x1f), opCode); - break; - - case AluOperation.AddImmediate: - EmitLoadGprA(opCode); - EmitLoadImm(opCode); - _ilGen.Emit(OpCodes.Add); - break; - - case AluOperation.BitfieldReplace: - case AluOperation.BitfieldExtractLslImm: - case AluOperation.BitfieldExtractLslReg: - int bfSrcBit = (opCode >> 17) & 0x1f; - int bfSize = (opCode >> 22) & 0x1f; - int bfDstBit = (opCode >> 27) & 0x1f; - - int bfMask = (1 << bfSize) - 1; - - switch (op) - { - case AluOperation.BitfieldReplace: - EmitLoadGprB(opCode); - _ilGen.Emit(OpCodes.Ldc_I4, bfSrcBit); - _ilGen.Emit(OpCodes.Shr_Un); - _ilGen.Emit(OpCodes.Ldc_I4, bfMask); - _ilGen.Emit(OpCodes.And); - _ilGen.Emit(OpCodes.Ldc_I4, bfDstBit); - _ilGen.Emit(OpCodes.Shl); - EmitLoadGprA(opCode); - _ilGen.Emit(OpCodes.Ldc_I4, ~(bfMask << bfDstBit)); - _ilGen.Emit(OpCodes.And); - _ilGen.Emit(OpCodes.Or); - break; - - case AluOperation.BitfieldExtractLslImm: - EmitLoadGprB(opCode); - EmitLoadGprA(opCode); - _ilGen.Emit(OpCodes.Shr_Un); - _ilGen.Emit(OpCodes.Ldc_I4, bfMask); - _ilGen.Emit(OpCodes.And); - _ilGen.Emit(OpCodes.Ldc_I4, bfDstBit); - _ilGen.Emit(OpCodes.Shl); - break; - - case AluOperation.BitfieldExtractLslReg: - EmitLoadGprB(opCode); - _ilGen.Emit(OpCodes.Ldc_I4, bfSrcBit); - _ilGen.Emit(OpCodes.Shr_Un); - _ilGen.Emit(OpCodes.Ldc_I4, bfMask); - _ilGen.Emit(OpCodes.And); - EmitLoadGprA(opCode); - _ilGen.Emit(OpCodes.Shl); - break; - } - break; - - case AluOperation.ReadImmediate: - _ilGen.Emit(OpCodes.Ldarg_1); - EmitLoadGprA(opCode); - EmitLoadImm(opCode); - _ilGen.Emit(OpCodes.Add); - _ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.Read))); - break; - - default: - throw new InvalidOperationException($"Invalid operation \"{op}\" on instruction 0x{opCode:X8}."); - } - } - - /// - /// Emits IL for a binary Arithmetic and Logic Unit instruction. - /// - /// Arithmetic and Logic Unit instruction - /// Raw instruction - /// Throw when the instruction encoding is invalid - private void EmitAluOp(AluRegOperation aluOp, int opCode) - { - switch (aluOp) - { - case AluRegOperation.Add: - EmitLoadGprA(opCode); - _ilGen.Emit(OpCodes.Conv_U8); - EmitLoadGprB(opCode); - _ilGen.Emit(OpCodes.Conv_U8); - _ilGen.Emit(OpCodes.Add); - _ilGen.Emit(OpCodes.Dup); - _ilGen.Emit(OpCodes.Ldc_I8, 0xffffffffL); - _ilGen.Emit(OpCodes.Cgt_Un); - _ilGen.Emit(OpCodes.Stloc, _carry); - _ilGen.Emit(OpCodes.Conv_U4); - break; - case AluRegOperation.AddWithCarry: - EmitLoadGprA(opCode); - _ilGen.Emit(OpCodes.Conv_U8); - EmitLoadGprB(opCode); - _ilGen.Emit(OpCodes.Conv_U8); - _ilGen.Emit(OpCodes.Ldloc_S, _carry); - _ilGen.Emit(OpCodes.Conv_U8); - _ilGen.Emit(OpCodes.Add); - _ilGen.Emit(OpCodes.Add); - _ilGen.Emit(OpCodes.Dup); - _ilGen.Emit(OpCodes.Ldc_I8, 0xffffffffL); - _ilGen.Emit(OpCodes.Cgt_Un); - _ilGen.Emit(OpCodes.Stloc, _carry); - _ilGen.Emit(OpCodes.Conv_U4); - break; - case AluRegOperation.Subtract: - EmitLoadGprA(opCode); - _ilGen.Emit(OpCodes.Conv_U8); - EmitLoadGprB(opCode); - _ilGen.Emit(OpCodes.Conv_U8); - _ilGen.Emit(OpCodes.Sub); - _ilGen.Emit(OpCodes.Dup); - _ilGen.Emit(OpCodes.Ldc_I8, 0x100000000L); - _ilGen.Emit(OpCodes.Clt_Un); - _ilGen.Emit(OpCodes.Stloc, _carry); - _ilGen.Emit(OpCodes.Conv_U4); - break; - case AluRegOperation.SubtractWithBorrow: - EmitLoadGprA(opCode); - _ilGen.Emit(OpCodes.Conv_U8); - EmitLoadGprB(opCode); - _ilGen.Emit(OpCodes.Conv_U8); - _ilGen.Emit(OpCodes.Ldc_I4_1); - _ilGen.Emit(OpCodes.Ldloc_S, _carry); - _ilGen.Emit(OpCodes.Sub); - _ilGen.Emit(OpCodes.Conv_U8); - _ilGen.Emit(OpCodes.Sub); - _ilGen.Emit(OpCodes.Sub); - _ilGen.Emit(OpCodes.Dup); - _ilGen.Emit(OpCodes.Ldc_I8, 0x100000000L); - _ilGen.Emit(OpCodes.Clt_Un); - _ilGen.Emit(OpCodes.Stloc, _carry); - _ilGen.Emit(OpCodes.Conv_U4); - break; - case AluRegOperation.BitwiseExclusiveOr: - EmitLoadGprA(opCode); - EmitLoadGprB(opCode); - _ilGen.Emit(OpCodes.Xor); - break; - case AluRegOperation.BitwiseOr: - EmitLoadGprA(opCode); - EmitLoadGprB(opCode); - _ilGen.Emit(OpCodes.Or); - break; - case AluRegOperation.BitwiseAnd: - EmitLoadGprA(opCode); - EmitLoadGprB(opCode); - _ilGen.Emit(OpCodes.And); - break; - case AluRegOperation.BitwiseAndNot: - EmitLoadGprA(opCode); - EmitLoadGprB(opCode); - _ilGen.Emit(OpCodes.Not); - _ilGen.Emit(OpCodes.And); - break; - case AluRegOperation.BitwiseNotAnd: - EmitLoadGprA(opCode); - EmitLoadGprB(opCode); - _ilGen.Emit(OpCodes.And); - _ilGen.Emit(OpCodes.Not); - break; - default: - throw new InvalidOperationException($"Invalid operation \"{aluOp}\" on instruction 0x{opCode:X8}."); - } - } - - /// - /// Loads a immediate value on the IL evaluation stack. - /// - /// Instruction from where the immediate should be extracted - private void EmitLoadImm(int opCode) - { - // Note: The immediate is signed, the sign-extension is intended here. - _ilGen.Emit(OpCodes.Ldc_I4, opCode >> 14); - } - - /// - /// Loads a value from the General Purpose register specified as first operand on the IL evaluation stack. - /// - /// Instruction from where the register number should be extracted - private void EmitLoadGprA(int opCode) - { - EmitLoadGpr((opCode >> 11) & 7); - } - - /// - /// Loads a value from the General Purpose register specified as second operand on the IL evaluation stack. - /// - /// Instruction from where the register number should be extracted - private void EmitLoadGprB(int opCode) - { - EmitLoadGpr((opCode >> 14) & 7); - } - - /// - /// Loads a value a General Purpose register on the IL evaluation stack. - /// - /// - /// Register number 0 has a hardcoded value of 0. - /// - /// Register number - private void EmitLoadGpr(int index) - { - if (index == 0) - { - _ilGen.Emit(OpCodes.Ldc_I4_0); - } - else - { - _ilGen.Emit(OpCodes.Ldloc_S, _gprs[index]); - } - } - - /// - /// Emits a call to the method that fetches an argument from the arguments FIFO. - /// The argument is pushed into the IL evaluation stack. - /// - private void EmitFetchParam() - { - _ilGen.Emit(OpCodes.Ldarg_0); - _ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.FetchParam))); - } - - /// - /// Stores the value on the top of the IL evaluation stack into a General Purpose register. - /// - /// - /// Register number 0 does not exist, reads are hardcoded to 0, and writes are simply discarded. - /// - /// Instruction from where the register number should be extracted - private void EmitStoreDstGpr(int opCode) - { - int index = (opCode >> 8) & 7; - - if (index == 0) - { - _ilGen.Emit(OpCodes.Pop); - } - else - { - _ilGen.Emit(OpCodes.Stloc_S, _gprs[index]); - } - } - - /// - /// Stores the value on the top of the IL evaluation stack as method address. - /// This will be used on subsequent send calls as the destination method address. - /// Additionally, the 6 bits starting at bit 12 will be used as increment value, - /// added to the method address after each sent value. - /// - private void EmitStoreMethAddr() - { - _ilGen.Emit(OpCodes.Dup); - _ilGen.Emit(OpCodes.Ldc_I4, 0xfff); - _ilGen.Emit(OpCodes.And); - _ilGen.Emit(OpCodes.Stloc_S, _methAddr); - _ilGen.Emit(OpCodes.Ldc_I4, 12); - _ilGen.Emit(OpCodes.Shr_Un); - _ilGen.Emit(OpCodes.Ldc_I4, 0x3f); - _ilGen.Emit(OpCodes.And); - _ilGen.Emit(OpCodes.Stloc_S, _methIncr); - } - - /// - /// Sends the value on the top of the IL evaluation stack to the GPU, - /// using the current method address. - /// - private void EmitSend() - { - _ilGen.Emit(OpCodes.Ldarg_1); - _ilGen.Emit(OpCodes.Ldloc_S, _methAddr); - _ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.Send))); - _ilGen.Emit(OpCodes.Ldloc_S, _methAddr); - _ilGen.Emit(OpCodes.Ldloc_S, _methIncr); - _ilGen.Emit(OpCodes.Add); - _ilGen.Emit(OpCodes.Stloc_S, _methAddr); - } - } -} diff --git a/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitContext.cs b/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitContext.cs deleted file mode 100644 index 52c2a11b..00000000 --- a/Ryujinx.Graphics.Gpu/Engine/MME/MacroJitContext.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Ryujinx.Common.Logging; -using Ryujinx.Graphics.Device; -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Gpu.Engine.MME -{ - /// - /// Represents a Macro Just-in-Time compiler execution context. - /// - class MacroJitContext - { - /// - /// Arguments FIFO. - /// - public Queue Fifo { get; } = new Queue(); - - /// - /// Fetches a arguments from the arguments FIFO. - /// - /// The call argument, or 0 if the FIFO is empty - public int FetchParam() - { - if (!Fifo.TryDequeue(out var value)) - { - Logger.Warning?.Print(LogClass.Gpu, "Macro attempted to fetch an inexistent argument."); - - return 0; - } - - return value.Word; - } - - /// - /// Reads data from a GPU register. - /// - /// Current GPU state - /// Register offset to read - /// GPU register value - public static int Read(IDeviceState state, int reg) - { - return state.Read(reg * 4); - } - - /// - /// Performs a GPU method call. - /// - /// Call argument - /// Current GPU state - /// Address, in words, of the method - public static void Send(int value, IDeviceState state, int methAddr) - { - state.Write(methAddr * 4, value); - } - } -} -- cgit v1.2.3