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, | ||||
| }; | ||||
| 
 | ||||
| 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) { | ||||
|     u32 offset = static_cast<u32>(address); | ||||
|     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; | ||||
|         } | ||||
|         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}; | ||||
|         } | ||||
|         default: | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Fernando Sahmkow
						Fernando Sahmkow