1 // Copyright 2020 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 <memory> 8 #include <unordered_map> 9 #include <vector> 10 #include "common/bit_field.h" 11 #include "common/common_types.h" 12 13 namespace Tegra { 14 15 namespace Engines { 16 class Maxwell3D; 17 } 18 19 namespace Macro { 20 constexpr std::size_t NUM_MACRO_REGISTERS = 8; 21 enum class Operation : u32 { 22 ALU = 0, 23 AddImmediate = 1, 24 ExtractInsert = 2, 25 ExtractShiftLeftImmediate = 3, 26 ExtractShiftLeftRegister = 4, 27 Read = 5, 28 Unused = 6, // This operation doesn't seem to be a valid encoding. 29 Branch = 7, 30 }; 31 32 enum class ALUOperation : u32 { 33 Add = 0, 34 AddWithCarry = 1, 35 Subtract = 2, 36 SubtractWithBorrow = 3, 37 // Operations 4-7 don't seem to be valid encodings. 38 Xor = 8, 39 Or = 9, 40 And = 10, 41 AndNot = 11, 42 Nand = 12 43 }; 44 45 enum class ResultOperation : u32 { 46 IgnoreAndFetch = 0, 47 Move = 1, 48 MoveAndSetMethod = 2, 49 FetchAndSend = 3, 50 MoveAndSend = 4, 51 FetchAndSetMethod = 5, 52 MoveAndSetMethodFetchAndSend = 6, 53 MoveAndSetMethodSend = 7 54 }; 55 56 enum class BranchCondition : u32 { 57 Zero = 0, 58 NotZero = 1, 59 }; 60 61 union Opcode { 62 u32 raw; 63 BitField<0, 3, Operation> operation; 64 BitField<4, 3, ResultOperation> result_operation; 65 BitField<4, 1, BranchCondition> branch_condition; 66 // If set on a branch, then the branch doesn't have a delay slot. 67 BitField<5, 1, u32> branch_annul; 68 BitField<7, 1, u32> is_exit; 69 BitField<8, 3, u32> dst; 70 BitField<11, 3, u32> src_a; 71 BitField<14, 3, u32> src_b; 72 // The signed immediate overlaps the second source operand and the alu operation. 73 BitField<14, 18, s32> immediate; 74 75 BitField<17, 5, ALUOperation> alu_operation; 76 77 // Bitfield instructions data 78 BitField<17, 5, u32> bf_src_bit; 79 BitField<22, 5, u32> bf_size; 80 BitField<27, 5, u32> bf_dst_bit; 81 GetBitfieldMask()82 u32 GetBitfieldMask() const { 83 return (1 << bf_size) - 1; 84 } 85 GetBranchTarget()86 s32 GetBranchTarget() const { 87 return static_cast<s32>(immediate * sizeof(u32)); 88 } 89 }; 90 91 union MethodAddress { 92 u32 raw; 93 BitField<0, 12, u32> address; 94 BitField<12, 6, u32> increment; 95 }; 96 97 } // namespace Macro 98 99 class HLEMacro; 100 101 class CachedMacro { 102 public: 103 virtual ~CachedMacro() = default; 104 /** 105 * Executes the macro code with the specified input parameters. 106 * 107 * @param parameters The parameters of the macro 108 * @param method The method to execute 109 */ 110 virtual void Execute(const std::vector<u32>& parameters, u32 method) = 0; 111 }; 112 113 class MacroEngine { 114 public: 115 explicit MacroEngine(Engines::Maxwell3D& maxwell3d); 116 virtual ~MacroEngine(); 117 118 // Store the uploaded macro code to compile them when they're called. 119 void AddCode(u32 method, u32 data); 120 121 // Compiles the macro if its not in the cache, and executes the compiled macro 122 void Execute(Engines::Maxwell3D& maxwell3d, u32 method, const std::vector<u32>& parameters); 123 124 protected: 125 virtual std::unique_ptr<CachedMacro> Compile(const std::vector<u32>& code) = 0; 126 127 private: 128 struct CacheInfo { 129 std::unique_ptr<CachedMacro> lle_program{}; 130 std::unique_ptr<CachedMacro> hle_program{}; 131 u64 hash{}; 132 bool has_hle_program{}; 133 }; 134 135 std::unordered_map<u32, CacheInfo> macro_cache; 136 std::unordered_map<u32, std::vector<u32>> uploaded_macro_code; 137 std::unique_ptr<HLEMacro> hle_macros; 138 }; 139 140 std::unique_ptr<MacroEngine> GetMacroEngine(Engines::Maxwell3D& maxwell3d); 141 142 } // namespace Tegra 143