@@ -234,7 +234,8 @@ std::string FragmentProgramDecompiler::AddCond()
234234
235235std::string FragmentProgramDecompiler::AddConst ()
236236{
237- const u32 constant_id = m_size + (4 * sizeof (u32 ));
237+ ensure (m_instruction->length == 8 );
238+ const u32 constant_id = m_instruction->addr + 16 ;
238239 u32 index = umax;
239240
240241 if (auto found = m_constant_offsets.find (constant_id);
@@ -249,9 +250,6 @@ std::string FragmentProgramDecompiler::AddConst()
249250 m_constant_offsets[constant_id] = index;
250251 }
251252
252- // Skip next instruction, its just a literal
253- m_offset = 2 * 4 * sizeof (u32 );
254-
255253 // Return the next offset index
256254 return " _fetch_constant(" + std::to_string (index) + " )" ;
257255}
@@ -1317,37 +1315,52 @@ std::string FragmentProgramDecompiler::Decompile()
13171315 for (const auto &block : graph.blocks )
13181316 {
13191317 // TODO: Handle block prologue if any
1320-
1321- for (const auto & inst : block.instructions )
1318+ if (!block.pred .empty ())
13221319 {
1323- for (auto found = std::find (m_end_offsets.begin (), m_end_offsets.end (), m_size);
1324- found != m_end_offsets.end ();
1325- found = std::find (m_end_offsets.begin (), m_end_offsets.end (), m_size))
1320+ // CFG guarantees predecessors are sorted, closest one first
1321+ for (const auto & pred : block.pred )
13261322 {
1327- m_end_offsets.erase (found);
1328- m_code_level--;
1329- AddCode (" }" );
1330- m_loop_count--;
1323+ switch (pred.type )
1324+ {
1325+ case rsx::assembler::EdgeType::ENDLOOP:
1326+ m_loop_count--;
1327+ [[ fallthrough ]];
1328+ case rsx::assembler::EdgeType::ENDIF:
1329+ m_code_level--;
1330+ AddCode (" }" );
1331+ break ;
1332+ case rsx::assembler::EdgeType::LOOP:
1333+ m_loop_count++;
1334+ [[ fallthrough ]];
1335+ case rsx::assembler::EdgeType::IF:
1336+ // Instruction will be inserted by the SIP decoder
1337+ AddCode (" {" );
1338+ m_code_level++;
1339+ break ;
1340+ case rsx::assembler::EdgeType::ELSE:
1341+ // This one needs more testing
1342+ m_code_level--;
1343+ AddCode (" }" );
1344+ AddCode (" else" );
1345+ AddCode (" {" );
1346+ m_code_level++;
1347+ break ;
1348+ default :
1349+ // Start a new block anyway
1350+ fmt::throw_exception (" Unexpected block found" );
1351+ }
13311352 }
1353+ }
13321354
1333- for (auto found = std::find (m_else_offsets.begin (), m_else_offsets.end (), m_size);
1334- found != m_else_offsets.end ();
1335- found = std::find (m_else_offsets.begin (), m_else_offsets.end (), m_size))
1336- {
1337- m_else_offsets.erase (found);
1338- m_code_level--;
1339- AddCode (" }" );
1340- AddCode (" else" );
1341- AddCode (" {" );
1342- m_code_level++;
1343- }
1355+ for (const auto & inst : block.instructions )
1356+ {
1357+ m_instruction = &inst;
13441358
13451359 dst.HEX = inst.bytecode [0 ];
13461360 src0.HEX = inst.bytecode [1 ];
13471361 src1.HEX = inst.bytecode [2 ];
13481362 src2.HEX = inst.bytecode [3 ];
13491363
1350- m_offset = 4 * sizeof (u32 );
13511364 opflags = 0 ;
13521365
13531366 const u32 opcode = dst.opcode | (src1.opcode_is_branch << 6 );
@@ -1373,43 +1386,14 @@ std::string FragmentProgramDecompiler::Decompile()
13731386 break ;
13741387 case RSX_FP_OPCODE_IFE:
13751388 AddCode (" if($cond)" );
1376- if (src2.end_offset != src1.else_offset )
1377- m_else_offsets.push_back (src1.else_offset << 2 );
1378- m_end_offsets.push_back (src2.end_offset << 2 );
1379- AddCode (" {" );
1380- m_code_level++;
13811389 break ;
13821390 case RSX_FP_OPCODE_LOOP:
1383- if (!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt )
1384- {
1385- AddCode (fmt::format (" //$ifcond for(int i%u = %u; i%u < %u; i%u += %u) {} //-> %u //LOOP" ,
1386- m_loop_count, src1.init_counter , m_loop_count, src1.end_counter , m_loop_count, src1.increment , src2.end_offset ));
1387- }
1388- else
1389- {
1390- AddCode (fmt::format (" $ifcond for(int i%u = %u; i%u < %u; i%u += %u) //LOOP" ,
1391+ AddCode (fmt::format (" $ifcond for(int i%u = %u; i%u < %u; i%u += %u) //LOOP" ,
13911392 m_loop_count, src1.init_counter , m_loop_count, src1.end_counter , m_loop_count, src1.increment ));
1392- m_loop_count++;
1393- m_end_offsets.push_back (src2.end_offset << 2 );
1394- AddCode (" {" );
1395- m_code_level++;
1396- }
13971393 break ;
13981394 case RSX_FP_OPCODE_REP:
1399- if (!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt )
1400- {
1401- AddCode (fmt::format (" //$ifcond for(int i%u = %u; i%u < %u; i%u += %u) {} //-> %u //REP" ,
1402- m_loop_count, src1.init_counter , m_loop_count, src1.end_counter , m_loop_count, src1.increment , src2.end_offset ));
1403- }
1404- else
1405- {
1406- AddCode (fmt::format (" if($cond) for(int i%u = %u; i%u < %u; i%u += %u) //REP" ,
1395+ AddCode (fmt::format (" if($cond) for(int i%u = %u; i%u < %u; i%u += %u) //REP" ,
14071396 m_loop_count, src1.init_counter , m_loop_count, src1.end_counter , m_loop_count, src1.increment ));
1408- m_loop_count++;
1409- m_end_offsets.push_back (src2.end_offset << 2 );
1410- AddCode (" {" );
1411- m_code_level++;
1412- }
14131397 break ;
14141398 case RSX_FP_OPCODE_RET:
14151399 AddFlowOp (" return" );
@@ -1447,9 +1431,7 @@ std::string FragmentProgramDecompiler::Decompile()
14471431 break ;
14481432 }
14491433
1450- m_size += m_offset;
1451- ensure ((m_offset & 15 ) == 0 ); // Must be aligned to 16 bytes
1452-
1434+ m_size += m_instruction->length * 4 ;
14531435 if (dst.end ) break ;
14541436 }
14551437
0 commit comments