mirror of https://github.com/zeldaret/tp.git
232 lines
8.3 KiB
C
232 lines
8.3 KiB
C
#include "dolphin/os/OSError.h"
|
|
#include "dolphin/base/PPCArch.h"
|
|
#include "dolphin/dsp.h"
|
|
#include "dolphin/dvd/dvdlow.h"
|
|
#include "dolphin/os.h"
|
|
|
|
OSThread* __OSCurrentThread : (OS_BASE_CACHED | 0x00E4);
|
|
OSThreadQueue __OSActiveThreadQueue : (OS_BASE_CACHED | 0x00DC);
|
|
volatile OSContext* __OSFPUContext : (OS_BASE_CACHED | 0x00D8);
|
|
|
|
extern volatile u32 __OSLastInterruptSrr0;
|
|
extern volatile s16 __OSLastInterrupt;
|
|
extern volatile OSTime __OSLastInterruptTime;
|
|
|
|
/* 8044BAD0-8044BB20 0787F0 0044+0C 2/2 2/2 0/0 .bss __OSErrorTable */
|
|
extern OSErrorHandlerEx __OSErrorTable[16];
|
|
OSErrorHandlerEx __OSErrorTable[16];
|
|
|
|
/* 804509A0-804509A4 000420 0004+00 1/1 2/2 0/0 .sdata __OSFpscrEnableBits */
|
|
#define FPSCR_ENABLE (FPSCR_VE | FPSCR_OE | FPSCR_UE | FPSCR_ZE | FPSCR_XE)
|
|
extern u32 __OSFpscrEnableBits = FPSCR_ENABLE;
|
|
|
|
__declspec(weak) void OSReport(const char* msg, ...) {
|
|
va_list marker;
|
|
|
|
va_start(marker, msg);
|
|
vprintf(msg, marker);
|
|
va_end(marker);
|
|
}
|
|
|
|
__declspec(weak) void OSVReport(const char* msg, va_list list) {
|
|
vprintf(msg, list);
|
|
}
|
|
|
|
__declspec(weak) void OSPanic(const char* file, s32 line, const char* msg, ...) {
|
|
va_list marker;
|
|
u32 i;
|
|
u32* p;
|
|
|
|
OSDisableInterrupts();
|
|
va_start(marker, msg);
|
|
vprintf(msg, marker);
|
|
va_end(marker);
|
|
OSReport(" in \"%s\" on line %d.\n", file, line);
|
|
|
|
// actually useful for debugging- stack crawl
|
|
OSReport("\nAddress: Back Chain LR Save\n");
|
|
for (i = 0, p = (u32*)OSGetStackPointer(); // get current stack pointer
|
|
p && (u32)p != 0xffffffff && i++ < 16; p = (u32*)*p) // get caller stack pointer
|
|
{
|
|
OSReport("0x%08x: 0x%08x 0x%08x\n", p, p[0], p[1]);
|
|
}
|
|
|
|
PPCHalt();
|
|
}
|
|
|
|
/* 8033C580-8033C798 336EC0 0218+00 0/0 4/4 0/0 .text OSSetErrorHandler */
|
|
OSErrorHandler OSSetErrorHandler(OSError error, OSErrorHandler handler) {
|
|
OSErrorHandlerEx oldHandler;
|
|
BOOL enabled;
|
|
|
|
enabled = OSDisableInterrupts();
|
|
oldHandler = __OSErrorTable[error];
|
|
__OSErrorTable[error] = (OSErrorHandlerEx)handler;
|
|
|
|
if (error == EXCEPTION_FLOATING_POINT_EXCEPTION) {
|
|
u32 msr;
|
|
u32 fpscr;
|
|
OSThread* thread;
|
|
|
|
msr = PPCMfmsr();
|
|
PPCMtmsr(msr | MSR_FP);
|
|
fpscr = PPCMffpscr();
|
|
if (handler) {
|
|
for (thread = __OSActiveThreadQueue.head; thread;
|
|
thread = thread->active_threads_link.next)
|
|
{
|
|
thread->context.srr1 |= MSR_FE0 | MSR_FE1;
|
|
if ((thread->context.state & OS_CONTEXT_STATE_FPSAVED) == 0) {
|
|
int i;
|
|
thread->context.state |= OS_CONTEXT_STATE_FPSAVED;
|
|
for (i = 0; i < 32; ++i) {
|
|
*(u64*)&thread->context.fpr[i] = (u64)0xffffffffffffffffLL;
|
|
*(u64*)&thread->context.ps[i] = (u64)0xffffffffffffffffLL;
|
|
}
|
|
thread->context.fpscr = FPSCR_NI;
|
|
}
|
|
thread->context.fpscr |= __OSFpscrEnableBits & FPSCR_ENABLE;
|
|
thread->context.fpscr &=
|
|
~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI |
|
|
FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX |
|
|
FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI);
|
|
}
|
|
fpscr |= __OSFpscrEnableBits & FPSCR_ENABLE;
|
|
msr |= MSR_FE0 | MSR_FE1;
|
|
} else {
|
|
for (thread = __OSActiveThreadQueue.head; thread;
|
|
thread = thread->active_threads_link.next)
|
|
{
|
|
thread->context.srr1 &= ~(MSR_FE0 | MSR_FE1);
|
|
thread->context.fpscr &= ~FPSCR_ENABLE;
|
|
thread->context.fpscr &=
|
|
~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI |
|
|
FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX |
|
|
FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI);
|
|
}
|
|
fpscr &= ~FPSCR_ENABLE;
|
|
msr &= ~(MSR_FE0 | MSR_FE1);
|
|
}
|
|
|
|
fpscr &= ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI |
|
|
FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX | FPSCR_ZX |
|
|
FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI);
|
|
|
|
PPCMtfpscr(fpscr);
|
|
PPCMtmsr(msr);
|
|
}
|
|
|
|
OSRestoreInterrupts(enabled);
|
|
return oldHandler;
|
|
}
|
|
|
|
/* 8033C798-8033CA80 3370D8 02E8+00 1/0 2/2 0/0 .text __OSUnhandledException */
|
|
void __OSUnhandledException(__OSException exception, OSContext* context, u32 dsisr, u32 dar) {
|
|
OSTime now;
|
|
|
|
now = OSGetTime();
|
|
|
|
if (!(context->srr1 & 2)) {
|
|
OSReport("Non-recoverable Exception %d", exception);
|
|
|
|
} else {
|
|
if (exception == EXCEPTION_PROGRAM && (context->srr1 & (0x80000000 >> 11)) &&
|
|
__OSErrorTable[EXCEPTION_FLOATING_POINT_EXCEPTION] != 0)
|
|
{
|
|
u32 fpscr;
|
|
u32 msr;
|
|
|
|
exception = EXCEPTION_FLOATING_POINT_EXCEPTION;
|
|
|
|
msr = PPCMfmsr();
|
|
PPCMtmsr(msr | 0x2000);
|
|
|
|
if (__OSFPUContext) {
|
|
OSSaveFPUContext((OSContext*)__OSFPUContext);
|
|
}
|
|
|
|
fpscr = PPCMffpscr();
|
|
fpscr &= ~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI |
|
|
FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX |
|
|
FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI);
|
|
PPCMtfpscr(fpscr);
|
|
|
|
PPCMtmsr(msr);
|
|
|
|
if (__OSFPUContext == context) {
|
|
OSDisableScheduler();
|
|
__OSErrorTable[exception](exception, context, dsisr, dar);
|
|
context->srr1 &= ~0x2000;
|
|
__OSFPUContext = NULL;
|
|
|
|
context->fpscr &=
|
|
~(FPSCR_VXVC | FPSCR_VXIMZ | FPSCR_VXZDZ | FPSCR_VXIDI | FPSCR_VXISI |
|
|
FPSCR_VXSNAN | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI | FPSCR_XX |
|
|
FPSCR_ZX | FPSCR_UX | FPSCR_OX | FPSCR_FX | FPSCR_FI);
|
|
OSEnableScheduler();
|
|
__OSReschedule();
|
|
} else {
|
|
context->srr1 &= ~0x2000;
|
|
__OSFPUContext = NULL;
|
|
}
|
|
|
|
OSLoadContext(context);
|
|
}
|
|
|
|
if (__OSErrorTable[exception]) {
|
|
OSDisableScheduler();
|
|
__OSErrorTable[exception](exception, context, dsisr, dar);
|
|
OSEnableScheduler();
|
|
__OSReschedule();
|
|
OSLoadContext(context);
|
|
}
|
|
|
|
if (exception == OS_ERROR_DECREMENTER) {
|
|
OSLoadContext(context);
|
|
}
|
|
|
|
OSReport("Unhandled Exception %d", exception);
|
|
}
|
|
|
|
OSReport("\n");
|
|
OSDumpContext(context);
|
|
OSReport("\nDSISR = 0x%08x DAR = 0x%08x\n", dsisr, dar);
|
|
OSReport("TB = 0x%016llx\n", now);
|
|
|
|
switch (exception) {
|
|
case EXCEPTION_DSI:
|
|
OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access "
|
|
"invalid address 0x%x (read from DAR)\n",
|
|
context->srr0, dar);
|
|
break;
|
|
case EXCEPTION_ISI:
|
|
OSReport("\nAttempted to fetch instruction from invalid address 0x%x "
|
|
"(read from SRR0)\n",
|
|
context->srr0);
|
|
break;
|
|
case EXCEPTION_ALIGNMENT:
|
|
OSReport("\nInstruction at 0x%x (read from SRR0) attempted to access "
|
|
"unaligned address 0x%x (read from DAR)\n",
|
|
context->srr0, dar);
|
|
break;
|
|
case EXCEPTION_PROGRAM:
|
|
OSReport("\nProgram exception : Possible illegal instruction/operation "
|
|
"at or around 0x%x (read from SRR0)\n",
|
|
context->srr0, dar);
|
|
break;
|
|
case EXCEPTION_MEMORY_PROTECTION:
|
|
OSReport("\n");
|
|
OSReport("AI DMA Address = 0x%04x%04x\n", __DSPRegs[DSP_DMA_START_HI],
|
|
__DSPRegs[DSP_DMA_START_LO]);
|
|
OSReport("ARAM DMA Address = 0x%04x%04x\n", __DSPRegs[DSP_ARAM_DMA_MM_HI],
|
|
__DSPRegs[DSP_ARAM_DMA_MM_LO]);
|
|
OSReport("DI DMA Address = 0x%08x\n", __DIRegs[5]);
|
|
break;
|
|
}
|
|
|
|
OSReport("\nLast interrupt (%d): SRR0 = 0x%08x TB = 0x%016llx\n", __OSLastInterrupt,
|
|
__OSLastInterruptSrr0, __OSLastInterruptTime);
|
|
|
|
PPCHalt();
|
|
}
|