mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
GPU: Allow relative jumps and calls.
These are tested in gpu/signals/jumps, so they ought to work. Doesn't seem like games generally use them, though.
This commit is contained in:
parent
5a6bf8b435
commit
511c822312
1 changed files with 27 additions and 5 deletions
|
@ -1397,31 +1397,53 @@ void GPUCommon::Execute_End(u32 op, u32 diff) {
|
|||
DEBUG_LOG(G3D, "Signal with Sync. signal/end: %04x %04x", signal, enddata);
|
||||
break;
|
||||
case PSP_GE_SIGNAL_JUMP:
|
||||
case PSP_GE_SIGNAL_RJUMP:
|
||||
case PSP_GE_SIGNAL_OJUMP:
|
||||
{
|
||||
trigger = false;
|
||||
currentList->signal = behaviour;
|
||||
// pc will be increased after we return, counteract that.
|
||||
u32 target = (((signal << 16) | enddata) & 0xFFFFFFFC) - 4;
|
||||
const char *targetType = "absolute";
|
||||
if (behaviour == PSP_GE_SIGNAL_RJUMP) {
|
||||
target += currentList->pc - 4;
|
||||
targetType = "relative";
|
||||
} else if (behaviour == PSP_GE_SIGNAL_OJUMP) {
|
||||
target = gstate_c.getRelativeAddress(target);
|
||||
targetType = "origin";
|
||||
}
|
||||
|
||||
if (!Memory::IsValidAddress(target)) {
|
||||
ERROR_LOG_REPORT(G3D, "Signal with Jump: bad address. signal/end: %04x %04x", signal, enddata);
|
||||
ERROR_LOG_REPORT(G3D, "Signal with Jump (%s): bad address. signal/end: %04x %04x", targetType, signal, enddata);
|
||||
UpdateState(GPUSTATE_ERROR);
|
||||
} else {
|
||||
UpdatePC(currentList->pc, target);
|
||||
currentList->pc = target;
|
||||
DEBUG_LOG(G3D, "Signal with Jump. signal/end: %04x %04x", signal, enddata);
|
||||
DEBUG_LOG(G3D, "Signal with Jump (%s). signal/end: %04x %04x", targetType, signal, enddata);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PSP_GE_SIGNAL_CALL:
|
||||
case PSP_GE_SIGNAL_RCALL:
|
||||
case PSP_GE_SIGNAL_OCALL:
|
||||
{
|
||||
trigger = false;
|
||||
currentList->signal = behaviour;
|
||||
// pc will be increased after we return, counteract that.
|
||||
u32 target = (((signal << 16) | enddata) & 0xFFFFFFFC) - 4;
|
||||
const char *targetType = "absolute";
|
||||
if (behaviour == PSP_GE_SIGNAL_RCALL) {
|
||||
target += currentList->pc - 4;
|
||||
targetType = "relative";
|
||||
} else if (behaviour == PSP_GE_SIGNAL_OCALL) {
|
||||
target = gstate_c.getRelativeAddress(target);
|
||||
targetType = "origin";
|
||||
}
|
||||
|
||||
if (currentList->stackptr == ARRAY_SIZE(currentList->stack)) {
|
||||
ERROR_LOG_REPORT(G3D, "Signal with Call: stack full. signal/end: %04x %04x", signal, enddata);
|
||||
ERROR_LOG_REPORT(G3D, "Signal with Call (%s): stack full. signal/end: %04x %04x", targetType, signal, enddata);
|
||||
} else if (!Memory::IsValidAddress(target)) {
|
||||
ERROR_LOG_REPORT(G3D, "Signal with Call: bad address. signal/end: %04x %04x", signal, enddata);
|
||||
ERROR_LOG_REPORT(G3D, "Signal with Call (%s): bad address. signal/end: %04x %04x", targetType, signal, enddata);
|
||||
UpdateState(GPUSTATE_ERROR);
|
||||
} else {
|
||||
// TODO: This might save/restore other state...
|
||||
|
@ -1431,7 +1453,7 @@ void GPUCommon::Execute_End(u32 op, u32 diff) {
|
|||
stackEntry.baseAddr = gstate.base;
|
||||
UpdatePC(currentList->pc, target);
|
||||
currentList->pc = target;
|
||||
DEBUG_LOG(G3D, "Signal with Call. signal/end: %04x %04x", signal, enddata);
|
||||
DEBUG_LOG(G3D, "Signal with Call (%s). signal/end: %04x %04x", targetType, signal, enddata);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Add table
Reference in a new issue