// Dolphin OS context RE by org // OSContext.c // OSLoMem.h OSContext *__OSPhysicalContext AT_ADDRESS(OS_BASE_CACHED | 0x00C0); OSContext *__OSCurrentContext AT_ADDRESS(OS_BASE_CACHED | 0x00D4); [800000D8] - default thread (OSThread *) void __OSLoadFPUContext(???, OSContext *context) { if(context->state & OS_CONTEXT_STATE_FPSAVED) { FPSCR = context.fpscr; if(HID2[PSE]) { PS[0] = context->psf[0]; . . . PS[31] = context->psf[31]; } else { FPR[0] = context->fpr[0]; . . . FPR[31] = context->fpr[31]; } } } void __OSSaveFPUContext(???, ???, OSContext *context) { context->state |= OS_CONTEXT_STATE_FPSAVED; // save FPRs context->fpr[0] = FPR[0]; . . . context->fpr[31] = FPR[31]; // save FP state/control context.fpscr = FPSCR; // save paireds if(HID2[PSE]) { context->fpr[0] = FPR[0]; . . . context->fpr[31] = FPR[31]; } } void OSLoadFPUContext(OSContext *context) { __OSLoadFPUContext(???, context); } void OSSaveFPUContext(OSContext *context) { __OSSaveFPUContext(???, ???, context); } void OSSetCurrentContext(OSContext *context) { __OSCurrentContext = context; __OSPhysicalContext= OSCachedToPhysical(context); if(context == __OSDefaultThread->context) { context.srr1 |= MSR_FP; // floating-point available MSR[RI] = 1; // recoverable interrupt } else { context.srr1 &= ~MSR_FP; MSR[FP] = 0; MSR[RI] = 1; __asm isync } } OSContext *OSGetCurrentContext() { return __OSCurrentContext; } u32 OSSaveContext(OSContext *context) { // save GPRs context.gpr[13...31] = GPR[13...31]; // save quantization regs (GQR0 is always zero) context.gqr[1...7] = GQR[1...7]; // others context.cr = CR; context.srr0 = context.lr = LR; context.srr1 = MSR; context.ctr = CTR; context.xer = XER; // compiler pointers context.gpr[1] = SP; context.gpr[2] = SDA1; context.gpr[12] = 1; return 0; } void OSLoadContext(OSContext *context) { if( context.srr0 >= __RAS_OSDisableInterrupts_begin && context.srr0 <= __RAS_OSDisableInterrupts_end ) { context.srr0 = __RAS_OSDisableInterrupts_begin; } // restore GPRs GPR[0...2] = context.gpr[0...2]; if(context.state & OS_CONTEXT_STATE_EXC) { context.state &= ~OS_CONTEXT_STATE_EXC; GPR[5...31] = context.gpr[5...31]; } else GPR[13...31] = context.gpr[13...31]; // restore GQRs (GQR0 is always 0) GQR[1...7] = context.gqr[1...7]; // others CR = context.cr; LR = context.lr; CTR = context.ctr; XER = context.xer; MSR[IE] = MSR[RI] = 0; SRR0 = context.srr0; SRR1 = context.srr1; GPR[4] = context.gpr[4]; GPR[3] = context.gpr[3]; // return from interrupt (update PC and MSR) __asm rfi } u32 OSGetStackPointer() { return GPR[1]; // SP } u32 OSSwitchStack(u32 newsp) { u32 oldsp = GPR[1]; GPR[1] = newsp; return oldsp; } int OSSwitchFiber(u32 pc, u32 newsp) { u32 oldsp = GPR[1]; int rval; GPR[1] = newsp; rval = (void *)pc(); GPR[1] = oldsp; return rval; } void OSClearContext(OSContext *context) { context.mode = context.state = 0; if(context == __OSDefaultThread->context) { __OSDefaultThread = NULL; } } void OSInitContext(OSContext *context, u32 pc, u32 sp) { context.srr0 = pc; context.gpr[1] = sp; context.srr1 = 0x9032; context.cr = context.xer = 0; context.gpr[2] = GPR[2]; context.gpr[3...31] = 0; context.gpr[13] = GPR[13]; context.gqr[0...7] = 0; OSClearContext(context); } void OSDumpContext(OSContext *context) { ... } void OSSwitchFPUContext(__OSException exception, OSContext *context) { ... } void __OSContextInit() { __OSSetExceptionHandler( __OS_EXCEPTION_FLOATING_POINT, OSSwitchFPUContext ); DBPrintf("FPU-unavailable handler installed\n"); } void OSFillFPUContext(OSContext *context) { ... }