mirror of
https://github.com/ran-j/PS2Recomp.git
synced 2026-09-26 08:51:05 -04:00
Merge origin/main into feature/iop-emulator
Preserve the branch's GS CLUT and texture cache implementation while integrating upstream thread initialization and syscall resume coverage. Build passes; 448/456 tests pass with the same eight failures reproduced on pre-merge HEAD (447/455).
This commit is contained in:
@@ -135,6 +135,9 @@ namespace ps2recomp
|
||||
|
||||
for (const auto &inst : instructions)
|
||||
{
|
||||
// A guest-installed syscall handler runs as a separate invocation,
|
||||
// so the scheduler resumes this thread at syscall+4 and needs an
|
||||
// entry point there. +4, not +8: syscall has no delay slot.
|
||||
if (inst.opcode == OPCODE_SPECIAL && inst.function == SPECIAL_SYSCALL)
|
||||
{
|
||||
queueResumeEntryTarget(inst.address + 4u);
|
||||
|
||||
@@ -153,10 +153,10 @@ struct alignas(16) R5900Context
|
||||
|
||||
// Reset COP0 registers
|
||||
cop0_random = 47; // Start at maximum value
|
||||
// cop0_status = 0x400000; // BEV set, ERL clear, kernel mode
|
||||
// 0x00400000 = BEV (Boot Exception Vectors).
|
||||
// 0x00000000 = Normal mode (after BIOS handoff).
|
||||
cop0_status = 0x00000000;
|
||||
// Status as the EE kernel leaves it at handoff. IE (bit 0) and EIE
|
||||
// (bit 16) are separate enables and guest code reads both; libkernel's
|
||||
// StartThread refuses to run while IE is clear.
|
||||
cop0_status = 0x00010001; // EIE | IE
|
||||
cop0_prid = 0x00002e20; // CPU ID for R5900
|
||||
|
||||
in_delay_slot = false;
|
||||
|
||||
@@ -491,7 +491,9 @@ PS2Runtime::PS2Runtime()
|
||||
}
|
||||
#endif
|
||||
|
||||
std::memset(&m_cpuContext, 0, sizeof(m_cpuContext));
|
||||
// Assign rather than memset: R5900Context's constructor zeroes itself and
|
||||
// then applies the COP0 reset values, which a memset here would discard.
|
||||
m_cpuContext = R5900Context{};
|
||||
|
||||
// R0 is always zero in MIPS
|
||||
m_cpuContext.r[0] = _mm_set1_epi32(0);
|
||||
|
||||
@@ -144,6 +144,17 @@ static Instruction makeJr(uint32_t address, uint8_t rs)
|
||||
return inst;
|
||||
}
|
||||
|
||||
static Instruction makeSyscall(uint32_t address)
|
||||
{
|
||||
Instruction inst{};
|
||||
inst.address = address;
|
||||
inst.opcode = OPCODE_SPECIAL;
|
||||
inst.function = SPECIAL_SYSCALL;
|
||||
inst.hasDelaySlot = false;
|
||||
inst.raw = (OPCODE_SPECIAL << 26) | SPECIAL_SYSCALL;
|
||||
return inst;
|
||||
}
|
||||
|
||||
static void printGeneratedCode(const std::string& name, const std::string& code)
|
||||
{
|
||||
#ifdef PRINT_GENERATED_CODE
|
||||
@@ -644,6 +655,35 @@ void register_code_generator_tests()
|
||||
"unresolved JALR should not pretend it has a resolved local jump table");
|
||||
});
|
||||
|
||||
tc.Run("syscall marks the following instruction as a resume entry", [](TestCase &t) {
|
||||
// Shape of a real SDK syscall wrapper:
|
||||
// addiu $v1, $zero, <num> ; syscall ; jr $ra ; <delay slot>
|
||||
Function func;
|
||||
func.name = "syscall_wrapper";
|
||||
func.start = 0x4000;
|
||||
func.end = 0x4010;
|
||||
func.isRecompiled = true;
|
||||
func.isStub = false;
|
||||
|
||||
std::vector<Instruction> instructions{
|
||||
makeAddiu(0x4000, 3, 0, 0x83),
|
||||
makeSyscall(0x4004),
|
||||
makeJr(0x4008, 31),
|
||||
makeNop(0x400C),
|
||||
};
|
||||
|
||||
CodeGenerator gen({}, {});
|
||||
CodeGenerator::AnalysisResult analysis = gen.collectInternalBranchTargets(func, instructions);
|
||||
|
||||
// +4, not +8: syscall has no delay slot.
|
||||
t.IsTrue(analysis.resumeEntryPoints.contains(0x4008u),
|
||||
"syscall should mark the next instruction as resumable");
|
||||
t.IsTrue(analysis.entryPoints.contains(0x4008u),
|
||||
"syscall resume pc should emit a label in the owner");
|
||||
t.IsFalse(analysis.resumeEntryPoints.contains(0x400Cu),
|
||||
"syscall must not claim a delay slot it does not have");
|
||||
});
|
||||
|
||||
tc.Run("resume entry targets emit a top-level pc switch in the owner wrapper", [](TestCase &t) {
|
||||
Function func;
|
||||
func.name = "resume_owner";
|
||||
|
||||
Reference in New Issue
Block a user