mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-27 18:52:11 -04:00
recompiler: tail-transfer image-edge fallthroughs
This commit is contained in:
@@ -2788,6 +2788,24 @@ GeneratedFunction CodeGenerator::generate_function(
|
||||
fallthrough_name);
|
||||
}
|
||||
}
|
||||
} else if (!cfg.block_order.empty()) {
|
||||
// No in-image fallthrough function exists (region/image boundary): a
|
||||
// reachable final block that runs off the end must publish its
|
||||
// continuation PC. Falling off the C body would return with the
|
||||
// entry-switch's consumed cpu->pc == 0, which the top-level trampoline
|
||||
// reads as "program ended".
|
||||
const BasicBlock& last_block = cfg.blocks.at(cfg.block_order.back());
|
||||
bool runs_off_end =
|
||||
last_block.exit_instr.type == ControlFlowType::None ||
|
||||
((last_block.exit_instr.type == ControlFlowType::Branch ||
|
||||
last_block.exit_instr.type == ControlFlowType::Jump) &&
|
||||
last_block.successors.empty());
|
||||
bool is_reachable = last_block.is_entry || !last_block.predecessors.empty();
|
||||
if (runs_off_end && is_reachable) {
|
||||
body_ss << fmt::format(
|
||||
" cpu->pc = 0x{:08X}u; return; /* image-edge fallthrough: tail-transfer */\n",
|
||||
last_block.end_addr + 4u);
|
||||
}
|
||||
}
|
||||
body_ss << " ; /* label compatibility: C requires a statement after the last label */\n";
|
||||
body_ss << "}\n";
|
||||
@@ -3017,6 +3035,23 @@ std::vector<GeneratedFunction> CodeGenerator::generate_alias_group(
|
||||
body << fmt::format(" {}(cpu); /* fallthrough to next function */\n",
|
||||
fallthrough_name);
|
||||
}
|
||||
} else if (!cfg.block_order.empty() &&
|
||||
live_blocks.count(cfg.block_order.back())) {
|
||||
// Image-edge fallthrough (mirrors generate_function): no in-image next
|
||||
// function exists, so a live final block that runs off the end must
|
||||
// tail-transfer to its continuation PC instead of falling off the C
|
||||
// body with cpu->pc still consumed to 0.
|
||||
const BasicBlock& last_block = cfg.blocks.at(cfg.block_order.back());
|
||||
bool runs_off_end =
|
||||
(last_block.exit_instr.type == ControlFlowType::None) ||
|
||||
((last_block.exit_instr.type == ControlFlowType::Branch ||
|
||||
last_block.exit_instr.type == ControlFlowType::Jump) &&
|
||||
last_block.successors.empty());
|
||||
if (runs_off_end) {
|
||||
body << fmt::format(
|
||||
" cpu->pc = 0x{:08X}u; return; /* image-edge fallthrough: tail-transfer */\n",
|
||||
last_block.end_addr + 4u);
|
||||
}
|
||||
}
|
||||
body << " ; /* label compatibility */\n";
|
||||
body << "}\n";
|
||||
|
||||
Reference in New Issue
Block a user