mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
MFF_NO_RETURN flag introduced
This commit is contained in:
parent
a70d305806
commit
b84d831d8f
@ -2004,19 +2004,10 @@ void Compiler::BC(u32 bo, u32 bi, s32 bd, u32 aa, u32 lk) {
|
||||
}
|
||||
|
||||
void Compiler::HACK(u32 index) {
|
||||
if (index & EIF_SAVE_RTOC) {
|
||||
auto addr_i64 = (Value *)m_ir_builder->getInt64(0x28);
|
||||
auto ra_i64 = GetGpr(1);
|
||||
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
|
||||
WriteMemory(addr_i64, GetGpr(2, 64));
|
||||
}
|
||||
Call<void>("execute_ppu_func_by_index", &execute_ppu_func_by_index, m_state.args[CompileTaskState::Args::State], m_ir_builder->getInt32(index & ~EIF_FLAGS));
|
||||
if (index & EIF_PERFORM_BLR) {
|
||||
auto lr_i64 = GetLr();
|
||||
lr_i64 = m_ir_builder->CreateAnd(lr_i64, ~0x3ULL);
|
||||
auto lr_i32 = m_ir_builder->CreateTrunc(lr_i64, m_ir_builder->getInt32Ty());
|
||||
CreateBranch(nullptr, lr_i32, false, true);
|
||||
Call<void>("execute_ppu_func_by_index", &execute_ppu_func_by_index, m_state.args[CompileTaskState::Args::State], m_ir_builder->getInt32(index & EIF_USE_BRANCH ? index : index & ~EIF_PERFORM_BLR));
|
||||
if (index & EIF_PERFORM_BLR || index & EIF_USE_BRANCH) {
|
||||
auto lr_i32 = index & EIF_USE_BRANCH ? GetPc() : m_ir_builder->CreateTrunc(m_ir_builder->CreateAnd(GetLr(), ~0x3ULL), m_ir_builder->getInt32Ty());
|
||||
CreateBranch(nullptr, lr_i32, false, (index & EIF_USE_BRANCH) == 0);
|
||||
}
|
||||
// copied from Compiler::SC()
|
||||
//auto ret_i1 = Call<bool>("PollStatus", m_poll_status_function, m_state.args[CompileTaskState::Args::State]);
|
||||
@ -6089,9 +6080,10 @@ BranchType ppu_recompiler_llvm::GetBranchTypeFromInstruction(u32 instruction) {
|
||||
} else if (field2 == 528) {
|
||||
type = lk ? BranchType::FunctionCall : BranchType::LocalBranch;
|
||||
}
|
||||
} else if (field1 == 1 && (instruction & EIF_PERFORM_BLR)) {
|
||||
type = BranchType::Return;
|
||||
} else if (field1 == 1 && (instruction & EIF_PERFORM_BLR)) { // classify HACK instruction
|
||||
type = instruction & EIF_USE_BRANCH ? BranchType::FunctionCall : BranchType::Return;
|
||||
} else if (field1 == 1 && (instruction & EIF_USE_BRANCH)) {
|
||||
type = BranchType::LocalBranch;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
@ -15,9 +15,19 @@ std::vector<StaticFunc> g_ppu_func_subs;
|
||||
|
||||
u32 add_ppu_func(ModuleFunc func)
|
||||
{
|
||||
if (g_ppu_func_list.empty())
|
||||
{
|
||||
// prevent relocations if the array growths, must be sizeof(ModuleFunc) * 0x8000 ~~ about 1 MB of memory
|
||||
g_ppu_func_list.reserve(0x8000);
|
||||
}
|
||||
|
||||
for (auto& f : g_ppu_func_list)
|
||||
{
|
||||
assert(f.id != func.id);
|
||||
if (f.id == func.id)
|
||||
{
|
||||
// TODO: if NIDs overlap or if the same function is added twice
|
||||
assert(!"add_ppu_func(): NID already exists");
|
||||
}
|
||||
}
|
||||
|
||||
g_ppu_func_list.push_back(func);
|
||||
@ -93,15 +103,56 @@ void execute_ppu_func_by_index(PPUThread& CPU, u32 index)
|
||||
{
|
||||
if (auto func = get_ppu_func_by_index(index))
|
||||
{
|
||||
auto old_last_syscall = CPU.m_last_syscall;
|
||||
CPU.m_last_syscall = func->id;
|
||||
|
||||
// save RTOC if necessary
|
||||
if (index & EIF_SAVE_RTOC)
|
||||
{
|
||||
// save RTOC if necessary
|
||||
vm::write64(vm::cast(CPU.GPR[1] + 0x28), CPU.GPR[2]);
|
||||
}
|
||||
|
||||
// save old syscall/NID value
|
||||
auto old_last_syscall = CPU.m_last_syscall;
|
||||
|
||||
// branch directly to the LLE function
|
||||
if (index & EIF_USE_BRANCH)
|
||||
{
|
||||
// for example, FastCall2 can't work with functions which do user level context switch
|
||||
|
||||
if (old_last_syscall)
|
||||
{
|
||||
throw "Unfortunately, this function cannot be called from the callback.";
|
||||
}
|
||||
|
||||
if (!func->lle_func)
|
||||
{
|
||||
throw "Wrong usage: LLE function not set.";
|
||||
}
|
||||
|
||||
if (func->flags & MFF_FORCED_HLE)
|
||||
{
|
||||
throw "Wrong usage: Forced HLE enabled.";
|
||||
}
|
||||
|
||||
if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
LOG_NOTICE(HLE, "Branch to LLE function: %s", SysCalls::GetFuncName(func->id));
|
||||
}
|
||||
|
||||
if (index & EIF_PERFORM_BLR)
|
||||
{
|
||||
throw "TODO: Branch with link";
|
||||
// CPU.LR = CPU.PC + 4;
|
||||
}
|
||||
|
||||
const auto data = vm::get_ptr<be_t<u32>>(func->lle_func.addr());
|
||||
CPU.SetBranch(data[0]);
|
||||
CPU.GPR[2] = data[1]; // set rtoc
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// change current syscall/NID value
|
||||
CPU.m_last_syscall = func->id;
|
||||
|
||||
if (func->lle_func && !(func->flags & MFF_FORCED_HLE))
|
||||
{
|
||||
// call LLE function if available
|
||||
@ -427,6 +478,15 @@ bool patch_ppu_import(u32 addr, u32 index)
|
||||
|
||||
using namespace PPU_instr;
|
||||
|
||||
if (index >= g_ppu_func_list.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const u32 imm = (g_ppu_func_list[index].flags & MFF_NO_RETURN) && !(g_ppu_func_list[index].flags & MFF_FORCED_HLE)
|
||||
? index | EIF_USE_BRANCH
|
||||
: index | EIF_PERFORM_BLR;
|
||||
|
||||
// check different patterns:
|
||||
|
||||
if (vm::check_addr(addr, 32) &&
|
||||
@ -439,7 +499,7 @@ bool patch_ppu_import(u32 addr, u32 index)
|
||||
data[6] == MTCTR(r0) &&
|
||||
data[7] == BCTR())
|
||||
{
|
||||
vm::write32(addr, HACK(index | EIF_SAVE_RTOC | EIF_PERFORM_BLR));
|
||||
vm::write32(addr, HACK(imm | EIF_SAVE_RTOC));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -467,7 +527,7 @@ bool patch_ppu_import(u32 addr, u32 index)
|
||||
sub[0xd] == MTLR(r0) &&
|
||||
sub[0xe] == BLR())
|
||||
{
|
||||
vm::write32(addr, HACK(index | EIF_PERFORM_BLR));
|
||||
vm::write32(addr, HACK(imm));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -490,7 +550,7 @@ bool patch_ppu_import(u32 addr, u32 index)
|
||||
data[0xe] == MTLR(r0) &&
|
||||
data[0xf] == BLR())
|
||||
{
|
||||
vm::write32(addr, HACK(index | EIF_PERFORM_BLR));
|
||||
vm::write32(addr, HACK(imm));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -511,7 +571,7 @@ bool patch_ppu_import(u32 addr, u32 index)
|
||||
data[0xd] == MTLR(r0) &&
|
||||
data[0xe] == BLR())
|
||||
{
|
||||
vm::write32(addr, HACK(index | EIF_PERFORM_BLR));
|
||||
vm::write32(addr, HACK(imm));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -531,7 +591,7 @@ bool patch_ppu_import(u32 addr, u32 index)
|
||||
data[0xc] == LD(r2, r1, 0x28) &&
|
||||
data[0xd] == BLR())
|
||||
{
|
||||
vm::write32(addr, HACK(index | EIF_PERFORM_BLR));
|
||||
vm::write32(addr, HACK(imm));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ class Module;
|
||||
enum : u32
|
||||
{
|
||||
MFF_FORCED_HLE = (1 << 0), // always call HLE function
|
||||
MFF_NO_RETURN = (1 << 1), // uses EIF_USE_BRANCH flag with LLE, ignored with MFF_FORCED_HLE
|
||||
};
|
||||
|
||||
// flags passed with index
|
||||
@ -16,8 +17,9 @@ enum : u32
|
||||
{
|
||||
EIF_SAVE_RTOC = (1 << 25), // save RTOC in [SP+0x28] before calling HLE/LLE function
|
||||
EIF_PERFORM_BLR = (1 << 24), // do BLR after calling HLE/LLE function
|
||||
EIF_USE_BRANCH = (1 << 23), // do only branch, LLE must be set, last_syscall must be zero
|
||||
|
||||
EIF_FLAGS = 0x3000000, // all flags
|
||||
EIF_FLAGS = 0x3800000, // all flags
|
||||
};
|
||||
|
||||
struct ModuleFunc
|
||||
@ -121,6 +123,7 @@ bool patch_ppu_import(u32 addr, u32 index);
|
||||
|
||||
#define REG_FUNC(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), 0, &module, #name, bind_func(name)))
|
||||
#define REG_FUNC_FH(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), MFF_FORCED_HLE, &module, #name, bind_func(name)))
|
||||
#define REG_FUNC_NR(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), MFF_NO_RETURN, &module, #name, bind_func(name)))
|
||||
|
||||
#define REG_UNNAMED(module, nid) add_ppu_func(ModuleFunc(0x##nid, 0, &module, "_nid_"#nid, bind_func(_nid_##nid)))
|
||||
|
||||
|
@ -293,57 +293,57 @@ int cellFiberPpuUtilWorkerControlInitializeWithAttribute()
|
||||
|
||||
Module cellFiber("cellFiber", []()
|
||||
{
|
||||
REG_FUNC(cellFiber, _cellFiberPpuInitialize);
|
||||
REG_FUNC_NR(cellFiber, _cellFiberPpuInitialize);
|
||||
|
||||
REG_FUNC(cellFiber, _cellFiberPpuSchedulerAttributeInitialize);
|
||||
REG_FUNC(cellFiber, cellFiberPpuInitializeScheduler);
|
||||
REG_FUNC(cellFiber, cellFiberPpuFinalizeScheduler);
|
||||
REG_FUNC(cellFiber, cellFiberPpuRunFibers);
|
||||
REG_FUNC(cellFiber, cellFiberPpuCheckFlags);
|
||||
REG_FUNC(cellFiber, cellFiberPpuHasRunnableFiber);
|
||||
REG_FUNC_NR(cellFiber, _cellFiberPpuSchedulerAttributeInitialize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuInitializeScheduler);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuFinalizeScheduler);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuRunFibers);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuCheckFlags);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuHasRunnableFiber);
|
||||
|
||||
REG_FUNC(cellFiber, _cellFiberPpuAttributeInitialize);
|
||||
REG_FUNC(cellFiber, cellFiberPpuCreateFiber);
|
||||
REG_FUNC(cellFiber, cellFiberPpuExit);
|
||||
REG_FUNC(cellFiber, cellFiberPpuYield);
|
||||
REG_FUNC(cellFiber, cellFiberPpuJoinFiber);
|
||||
REG_FUNC(cellFiber, cellFiberPpuSelf);
|
||||
REG_FUNC(cellFiber, cellFiberPpuSendSignal);
|
||||
REG_FUNC(cellFiber, cellFiberPpuWaitSignal);
|
||||
REG_FUNC(cellFiber, cellFiberPpuWaitFlag);
|
||||
REG_FUNC(cellFiber, cellFiberPpuGetScheduler);
|
||||
REG_FUNC(cellFiber, cellFiberPpuSetPriority);
|
||||
REG_FUNC(cellFiber, cellFiberPpuCheckStackLimit);
|
||||
REG_FUNC_NR(cellFiber, _cellFiberPpuAttributeInitialize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuCreateFiber);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuExit);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuYield);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuJoinFiber);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuSelf);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuSendSignal);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuWaitSignal);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuWaitFlag);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuGetScheduler);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuSetPriority);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuCheckStackLimit);
|
||||
|
||||
REG_FUNC(cellFiber, _cellFiberPpuContextAttributeInitialize);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextInitialize);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextFinalize);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextRun);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextSwitch);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextSelf);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextReturnToThread);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextCheckStackLimit);
|
||||
REG_FUNC_NR(cellFiber, _cellFiberPpuContextAttributeInitialize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextInitialize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextFinalize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextRun);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextSwitch);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextSelf);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextReturnToThread);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextCheckStackLimit);
|
||||
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextRunScheduler);
|
||||
REG_FUNC(cellFiber, cellFiberPpuContextEnterScheduler);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextRunScheduler);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuContextEnterScheduler);
|
||||
|
||||
REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceInitialize);
|
||||
REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceFinalize);
|
||||
REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceStart);
|
||||
REG_FUNC(cellFiber, cellFiberPpuSchedulerTraceStop);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceInitialize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceFinalize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceStart);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuSchedulerTraceStop);
|
||||
|
||||
REG_FUNC(cellFiber, _cellFiberPpuUtilWorkerControlAttributeInitialize);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlRunFibers);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlInitialize);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlSetPollingMode);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlJoinFiber);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlDisconnectEventQueue);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlSendSignal);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlConnectEventQueueToSpurs);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlFinalize);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlWakeup);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlCreateFiber);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlShutdown);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlCheckFlags);
|
||||
REG_FUNC(cellFiber, cellFiberPpuUtilWorkerControlInitializeWithAttribute);
|
||||
REG_FUNC_NR(cellFiber, _cellFiberPpuUtilWorkerControlAttributeInitialize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlRunFibers);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlInitialize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlSetPollingMode);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlJoinFiber);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlDisconnectEventQueue);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlSendSignal);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlConnectEventQueueToSpurs);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlFinalize);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlWakeup);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlCreateFiber);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlShutdown);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlCheckFlags);
|
||||
REG_FUNC_NR(cellFiber, cellFiberPpuUtilWorkerControlInitializeWithAttribute);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user