Files
psxrecomp/recompiler/include/function_analysis.h
T
Matthew Stanley ec4306fbb3 mmx6 framework: CD/DMA/MDEC + codegen fixes (Tomba builds+plays, MMX6 boots to intro)
Framework work on codex/mmx6-support that makes Tomba build and play
(title screen, 0 dispatch misses) and MMX6 boot through BIOS to its
intro. Touches recompiler codegen (code_generator, function_analysis)
and runtime CD-ROM/DMA/MDEC/GPU/SIO timing (cdrom, dma, mdec, gpu,
psx_cycles, traps, fntrace, debug_server) + headers + runtime.cmake.

Milestone snapshot for collapsing onto master. Build dir excluded.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 12:06:02 -07:00

69 lines
2.2 KiB
C++

#pragma once
#include <cstdint>
#include <vector>
#include <string>
#include "ps1_exe_parser.h"
namespace PSXRecomp {
struct Function {
uint32_t start_addr;
uint32_t end_addr;
uint32_t size;
bool has_prologue;
bool has_epilogue;
int32_t stack_frame_size; // Size of stack frame (if has prologue)
std::string name; // Optional name (for now, just "func_<addr>")
bool is_data_section = false; // True if this "function" is actually a data section
};
struct FunctionAnalysisResult {
std::vector<Function> functions;
int total_instructions;
int jr_ra_count;
int prologue_count;
int call_discovered_count = 0; // Functions found via JAL call-target following
int strong_prologue_count = 0; // Functions found from prologues with saved $ra
int state_continuation_count = 0; // Split entries after calls to SaveState-style helpers
};
class FunctionAnalyzer {
public:
explicit FunctionAnalyzer(const PS1Executable& exe);
// Scan entire executable for function boundaries
FunctionAnalysisResult analyze();
// Add a forced entry point address that is treated as a function start
// even if it has no standard ADDIU $sp prologue. The function will be
// included in the analysis result with has_prologue = false.
void add_forced_entry(uint32_t addr);
// Check if instruction is jr $ra (return)
static bool is_jr_ra(uint32_t instr);
// Check if instruction is function prologue (addiu $sp, $sp, -N)
static bool is_prologue(uint32_t instr, int32_t& stack_size);
// Check if instruction is epilogue (addiu $sp, $sp, +N)
static bool is_epilogue(uint32_t instr, int32_t& stack_size);
// Check if instruction is a branch or jump (has a delay slot)
static bool is_branch_or_jump(uint32_t instr);
private:
const PS1Executable& exe_;
// Forced entry points (from add_forced_entry())
std::vector<uint32_t> forced_entry_points_;
// Find function start by scanning backward from jr $ra
uint32_t find_function_start(uint32_t return_addr);
// Detect if a region is likely a data section masquerading as code
bool is_likely_data_section(uint32_t start_addr, uint32_t end_addr) const;
};
} // namespace PSXRecomp