summaryrefslogtreecommitdiff
path: root/src/video_core/macro_interpreter.h
diff options
context:
space:
mode:
authorGravatar Subv2018-03-28 15:14:47 -0500
committerGravatar Subv2018-04-01 12:07:26 -0500
commit1ec8d2123d3cca013178827e059641f8989b5af4 (patch)
tree697717ce5175807e6f56611aee8eef9fd2a11ec3 /src/video_core/macro_interpreter.h
parentMerge pull request #286 from N00byKing/citratoyuzuagain (diff)
downloadyuzu-1ec8d2123d3cca013178827e059641f8989b5af4.tar.gz
yuzu-1ec8d2123d3cca013178827e059641f8989b5af4.tar.xz
yuzu-1ec8d2123d3cca013178827e059641f8989b5af4.zip
GPU: Implemented a gpu macro interpreter.
The Ryujinx macro interpreter and envydis were used as reference. Macros are programs that are uploaded by the games during boot and can later be called by writing to their method id in a GPU command buffer.
Diffstat (limited to 'src/video_core/macro_interpreter.h')
-rw-r--r--src/video_core/macro_interpreter.h164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/video_core/macro_interpreter.h b/src/video_core/macro_interpreter.h
new file mode 100644
index 000000000..a71e359d8
--- /dev/null
+++ b/src/video_core/macro_interpreter.h
@@ -0,0 +1,164 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <vector>
9#include <boost/optional.hpp>
10#include "common/bit_field.h"
11#include "common/common_types.h"
12
13namespace Tegra {
14namespace Engines {
15class Maxwell3D;
16}
17
18class MacroInterpreter final {
19public:
20 explicit MacroInterpreter(Engines::Maxwell3D& maxwell3d);
21
22 /**
23 * Executes the macro code with the specified input parameters.
24 * @param code The macro byte code to execute
25 * @param parameters The parameters of the macro
26 */
27 void Execute(const std::vector<u32>& code, std::vector<u32> parameters);
28
29private:
30 enum class Operation : u32 {
31 ALU = 0,
32 AddImmediate = 1,
33 ExtractInsert = 2,
34 ExtractShiftLeftImmediate = 3,
35 ExtractShiftLeftRegister = 4,
36 Read = 5,
37 Unused = 6, // This operation doesn't seem to be a valid encoding.
38 Branch = 7,
39 };
40
41 enum class ALUOperation : u32 {
42 Add = 0,
43 AddWithCarry = 1,
44 Subtract = 2,
45 SubtractWithBorrow = 3,
46 // Operations 4-7 don't seem to be valid encodings.
47 Xor = 8,
48 Or = 9,
49 And = 10,
50 AndNot = 11,
51 Nand = 12
52 };
53
54 enum class ResultOperation : u32 {
55 IgnoreAndFetch = 0,
56 Move = 1,
57 MoveAndSetMethod = 2,
58 FetchAndSend = 3,
59 MoveAndSend = 4,
60 FetchAndSetMethod = 5,
61 MoveAndSetMethodFetchAndSend = 6,
62 MoveAndSetMethodSend = 7
63 };
64
65 enum class BranchCondition : u32 {
66 Zero = 0,
67 NotZero = 1,
68 };
69
70 union Opcode {
71 u32 raw;
72 BitField<0, 3, Operation> operation;
73 BitField<4, 3, ResultOperation> result_operation;
74 BitField<4, 1, BranchCondition> branch_condition;
75 BitField<5, 1, u32>
76 branch_annul; // If set on a branch, then the branch doesn't have a delay slot.
77 BitField<7, 1, u32> is_exit;
78 BitField<8, 3, u32> dst;
79 BitField<11, 3, u32> src_a;
80 BitField<14, 3, u32> src_b;
81 // The signed immediate overlaps the second source operand and the alu operation.
82 BitField<14, 18, s32> immediate;
83
84 BitField<17, 5, ALUOperation> alu_operation;
85
86 // Bitfield instructions data
87 BitField<17, 5, u32> bf_src_bit;
88 BitField<22, 5, u32> bf_size;
89 BitField<27, 5, u32> bf_dst_bit;
90
91 u32 GetBitfieldMask() const {
92 return (1 << bf_size) - 1;
93 }
94 };
95
96 union MethodAddress {
97 u32 raw;
98 BitField<0, 12, u32> address;
99 BitField<12, 6, u32> increment;
100 };
101
102 /// Resets the execution engine state, zeroing registers, etc.
103 void Reset();
104
105 /**
106 * Executes a single macro instruction located at the current program counter. Returns whether
107 * the interpreter should keep running.
108 * @param code The macro code to execute.
109 * @param is_delay_slot Whether the current step is being executed due to a delay slot in a
110 * previous instruction.
111 */
112 bool Step(const std::vector<u32>& code, bool is_delay_slot);
113
114 /// Calculates the result of an ALU operation. src_a OP src_b;
115 u32 GetALUResult(ALUOperation operation, u32 src_a, u32 src_b) const;
116
117 /// Performs the result operation on the input result and stores it in the specified register
118 /// (if necessary).
119 void ProcessResult(ResultOperation operation, u32 reg, u32 result);
120
121 /// Evaluates the branch condition and returns whether the branch should be taken or not.
122 bool EvaluateBranchCondition(BranchCondition cond, u32 value) const;
123
124 /// Reads an opcode at the current program counter location.
125 Opcode GetOpcode(const std::vector<u32>& code) const;
126
127 /// Returns the specified register's value. Register 0 is hardcoded to always return 0.
128 u32 GetRegister(u32 register_id) const;
129
130 /// Sets the register to the input value.
131 void SetRegister(u32 register_id, u32 value);
132
133 /// Sets the method address to use for the next Send instruction.
134 void SetMethodAddress(u32 address);
135
136 /// Calls a GPU Engine method with the input parameter.
137 void Send(u32 value);
138
139 /// Reads a GPU register located at the method address.
140 u32 Read(u32 method) const;
141
142 /// Returns the next parameter in the parameter queue.
143 u32 FetchParameter();
144
145 Engines::Maxwell3D& maxwell3d;
146
147 u32 pc; ///< Current program counter
148 boost::optional<u32>
149 delayed_pc; ///< Program counter to execute at after the delay slot is executed.
150
151 static constexpr size_t NumMacroRegisters = 8;
152
153 /// General purpose macro registers.
154 std::array<u32, NumMacroRegisters> registers = {};
155
156 /// Method address to use for the next Send instruction.
157 MethodAddress method_address = {};
158
159 /// Input parameters of the current macro.
160 std::vector<u32> parameters;
161 /// Index of the next parameter that will be fetched by the 'parm' instruction.
162 u32 next_parameter_index = 0;
163};
164} // namespace Tegra