forked from eden-emu/eden
		
	Shader_IR: Implement BRX tracking.
This commit is contained in:
		
							parent
							
								
									5ee4fb6e12
								
							
						
					
					
						commit
						2ef696c85a
					
				
					 1 changed files with 113 additions and 0 deletions
				
			
		|  | @ -124,6 +124,111 @@ enum class ParseResult : u32 { | ||||||
|     AbnormalFlow, |     AbnormalFlow, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | struct BranchIndirectInfo { | ||||||
|  |     u32 buffer{}; | ||||||
|  |     u32 offset{}; | ||||||
|  |     u32 entries{}; | ||||||
|  |     s32 relative_position{}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& state, | ||||||
|  |                                                           u32 start_address, u32 current_position) { | ||||||
|  |     const u32 shader_start = state.start; | ||||||
|  |     u32 pos = current_position; | ||||||
|  |     BranchIndirectInfo result{}; | ||||||
|  |     u64 track_register = 0; | ||||||
|  | 
 | ||||||
|  |     // Step 0 Get BRX Info
 | ||||||
|  |     const Instruction instr = {state.program_code[pos]}; | ||||||
|  |     const auto opcode = OpCode::Decode(instr); | ||||||
|  |     if (opcode->get().GetId() != OpCode::Id::BRX) { | ||||||
|  |         return {}; | ||||||
|  |     } | ||||||
|  |     if (instr.brx.constant_buffer != 0) { | ||||||
|  |         return {}; | ||||||
|  |     } | ||||||
|  |     track_register = instr.gpr8.Value(); | ||||||
|  |     result.relative_position = instr.brx.GetBranchExtend(); | ||||||
|  |     pos--; | ||||||
|  |     bool found_track = false; | ||||||
|  | 
 | ||||||
|  |     // Step 1 Track LDC
 | ||||||
|  |     while (pos >= shader_start) { | ||||||
|  |         if (IsSchedInstruction(pos, shader_start)) { | ||||||
|  |             pos--; | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |         const Instruction instr = {state.program_code[pos]}; | ||||||
|  |         const auto opcode = OpCode::Decode(instr); | ||||||
|  |         if (opcode->get().GetId() == OpCode::Id::LD_C) { | ||||||
|  |             if (instr.gpr0.Value() == track_register && | ||||||
|  |                 instr.ld_c.type.Value() == Tegra::Shader::UniformType::Single) { | ||||||
|  |                 result.buffer = instr.cbuf36.index; | ||||||
|  |                 result.offset = instr.cbuf36.GetOffset(); | ||||||
|  |                 track_register = instr.gpr8.Value(); | ||||||
|  |                 pos--; | ||||||
|  |                 found_track = true; | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         pos--; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (!found_track) { | ||||||
|  |         return {}; | ||||||
|  |     } | ||||||
|  |     found_track = false; | ||||||
|  | 
 | ||||||
|  |     // Step 2 Track SHL
 | ||||||
|  |     while (pos >= shader_start) { | ||||||
|  |         if (IsSchedInstruction(pos, shader_start)) { | ||||||
|  |             pos--; | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |         const Instruction instr = {state.program_code[pos]}; | ||||||
|  |         const auto opcode = OpCode::Decode(instr); | ||||||
|  |         if (opcode->get().GetId() == OpCode::Id::SHL_IMM) { | ||||||
|  |             if (instr.gpr0.Value() == track_register) { | ||||||
|  |                 track_register = instr.gpr8.Value(); | ||||||
|  |                 pos--; | ||||||
|  |                 found_track = true; | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         pos--; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (!found_track) { | ||||||
|  |         return {}; | ||||||
|  |     } | ||||||
|  |     found_track = false; | ||||||
|  | 
 | ||||||
|  |     // Step 3 Track IMNMX
 | ||||||
|  |     while (pos >= shader_start) { | ||||||
|  |         if (IsSchedInstruction(pos, shader_start)) { | ||||||
|  |             pos--; | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |         const Instruction instr = {state.program_code[pos]}; | ||||||
|  |         const auto opcode = OpCode::Decode(instr); | ||||||
|  |         if (opcode->get().GetId() == OpCode::Id::IMNMX_IMM) { | ||||||
|  |             if (instr.gpr0.Value() == track_register) { | ||||||
|  |                 track_register = instr.gpr8.Value(); | ||||||
|  |                 result.entries = instr.alu.GetSignedImm20_20(); | ||||||
|  |                 pos--; | ||||||
|  |                 found_track = true; | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         pos--; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (!found_track) { | ||||||
|  |         return {}; | ||||||
|  |     } | ||||||
|  |     return {result}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) { | std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) { | ||||||
|     u32 offset = static_cast<u32>(address); |     u32 offset = static_cast<u32>(address); | ||||||
|     const u32 end_address = static_cast<u32>(state.program_size / sizeof(Instruction)); |     const u32 end_address = static_cast<u32>(state.program_size / sizeof(Instruction)); | ||||||
|  | @ -298,6 +403,14 @@ std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         case OpCode::Id::BRX: { |         case OpCode::Id::BRX: { | ||||||
|  |             auto tmp = TrackBranchIndirectInfo(state, address, offset); | ||||||
|  |             if (tmp) { | ||||||
|  |                 auto result = *tmp; | ||||||
|  |                 LOG_CRITICAL(HW_GPU, "Track Successful, BRX: buffer:{}, offset:{}, entries:{}", | ||||||
|  |                              result.buffer, result.offset, result.entries); | ||||||
|  |             } else { | ||||||
|  |                 LOG_CRITICAL(HW_GPU, "Track Unsuccesful"); | ||||||
|  |             } | ||||||
|             return {ParseResult::AbnormalFlow, parse_info}; |             return {ParseResult::AbnormalFlow, parse_info}; | ||||||
|         } |         } | ||||||
|         default: |         default: | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Fernando Sahmkow
						Fernando Sahmkow