diff options
Diffstat (limited to 'Ryujinx.Graphics.Gpu/MacroInterpreter.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/MacroInterpreter.cs | 92 |
1 files changed, 81 insertions, 11 deletions
diff --git a/Ryujinx.Graphics.Gpu/MacroInterpreter.cs b/Ryujinx.Graphics.Gpu/MacroInterpreter.cs index e424b8ff..cfc3815b 100644 --- a/Ryujinx.Graphics.Gpu/MacroInterpreter.cs +++ b/Ryujinx.Graphics.Gpu/MacroInterpreter.cs @@ -5,6 +5,9 @@ using System.Collections.Generic; namespace Ryujinx.Graphics.Gpu { + /// <summary> + /// Macro code interpreter. + /// </summary> class MacroInterpreter { private enum AssignmentOperation @@ -42,10 +45,6 @@ namespace Ryujinx.Graphics.Gpu BitwiseNotAnd = 12 } - private GpuContext _context; - - private NvGpuFifo _pFifo; - public Queue<int> Fifo { get; private set; } private int[] _gprs; @@ -61,16 +60,23 @@ namespace Ryujinx.Graphics.Gpu private int _pc; - public MacroInterpreter(GpuContext context, NvGpuFifo pFifo) + /// <summary> + /// Creates a new instance of the macro code interpreter. + /// </summary> + public MacroInterpreter() { - _context = context; - _pFifo = pFifo; - Fifo = new Queue<int>(); _gprs = new int[8]; } + /// <summary> + /// Executes a macro program until it exits. + /// </summary> + /// <param name="mme">Code of the program to execute</param> + /// <param name="position">Start position to execute</param> + /// <param name="param">Optional argument passed to the program, 0 if not used</param> + /// <param name="state">Current GPU state</param> public void Execute(int[] mme, int position, int param, GpuState state) { Reset(); @@ -88,6 +94,10 @@ namespace Ryujinx.Graphics.Gpu Step(mme, state); } + /// <summary> + /// Resets the internal interpreter state. + /// Call each time you run a new program. + /// </summary> private void Reset() { for (int index = 0; index < _gprs.Length; index++) @@ -101,6 +111,12 @@ namespace Ryujinx.Graphics.Gpu _carry = false; } + /// <summary> + /// Executes a single instruction of the program. + /// </summary> + /// <param name="mme">Program code to execute</param> + /// <param name="state">Current GPU state</param> + /// <returns>True to continue execution, false if the program exited</returns> private bool Step(int[] mme, GpuState state) { int baseAddr = _pc - 1; @@ -226,12 +242,21 @@ namespace Ryujinx.Graphics.Gpu return !exit; } + /// <summary> + /// Fetches a single operation code from the program code. + /// </summary> + /// <param name="mme">Program code</param> private void FetchOpCode(int[] mme) { _opCode = _pipeOp; _pipeOp = mme[_pc++]; } + /// <summary> + /// Gets the result of the current Arithmetic and Logic unit operation. + /// </summary> + /// <param name="state">Current GPU state</param> + /// <returns>Operation result</returns> private int GetAluResult(GpuState state) { AluOperation op = (AluOperation)(_opCode & 7); @@ -303,6 +328,13 @@ namespace Ryujinx.Graphics.Gpu throw new ArgumentException(nameof(_opCode)); } + /// <summary> + /// Gets the result of a Arithmetic and Logic operation using registers. + /// </summary> + /// <param name="aluOp">Arithmetic and Logic unit operation with registers</param> + /// <param name="a">First operand value</param> + /// <param name="b">Second operand value</param> + /// <returns>Operation result</returns> private int GetAluResult(AluRegOperation aluOp, int a, int b) { switch (aluOp) @@ -353,43 +385,70 @@ namespace Ryujinx.Graphics.Gpu throw new ArgumentOutOfRangeException(nameof(aluOp)); } + /// <summary> + /// Extracts a 32-bits signed integer constant from the current operation code. + /// </summary> + /// <returns></returns> private int GetImm() { // Note: The immediate is signed, the sign-extension is intended here. return _opCode >> 14; } + /// <summary> + /// Sets the current method address, for method calls. + /// </summary> + /// <param name="value">Packed address and increment value</param> private void SetMethAddr(int value) { _methAddr = (value >> 0) & 0xfff; _methIncr = (value >> 12) & 0x3f; } + /// <summary> + /// Sets the destination register value. + /// </summary> + /// <param name="value">Value to set (usually the operation result)</param> private void SetDstGpr(int value) { _gprs[(_opCode >> 8) & 7] = value; } + /// <summary> + /// Gets first operand value from the respective register. + /// </summary> + /// <returns>Operand value</returns> private int GetGprA() { return GetGprValue((_opCode >> 11) & 7); } + /// <summary> + /// Gets second operand value from the respective register. + /// </summary> + /// <returns>Operand value</returns> private int GetGprB() { return GetGprValue((_opCode >> 14) & 7); } + /// <summary> + /// Gets the value from a register, or 0 if the R0 register is specified. + /// </summary> + /// <param name="index">Index of the register</param> + /// <returns>Register value</returns> private int GetGprValue(int index) { return index != 0 ? _gprs[index] : 0; } + /// <summary> + /// Fetches a call argument from the call argument FIFO. + /// </summary> + /// <returns>The call argument, or 0 if the FIFO is empty</returns> private int FetchParam() { - int value; - - if (!Fifo.TryDequeue(out value)) + if (!Fifo.TryDequeue(out int value)) { Logger.PrintWarning(LogClass.Gpu, "Macro attempted to fetch an inexistent argument."); @@ -399,11 +458,22 @@ namespace Ryujinx.Graphics.Gpu return value; } + /// <summary> + /// Reads data from a GPU register. + /// </summary> + /// <param name="state">Current GPU state</param> + /// <param name="reg">Register offset to read</param> + /// <returns>GPU register value</returns> private int Read(GpuState state, int reg) { return state.Read(reg); } + /// <summary> + /// Performs a GPU method call. + /// </summary> + /// <param name="state">Current GPU state</param> + /// <param name="value">Call argument</param> private void Send(GpuState state, int value) { MethodParams meth = new MethodParams(_methAddr, value); |