macro_interpreter.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // Copyright 2018 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <array>
  6. #include <optional>
  7. #include "common/bit_field.h"
  8. #include "common/common_types.h"
  9. namespace Tegra {
  10. namespace Engines {
  11. class Maxwell3D;
  12. }
  13. class MacroInterpreter final {
  14. public:
  15. explicit MacroInterpreter(Engines::Maxwell3D& maxwell3d);
  16. /**
  17. * Executes the macro code with the specified input parameters.
  18. * @param offset Offset to start execution at.
  19. * @param parameters The parameters of the macro.
  20. */
  21. void Execute(u32 offset, std::size_t num_parameters, const u32* parameters);
  22. private:
  23. enum class ALUOperation : u32;
  24. enum class BranchCondition : u32;
  25. enum class ResultOperation : u32;
  26. union Opcode;
  27. union MethodAddress {
  28. u32 raw;
  29. BitField<0, 12, u32> address;
  30. BitField<12, 6, u32> increment;
  31. };
  32. /// Resets the execution engine state, zeroing registers, etc.
  33. void Reset();
  34. /**
  35. * Executes a single macro instruction located at the current program counter. Returns whether
  36. * the interpreter should keep running.
  37. * @param offset Offset to start execution at.
  38. * @param is_delay_slot Whether the current step is being executed due to a delay slot in a
  39. * previous instruction.
  40. */
  41. bool Step(u32 offset, bool is_delay_slot);
  42. /// Calculates the result of an ALU operation. src_a OP src_b;
  43. u32 GetALUResult(ALUOperation operation, u32 src_a, u32 src_b);
  44. /// Performs the result operation on the input result and stores it in the specified register
  45. /// (if necessary).
  46. void ProcessResult(ResultOperation operation, u32 reg, u32 result);
  47. /// Evaluates the branch condition and returns whether the branch should be taken or not.
  48. bool EvaluateBranchCondition(BranchCondition cond, u32 value) const;
  49. /// Reads an opcode at the current program counter location.
  50. Opcode GetOpcode(u32 offset) const;
  51. /// Returns the specified register's value. Register 0 is hardcoded to always return 0.
  52. u32 GetRegister(u32 register_id) const;
  53. /// Sets the register to the input value.
  54. void SetRegister(u32 register_id, u32 value);
  55. /// Sets the method address to use for the next Send instruction.
  56. void SetMethodAddress(u32 address);
  57. /// Calls a GPU Engine method with the input parameter.
  58. void Send(u32 value);
  59. /// Reads a GPU register located at the method address.
  60. u32 Read(u32 method) const;
  61. /// Returns the next parameter in the parameter queue.
  62. u32 FetchParameter();
  63. Engines::Maxwell3D& maxwell3d;
  64. /// Current program counter
  65. u32 pc;
  66. /// Program counter to execute at after the delay slot is executed.
  67. std::optional<u32> delayed_pc;
  68. static constexpr std::size_t NumMacroRegisters = 8;
  69. /// General purpose macro registers.
  70. std::array<u32, NumMacroRegisters> registers = {};
  71. /// Method address to use for the next Send instruction.
  72. MethodAddress method_address = {};
  73. /// Input parameters of the current macro.
  74. std::unique_ptr<u32[]> parameters;
  75. std::size_t num_parameters = 0;
  76. std::size_t parameters_capacity = 0;
  77. /// Index of the next parameter that will be fetched by the 'parm' instruction.
  78. u32 next_parameter_index = 0;
  79. bool carry_flag = false;
  80. };
  81. } // namespace Tegra