tp/libs/dolphin/os/OS.c

838 lines
25 KiB
C

//
// Generated By: dol2asm
// Translation Unit: OS
//
#include "dolphin/os/OS.h"
#include "dol2asm.h"
#include "dolphin/base/PPCArch.h"
#include "dolphin/db/db.h"
#include "dolphin/dvd/dvd.h"
#define OS_CURRENTCONTEXT_PADDR 0x00C0
#define OS_EXCEPTIONTABLE_ADDR 0x3000
#define OS_DBJUMPPOINT_ADDR 0x60
#define OS_BI2_DEBUG_ADDRESS 0x800000F4
#define OS_DEBUG_ADDRESS_2 0x800030E9
#define DEBUGFLAG_ADDR 0x800030E8
//
// External References:
//
SECTION_INIT void memset();
SECTION_INIT void memcpy();
void PPCMtmmcr0();
void PPCMtmmcr1();
void PPCMtpmc1();
void PPCMtpmc2();
void PPCMtpmc3();
void PPCMtpmc4();
void PPCMthid2();
void PPCDisableSpeculation();
void PPCSetFpNonIEEEMode();
void OSInitAlarm();
void __OSInitAudioSystem();
void __OSCacheInit();
void __OSContextInit();
void __OSInterruptInit();
void __OSModuleInit();
void __OSInitMemoryProtection();
void __OSResetSWInterruptHandler();
void __OSInitSram();
void __OSInitSystemCall();
void __OSThreadInit();
void EXIInit();
void SIInit();
BOOL __DBIsExceptionMarked(__OSException);
void EnableMetroTRKInterrupts();
extern u32 __DVDLongFileNameFlag;
extern u32 __PADSpec;
void _epilog();
void regist__9daBgObj_cFP4dBgW();
//
// Declarations:
//
/* ############################################################################################## */
/* 80451600-80451604 000B00 0004+00 2/2 0/0 0/0 .sbss BootInfo */
static OSBootInfo* BootInfo;
/* 80451604-80451608 000B04 0004+00 2/2 0/0 0/0 .sbss BI2DebugFlag */
static volatile u32* BI2DebugFlag;
/* 80451608-8045160C 000B08 0004+00 1/1 0/0 0/0 .sbss BI2DebugFlagHolder */
static u32* BI2DebugFlagHolder;
/* 80451630-80451634 000B30 0004+00 1/1 1/1 0/0 .sbss __OSStartTime */
OSTime __OSStartTime;
/* 80451628-80451630 000B28 0004+04 1/1 1/1 0/0 .sbss __OSInIPL */
extern BOOL __OSInIPL;
BOOL __OSInIPL;
/* 80451624-80451628 000B24 0004+00 3/3 0/0 0/0 .sbss OSExceptionTable */
extern OSExceptionHandler* OSExceptionTable;
OSExceptionHandler* OSExceptionTable;
/* 80451620-80451624 000B20 0004+00 1/1 0/0 0/0 .sbss AreWeInitialized */
extern BOOL AreWeInitialized;
BOOL AreWeInitialized;
/* 80451618-80451620 000B18 0008+00 1/1 0/0 0/0 .sbss ZeroPS */
extern f64 ZeroPS;
f64 ZeroPS;
/* 80451610-80451618 000B10 0008+00 1/1 0/0 0/0 .sbss ZeroF */
extern f64 ZeroF;
f64 ZeroF;
/* 8045160C-80451610 000B0C 0004+00 1/1 1/1 0/0 .sbss __OSIsGcam */
extern BOOL __OSIsGcam;
BOOL __OSIsGcam;
/* 80339DD4-80339EFC 334714 0128+00 0/0 1/1 0/0 .text __OSFPRInit */
asm void __OSFPRInit(void) {
// clang-format off
nofralloc
mfmsr r3
ori r3, r3, 0x2000
mtmsr r3
mfspr r3, 0x398
rlwinm. r3, r3, 3, 0x1f, 0x1f
beq skip_ps_init
lis r3, ZeroPS@ha
addi r3, r3, ZeroPS@l
psq_l f0, 0(r3), 0, 0
ps_mr f1, f0
ps_mr f2, f0
ps_mr f3, f0
ps_mr f4, f0
ps_mr f5, f0
ps_mr f6, f0
ps_mr f7, f0
ps_mr f8, f0
ps_mr f9, f0
ps_mr f10, f0
ps_mr f11, f0
ps_mr f12, f0
ps_mr f13, f0
ps_mr f14, f0
ps_mr f15, f0
ps_mr f16, f0
ps_mr f17, f0
ps_mr f18, f0
ps_mr f19, f0
ps_mr f20, f0
ps_mr f21, f0
ps_mr f22, f0
ps_mr f23, f0
ps_mr f24, f0
ps_mr f25, f0
ps_mr f26, f0
ps_mr f27, f0
ps_mr f28, f0
ps_mr f29, f0
ps_mr f30, f0
ps_mr f31, f0
skip_ps_init:
lfd f0, ZeroF(r13)
fmr f1, f0
fmr f2, f0
fmr f3, f0
fmr f4, f0
fmr f5, f0
fmr f6, f0
fmr f7, f0
fmr f8, f0
fmr f9, f0
fmr f10, f0
fmr f11, f0
fmr f12, f0
fmr f13, f0
fmr f14, f0
fmr f15, f0
fmr f16, f0
fmr f17, f0
fmr f18, f0
fmr f19, f0
fmr f20, f0
fmr f21, f0
fmr f22, f0
fmr f23, f0
fmr f24, f0
fmr f25, f0
fmr f26, f0
fmr f27, f0
fmr f28, f0
fmr f29, f0
fmr f30, f0
fmr f31, f0
mtfsf 0xff, f0
blr
// clang-format on
}
/* 80339EFC-80339F24 33483C 0028+00 0/0 5/5 0/0 .text OSGetConsoleType */
u32 OSGetConsoleType(void) {
if (BootInfo == NULL || BootInfo->console_type == 0) {
return OS_CONSOLE_ARTHUR;
}
return BootInfo->console_type;
}
/* ############################################################################################## */
/* 8044BA60-8044BA80 078780 0020+00 2/2 0/0 0/0 .bss DriveInfo */
static DVDDriveInfo DriveInfo;
void* __OSSavedRegionStart;
void* __OSSavedRegionEnd;
extern u32 BOOT_REGION_START : 0x812FDFF0; //(*(u32 *)0x812fdff0)
extern u32 BOOT_REGION_END : 0x812FDFEC; //(*(u32 *)0x812fdfec)
inline void ClearArena(void) {
if ((u32)(OSGetResetCode() + 0x80000000) != 0U) {
__OSSavedRegionStart = 0U;
__OSSavedRegionEnd = 0U;
memset(OSGetArenaLo(), 0U, (u32)OSGetArenaHi() - (u32)OSGetArenaLo());
return;
}
__OSSavedRegionStart = (void*)BOOT_REGION_START;
__OSSavedRegionEnd = (void*)BOOT_REGION_END;
if (BOOT_REGION_START == 0U) {
memset(OSGetArenaLo(), 0U, (u32)OSGetArenaHi() - (u32)OSGetArenaLo());
return;
}
if ((u32)OSGetArenaLo() < (u32)__OSSavedRegionStart) {
if ((u32)OSGetArenaHi() <= (u32)__OSSavedRegionStart) {
memset((u32)OSGetArenaLo(), 0U, (u32)OSGetArenaHi() - (u32)OSGetArenaLo());
return;
}
memset(OSGetArenaLo(), 0U, (u32)__OSSavedRegionStart - (u32)OSGetArenaLo());
if ((u32)OSGetArenaHi() > (u32)__OSSavedRegionEnd) {
memset((u32)__OSSavedRegionEnd, 0, (u32)OSGetArenaHi() - (u32)__OSSavedRegionEnd);
}
}
}
/* 80339F24-80339F60 334864 003C+00 1/1 0/0 0/0 .text InquiryCallback */
static void InquiryCallback(u32 result, DVDCommandBlock* block) {
switch (block->state) {
case 0:
__OSDeviceCode = (u16)(0x8000 | DriveInfo.device_code);
break;
default:
__OSDeviceCode = 1;
break;
}
}
/* ############################################################################################## */
/* 803CF288-803CF2CC 02C3A8 0044+00 3/2 0/0 0/0 .data @1 */
SECTION_DATA static char lit_1[68] =
"<< Dolphin SDK - OS release build: Nov 10 2004 06:26:41 (0x2301) >>";
/* 803CF2CC-803CF2DC 02C3EC 000D+03 0/1 0/0 0/0 .data @105 */
#pragma push
#pragma force_active on
SECTION_DATA static char lit_105[13] = "\nDolphin OS\n";
#pragma pop
/* 803CF2DC-803CF2F4 02C3FC 0016+02 0/1 0/0 0/0 .data @106 */
#pragma push
#pragma force_active on
SECTION_DATA static char lit_106[22] = "Kernel built : %s %s\n";
#pragma pop
/* 803CF2F4-803CF300 02C414 000C+00 0/1 0/0 0/0 .data @107 */
#pragma push
#pragma force_active on
SECTION_DATA static char lit_107[12] = "Nov 10 2004";
#pragma pop
/* 803CF300-803CF30C 02C420 0009+03 0/1 0/0 0/0 .data @108 */
#pragma push
#pragma force_active on
SECTION_DATA static char lit_108[9] = "06:26:41";
#pragma pop
/* 803CF30C-803CF31C 02C42C 0010+00 0/1 0/0 0/0 .data @109 */
#pragma push
#pragma force_active on
SECTION_DATA static char lit_109[16] = "Console Type : ";
#pragma pop
/* 803CF31C-803CF328 02C43C 000B+01 0/1 0/0 0/0 .data @110 */
#pragma push
#pragma force_active on
SECTION_DATA static char lit_110[11] = "Retail %d\n";
#pragma pop
/* 803CF328-803CF338 02C448 000E+02 0/1 0/0 0/0 .data @111 */
#pragma push
#pragma force_active on
SECTION_DATA static char lit_111[14] = "Mac Emulator\n";
#pragma pop
/* 803CF338-803CF348 02C458 000D+03 0/1 0/0 0/0 .data @112 */
#pragma push
#pragma force_active on
SECTION_DATA static char lit_112[13] = "PC Emulator\n";
#pragma pop
/* 803CF348-803CF358 02C468 000D+03 0/1 0/0 0/0 .data @113 */
#pragma push
#pragma force_active on
SECTION_DATA static char lit_113[13] = "EPPC Arthur\n";
#pragma pop
/* 803CF358-803CF368 02C478 000D+03 0/1 0/0 0/0 .data @114 */
#pragma push
#pragma force_active on
SECTION_DATA static char lit_114[13] = "EPPC Minnow\n";
#pragma pop
/* 803CF368-803CF384 02C488 0019+03 0/1 0/0 0/0 .data @115 */
#pragma push
#pragma force_active on
SECTION_DATA static char lit_115[25] = "Development HW%d (%08x)\n";
#pragma pop
/* 803CF384-803CF394 02C4A4 000E+02 0/1 0/0 0/0 .data @117 */
#pragma push
#pragma force_active on
SECTION_DATA static char lit_117[14] = "Memory %d MB\n";
#pragma pop
/* 803CF394-803CF3AC 02C4B4 0015+03 0/1 0/0 0/0 .data @118 */
#pragma push
#pragma force_active on
SECTION_DATA static char lit_118[21] = "Arena : 0x%x - 0x%x\n";
#pragma pop
/* 8044BA80-8044BAB0 0787A0 0030+00 0/1 0/0 0/0 .bss DriveBlock */
#pragma push
#pragma force_active on
static u8 DriveBlock[48];
#pragma pop
/* 8044BAB0-8044BAD0 0787D0 001C+04 0/1 1/1 0/0 .bss __OSRebootParams */
extern OSExecParams __OSRebootParams;
OSExecParams __OSRebootParams;
/* 80450980-80450984 -00001 0004+00 1/1 0/0 0/0 .sdata __OSVersion */
SECTION_SDATA static void* __OSVersion = (void*)&lit_1;
/* 80450984-8045098C 000404 0006+02 1/1 0/0 0/0 .sdata @116 */
SECTION_SDATA static char lit_116[6] = "%08x\n";
extern void* __ArenaHi;
extern void* _stack_end;
extern char _db_stack_end[];
/* 80339F60-8033A440 3348A0 04E0+00 0/0 2/2 0/0 .text OSInit */
#ifdef NONMATCHING
void OSInit(void) {
/*
Initializes the Dolphin operating system.
- most of the main operations get farmed out to other functions
- loading debug info and setting up heap bounds largely happen here
- a lot of OS reporting also gets controlled here
*/
// pretty sure this is the min(/max) amount of pointers etc for the stack to match
BI2Debug* DebugInfo;
void* debugArenaLo;
u32 inputConsoleType;
u32 tdev;
// check if we've already done all this or not
if ((BOOL)AreWeInitialized == FALSE) { // fantastic name
AreWeInitialized = TRUE; // flag to make sure we don't have to do this again
// SYSTEM //
__OSStartTime = __OSGetSystemTime();
OSDisableInterrupts();
__OSGetExecParams(&__OSRebootParams);
PPCMtmmcr0(0);
PPCMtmmcr1(0);
PPCMtpmc1(0);
PPCMtpmc2(0);
PPCMtpmc3(0);
PPCMtpmc4(0);
// set some PPC things
PPCDisableSpeculation();
PPCSetFpNonIEEEMode();
// DEBUG //
// load some DVD stuff
BI2DebugFlag = 0; // debug flag from the DVD BI2 header
BootInfo = (OSBootInfo*)OS_BASE_CACHED; // set pointer to BootInfo
__DVDLongFileNameFlag =
(u32)0; // flag to tell us whether we make it through the debug loading
// time to grab a bunch of debug info from the DVD
// the address for where the BI2 debug info is, is stored at OS_BI2_DEBUG_ADDRESS
DebugInfo = (BI2Debug*)*((u32*)OS_BI2_DEBUG_ADDRESS);
// if the debug info address exists, grab some debug info
if (DebugInfo != NULL) {
BI2DebugFlag = &DebugInfo->debugFlag; // debug flag from DVD BI2
__PADSpec = (u32)DebugInfo->padSpec; // some other info from DVD BI2
*((u8*)DEBUGFLAG_ADDR) = (u8)*BI2DebugFlag; // store flag in mem
*((u8*)OS_DEBUG_ADDRESS_2) = (u8)__PADSpec; // store other info in mem
} else if (BootInfo->arena_hi) { // if the top of the heap is already set
BI2DebugFlagHolder =
(u32*)*((u8*)DEBUGFLAG_ADDR); // grab whatever's stored at 0x800030E8
BI2DebugFlag = (u32*)&BI2DebugFlagHolder; // flag is then address of flag holder
__PADSpec = (u32) * ((u8*)OS_DEBUG_ADDRESS_2); // pad spec is whatever's at 0x800030E9
}
__DVDLongFileNameFlag = 1; // we made it through debug!
// HEAP //
// set up bottom of heap (ArenaLo)
// grab address from BootInfo if it exists, otherwise use default __ArenaLo
OSSetArenaLo((BootInfo->arena_lo == NULL) ? /* __ArenaLo */ 0 : BootInfo->arena_lo);
// if the input arenaLo is null, and debug flag location exists (and flag is < 2),
// set arenaLo to just past the end of the db stack
if ((BootInfo->arena_lo == NULL) && (BI2DebugFlag != 0) && (*BI2DebugFlag < 2)) {
debugArenaLo = (char*)(((u32)_db_stack_end + 0x1f) & ~0x1f);
OSSetArenaLo(debugArenaLo);
}
// set up top of heap (ArenaHi)
// grab address from BootInfo if it exists, otherwise use default __ArenaHi
OSSetArenaHi((BootInfo->arena_hi == NULL) ? /* __ArenaHi */ 0 : BootInfo->arena_hi);
// OS INIT AND REPORT //
// initialise a whole bunch of OS stuff
OSExceptionInit();
__OSInitSystemCall();
OSInitAlarm();
__OSModuleInit();
__OSInterruptInit();
__OSSetInterruptHandler(OS_INTR_PI_RSW, (void*)__OSResetSWInterruptHandler);
__OSContextInit();
__OSCacheInit();
EXIInit();
SIInit();
__OSInitSram();
__OSThreadInit();
__OSInitAudioSystem();
PPCMthid2(PPCMfhid2() & 0xBFFFFFFF);
if ((BOOL)__OSInIPL == FALSE) {
__OSInitMemoryProtection();
}
// begin OS reporting
OSReport("\nDolphin OS\n");
OSReport("Kernel built : %s %s\n", "Nov 10 2004", "06:26:41");
OSReport("Console Type : ");
// this is a function in the same file, but it doesn't seem to match
// inputConsoleType = OSGetConsoleType();
// inputConsoleType = (BootInfo == NULL || (inputConsoleType = BootInfo->consoleType) == 0)
// ? 0x10000002 : BootInfo->consoleType;
if (BootInfo == NULL || (inputConsoleType = BootInfo->console_type) == 0) {
inputConsoleType = OS_CONSOLE_ARTHUR; // default console type
} else {
inputConsoleType = BootInfo->console_type;
}
// work out what console type this corresponds to and report it
// consoleTypeSwitchHi = inputConsoleType & 0xF0000000;
switch (inputConsoleType & 0xffff0000) { // check "first" byte
case OS_CONSOLE_RETAIL:
OSReport("Retail %d\n", inputConsoleType);
break;
default:
switch (inputConsoleType & 0x0000ffff) { // if "first" byte is 2, check "the rest"
case OS_CONSOLE_EMULATOR:
OSReport("Mac Emulator\n");
break;
case OS_CONSOLE_PC_EMULATOR:
OSReport("PC Emulator\n");
break;
case OS_CONSOLE_ARTHUR:
OSReport("EPPC Arthur\n");
break;
case OS_CONSOLE_MINNOW:
OSReport("EPPC Minnow\n");
break;
default:
tdev = ((u32)inputConsoleType & 0x0000ffff);
OSReport("Development HW%d (%08x)\n", tdev - 3, inputConsoleType);
break;
}
break;
}
// report memory size
OSReport("Memory %d MB\n", (u32)BootInfo->memory_size >> 0x14U);
// report heap bounds
OSReport("Arena : 0x%x - 0x%x\n", OSGetArenaLo(), OSGetArenaHi());
// report OS version
OSRegisterVersion(__OSVersion);
// if location of debug flag exists, and flag is >= 2, enable MetroTRKInterrupts
if (BI2DebugFlag && ((*BI2DebugFlag) >= 2)) {
EnableMetroTRKInterrupts();
}
// free up memory and re-enable things
ClearArena();
OSEnableInterrupts();
// check if we can load OS from IPL; if not, grab it from DVD (?)
if ((BOOL)__OSInIPL == FALSE) {
DVDInit();
if ((BOOL)__OSIsGcam) {
__OSDeviceCode = 0x9000;
return;
}
DCInvalidateRange(&DriveInfo, sizeof(DriveInfo));
DVDInquiryAsync((DVDCommandBlock*)&DriveBlock, &DriveInfo,
(DVDCBCallback)InquiryCallback);
}
}
}
#else
#pragma push
#pragma optimization_level 0
#pragma optimizewithasm off
asm void OSInit(void) {
nofralloc
#include "asm/dolphin/os/OS/OSInit.s"
}
#pragma pop
#endif
/* ############################################################################################## */
/* 803CF3AC-803CF3E8 02C4CC 003C+00 0/1 0/0 0/0 .data __OSExceptionLocations */
SECTION_DATA static u32 __OSExceptionLocations[] = {
0x00000100, // 0 System reset
0x00000200, // 1 Machine check
0x00000300, // 2 DSI - seg fault or DABR
0x00000400, // 3 ISI
0x00000500, // 4 External interrupt
0x00000600, // 5 Alignment
0x00000700, // 6 Program
0x00000800, // 7 FP Unavailable
0x00000900, // 8 Decrementer
0x00000C00, // 9 System call
0x00000D00, // 10 Trace
0x00000F00, // 11 Performance monitor
0x00001300, // 12 Instruction address breakpoint.
0x00001400, // 13 System management interrupt
0x00001700 // 14 Thermal interrupt
};
// dummy entry points to the OS Exception vector
void __OSEVStart(void);
void __OSDBINTSTART(void);
void __OSDBINTEND(void);
void __OSDBJUMPSTART(void);
void __OSDBJUMPEND(void);
#define NOP 0x60000000
/* 8033A440-8033A6C0 334D80 0280+00 1/1 0/0 0/0 .text OSExceptionInit */
static void OSExceptionInit(void) {
__OSException exception;
void* destAddr;
// These two vars help us change the exception number embedded
// in the exception handler code.
u32* opCodeAddr;
u32 oldOpCode;
// Address range of the actual code to be copied.
u8* handlerStart;
u32 handlerSize;
// Install the first level exception vector.
opCodeAddr = (u32*)__OSEVSetNumber;
oldOpCode = *opCodeAddr;
handlerStart = (u8*)__OSEVStart;
handlerSize = (u32)((u8*)__OSEVEnd - (u8*)__OSEVStart);
// Install the DB integrator, only if we are the first OSInit to be run
destAddr = (void*)OSPhysicalToCached(OS_DBJUMPPOINT_ADDR);
if (*(u32*)destAddr == 0) // Lomem should be zero cleared only once by BS2
{
DBPrintf("Installing OSDBIntegrator\n");
memcpy(destAddr, (void*)__OSDBINTSTART, (u32)__OSDBINTEND - (u32)__OSDBINTSTART);
DCFlushRangeNoSync(destAddr, (u32)__OSDBINTEND - (u32)__OSDBINTSTART);
__sync();
ICInvalidateRange(destAddr, (u32)__OSDBINTEND - (u32)__OSDBINTSTART);
}
// Copy the right vector into the table
for (exception = 0; exception < 15; exception++) {
if (BI2DebugFlag && (*BI2DebugFlag >= 2) && __DBIsExceptionMarked(exception)) {
// this DBPrintf is suspicious.
DBPrintf(">>> OSINIT: exception %d commandeered by TRK\n", exception);
continue;
}
// Modify the copy of code in text before transferring
// to the exception table.
*opCodeAddr = oldOpCode | exception;
// Modify opcodes at __DBVECTOR if necessary
if (__DBIsExceptionMarked(exception)) {
DBPrintf(">>> OSINIT: exception %d vectored to debugger\n", exception);
memcpy((void*)__DBVECTOR, (void*)__OSDBJUMPSTART,
(u32)__OSDBJUMPEND - (u32)__OSDBJUMPSTART);
} else {
// make sure the opcodes are still nop
u32* ops = (u32*)__DBVECTOR;
int cb;
for (cb = 0; cb < (u32)__OSDBJUMPEND - (u32)__OSDBJUMPSTART; cb += sizeof(u32)) {
*ops++ = NOP;
}
}
// Install the modified handler.
destAddr = (void*)OSPhysicalToCached(__OSExceptionLocations[(u32)exception]);
memcpy(destAddr, handlerStart, handlerSize);
DCFlushRangeNoSync(destAddr, handlerSize);
__sync();
ICInvalidateRange(destAddr, handlerSize);
}
// initialize pointer to exception table
OSExceptionTable = OSPhysicalToCached(OS_EXCEPTIONTABLE_ADDR);
// install default exception handlers
for (exception = 0; exception < 15; exception++) {
__OSSetExceptionHandler(exception, OSDefaultExceptionHandler);
}
// restore the old opcode, so that we can re-start an application without
// downloading the text segments
*opCodeAddr = oldOpCode;
DBPrintf("Exceptions initialized...\n");
}
/* 8033A6C0-8033A6E4 335000 0024+00 1/1 0/0 0/0 .text __OSDBIntegrator */
asm void __OSDBIntegrator(void) {
// clang-format off
nofralloc
entry __OSDBINTSTART
li r5, 0x40
mflr r3
stw r3, 0xc(r5)
lwz r3, 8(r5)
oris r3, r3, 0x8000
mtlr r3
li r3, 0x30
mtmsr r3
blr
entry __OSDBINTEND
// clang-format on
}
/* 8033A6E4-8033A6E8 335024 0004+00 1/1 0/0 0/0 .text __OSDBJump */
asm void __OSDBJump(void){
// clang-format off
nofralloc
entry __OSDBJUMPSTART
bla 0x60
entry __OSDBJUMPEND
// clang-format on
}
/* 8033A6E8-8033A704 335028 001C+00 1/1 3/3 0/0 .text __OSSetExceptionHandler */
OSExceptionHandler __OSSetExceptionHandler(__OSException exception, OSExceptionHandler handler) {
OSExceptionHandler old = OSExceptionTable[exception];
OSExceptionTable[exception] = handler;
return old;
}
/* 8033A704-8033A718 335044 0014+00 0/0 1/1 0/0 .text __OSGetExceptionHandler */
OSExceptionHandler __OSGetExceptionHandler(__OSException exception) {
return OSExceptionTable[exception];
}
/* 8033A718-8033A770 335058 0058+00 1/1 0/0 0/0 .text OSExceptionVector */
static asm void OSExceptionVector(void) {
// clang-format off
nofralloc
entry __OSEVStart
// Save r4 into SPRG0
mtsprg 0, r4
// Load current context physical address into r4
lwz r4, OS_CURRENTCONTEXT_PADDR
// Save r3 - r5 into the current context
stw r3, OS_CONTEXT_R3(r4)
mfsprg r3, 0
stw r3, OS_CONTEXT_R4(r4)
stw r5, OS_CONTEXT_R5(r4)
lhz r3, OS_CONTEXT_STATE(r4)
ori r3, r3, OS_CONTEXT_STATE_EXC
sth r3, OS_CONTEXT_STATE(r4)
// Save misc registers
mfcr r3
stw r3, OS_CONTEXT_CR(r4)
mflr r3
stw r3, OS_CONTEXT_LR(r4)
mfctr r3
stw r3, OS_CONTEXT_CTR(r4)
mfxer r3
stw r3, OS_CONTEXT_XER(r4)
mfsrr0 r3
stw r3, OS_CONTEXT_SRR0(r4)
mfsrr1 r3
stw r3, OS_CONTEXT_SRR1(r4)
mr r5, r3
entry __DBVECTOR
nop
// Set SRR1[IR|DR] to turn on address
// translation at the next RFI
mfmsr r3
ori r3, r3, 0x30
mtsrr1 r3
// This lets us change the exception number based on the
// exception we're installing.
entry __OSEVSetNumber
li r3, 0
// Load current context virtual address into r4
lwz r4, 0xd4(r0)
// Check non-recoverable interrupt
rlwinm. r5, r5, 0, MSR_RI_BIT, MSR_RI_BIT
bne recoverable
lis r5, OSDefaultExceptionHandler@ha
addi r5, r5, OSDefaultExceptionHandler@l
mtsrr0 r5
rfi
// NOT REACHED HERE
recoverable:
// Locate exception handler.
rlwinm r5, r3, 2, 0x16, 0x1d // r5 contains exception*4
lwz r5, OS_EXCEPTIONTABLE_ADDR(r5)
mtsrr0 r5
// Final state
// r3 - exception number
// r4 - pointer to context
// r5 - garbage
// srr0 - exception handler
// srr1 - address translation enabled, not yet recoverable
rfi
// NOT REACHED HERE
// The handler will restore state
entry __OSEVEnd
nop
// clang-format on
}
/* 8033A7B4-8033A80C 3350F4 0058+00 2/2 0/0 0/0 .text OSDefaultExceptionHandler */
static asm void OSDefaultExceptionHandler(register __OSException exception,
register OSContext* context) {
// clang-format off
nofralloc
stw r0, 0(context)
stw r1, 4(context)
stw r2, 8(context)
stmw r6, 0x18(context)
mfspr r0, 0x391
stw r0, 0x1a8(context)
mfspr r0, 0x392
stw r0, 0x1ac(context)
mfspr r0, 0x393
stw r0, 0x1b0(context)
mfspr r0, 0x394
stw r0, 0x1b4(context)
mfspr r0, 0x395
stw r0, 0x1b8(context)
mfspr r0, 0x396
stw r0, 0x1bc(context)
mfspr r0, 0x397
stw r0, 0x1c0(context)
mfdsisr r5
mfdar r6
stwu r1, -8(r1)
b __OSUnhandledException
// clang-format on
}
/* 8033A80C-8033A860 33514C 0054+00 0/0 1/1 0/0 .text __OSPSInit */
asm void __OSPSInit(void){
// clang-format off
nofralloc
mflr r0
stw r0, 4(r1)
stwu r1, -8(r1)
bl PPCMfhid2
oris r3, r3, 0xa000
bl PPCMthid2
bl ICFlashInvalidate
sync
li r3, 0
mtspr 0x390, r3
mtspr 0x391, r3
mtspr 0x392, r3
mtspr 0x393, r3
mtspr 0x394, r3
mtspr 0x395, r3
mtspr 0x396, r3
mtspr 0x397, r3
lwz r0, 0xc(r1)
addi r1, r1, 8
mtlr r0
blr
// clang-format on
}
vu32 __DIRegs[16] : 0xCC006000;
#define DI_CONFIG_IDX 0x9
#define DI_CONFIG_CONFIG_MASK 0xFF
/* 8033A860-8033A874 3351A0 0014+00 0/0 1/1 0/0 .text __OSGetDIConfig */
u32 __OSGetDIConfig(void) {
return (__DIRegs[DI_CONFIG_IDX] & DI_CONFIG_CONFIG_MASK);
}
/* 8033A874-8033A8A0 3351B4 002C+00 1/1 11/11 0/0 .text OSRegisterVersion */
void OSRegisterVersion(char* version) {
OSReport("%s\n", version);
}