From 7bd2b5f649703d35cfa4e2563435cb9eb78ff018 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sun, 18 Dec 2022 10:32:00 -0800 Subject: [PATCH] Match and link OSMemory Former-commit-id: 8c11873cf2cc10039966e701cc359e65736e4957 --- asm/Dolphin/os/OSError.s | 12 +- asm/Dolphin/os/OSMemory.s | 4 +- configure.py | 2 +- include/dolphin/os.h | 1 + include/dolphin/os/OSError.h | 4 +- src/Dolphin/os/OSMemory.c | 247 +++++++++++++++++++++++++++++++++++ 6 files changed, 259 insertions(+), 11 deletions(-) create mode 100644 src/Dolphin/os/OSMemory.c diff --git a/asm/Dolphin/os/OSError.s b/asm/Dolphin/os/OSError.s index 6af16c4c..d9eaee8c 100644 --- a/asm/Dolphin/os/OSError.s +++ b/asm/Dolphin/os/OSError.s @@ -2,8 +2,8 @@ .section .bss .balign 8 -.global lbl_80541250 -lbl_80541250: +.global __OSErrorTable +__OSErrorTable: .skip 0x48 .section .data @@ -206,9 +206,9 @@ OSSetErrorHandler: /* 8037FB74 0037CAD4 93 81 00 20 */ stw r28, 0x20(r1) /* 8037FB78 0037CAD8 3B 84 00 00 */ addi r28, r4, 0 /* 8037FB7C 0037CADC 48 00 1A E5 */ bl OSDisableInterrupts -/* 8037FB80 0037CAE0 3C 80 80 54 */ lis r4, lbl_80541250@ha +/* 8037FB80 0037CAE0 3C 80 80 54 */ lis r4, __OSErrorTable@ha /* 8037FB84 0037CAE4 57 A5 13 BA */ rlwinm r5, r29, 2, 0xe, 0x1d -/* 8037FB88 0037CAE8 38 04 12 50 */ addi r0, r4, lbl_80541250@l +/* 8037FB88 0037CAE8 38 04 12 50 */ addi r0, r4, __OSErrorTable@l /* 8037FB8C 0037CAEC 57 A6 04 3E */ clrlwi r6, r29, 0x10 /* 8037FB90 0037CAF0 7C 80 2A 14 */ add r4, r0, r5 /* 8037FB94 0037CAF4 83 C4 00 00 */ lwz r30, 0(r4) @@ -343,7 +343,7 @@ lbl_8037FD44: .global __OSUnhandledException __OSUnhandledException: /* 8037FD70 0037CCD0 7C 08 02 A6 */ mflr r0 -/* 8037FD74 0037CCD4 3D 00 80 54 */ lis r8, lbl_80541250@ha +/* 8037FD74 0037CCD4 3D 00 80 54 */ lis r8, __OSErrorTable@ha /* 8037FD78 0037CCD8 90 01 00 04 */ stw r0, 4(r1) /* 8037FD7C 0037CCDC 3C E0 80 3F */ lis r7, lbl_803F1430@ha /* 8037FD80 0037CCE0 94 21 FF C0 */ stwu r1, -0x40(r1) @@ -352,7 +352,7 @@ __OSUnhandledException: /* 8037FD8C 0037CCEC 3B 24 00 00 */ addi r25, r4, 0 /* 8037FD90 0037CCF0 3B 45 00 00 */ addi r26, r5, 0 /* 8037FD94 0037CCF4 3B 66 00 00 */ addi r27, r6, 0 -/* 8037FD98 0037CCF8 3B C8 12 50 */ addi r30, r8, lbl_80541250@l +/* 8037FD98 0037CCF8 3B C8 12 50 */ addi r30, r8, __OSErrorTable@l /* 8037FD9C 0037CCFC 3B E7 14 30 */ addi r31, r7, lbl_803F1430@l /* 8037FDA0 0037CD00 48 00 56 09 */ bl OSGetTime /* 8037FDA4 0037CD04 80 B9 01 9C */ lwz r5, 0x19c(r25) diff --git a/asm/Dolphin/os/OSMemory.s b/asm/Dolphin/os/OSMemory.s index f4b9f70e..5b53d4ef 100644 --- a/asm/Dolphin/os/OSMemory.s +++ b/asm/Dolphin/os/OSMemory.s @@ -38,9 +38,9 @@ MEMIntrruptHandler: /* 80382A60 0037F9C0 38 00 00 00 */ li r0, 0 /* 80382A64 0037F9C4 94 21 FF F8 */ stwu r1, -8(r1) /* 80382A68 0037F9C8 A0 E3 40 24 */ lhz r7, 0x4024(r3) -/* 80382A6C 0037F9CC 3C 60 80 54 */ lis r3, lbl_80541250@ha +/* 80382A6C 0037F9CC 3C 60 80 54 */ lis r3, __OSErrorTable@ha /* 80382A70 0037F9D0 A0 C8 00 22 */ lhz r6, 0x22(r8) -/* 80382A74 0037F9D4 38 63 12 50 */ addi r3, r3, lbl_80541250@l +/* 80382A74 0037F9D4 38 63 12 50 */ addi r3, r3, __OSErrorTable@l /* 80382A78 0037F9D8 A0 A8 00 1E */ lhz r5, 0x1e(r8) /* 80382A7C 0037F9DC 50 E6 81 9E */ rlwimi r6, r7, 0x10, 6, 0xf /* 80382A80 0037F9E0 B0 08 00 20 */ sth r0, 0x20(r8) diff --git a/configure.py b/configure.py index 366ce8fa..bbc268f0 100755 --- a/configure.py +++ b/configure.py @@ -816,7 +816,7 @@ LIBS = [ ["Dolphin/os/OSInterrupt", True], ["Dolphin/os/OSLink", True], ["Dolphin/os/OSMessage", True], - ["Dolphin/os/OSMemory", False], + ["Dolphin/os/OSMemory", True], ["Dolphin/os/OSMutex", True], "Dolphin/os/OSReboot", ["Dolphin/os/OSReset", True], diff --git a/include/dolphin/os.h b/include/dolphin/os.h index 0235649c..7ca912e7 100644 --- a/include/dolphin/os.h +++ b/include/dolphin/os.h @@ -158,6 +158,7 @@ void OSFatal(GXColor fg, GXColor bg, const char* msg); #include #include #include +#include #include #include #include diff --git a/include/dolphin/os/OSError.h b/include/dolphin/os/OSError.h index 526e3ac9..015f9c12 100644 --- a/include/dolphin/os/OSError.h +++ b/include/dolphin/os/OSError.h @@ -28,9 +28,9 @@ extern "C" { #define OS_ERROR_MAX (OS_ERROR_FPE + 1) typedef u16 OSError; -typedef void OSErrorHandler(OSError, OSContext* context, ...); +typedef void (*OSErrorHandler)( OSError error, OSContext* context, ... ); -void OSSetErrorHandler(OSError code, OSErrorHandler* handler); +void OSSetErrorHandler(OSError code, OSErrorHandler handler); #ifdef __cplusplus } diff --git a/src/Dolphin/os/OSMemory.c b/src/Dolphin/os/OSMemory.c new file mode 100644 index 00000000..996d3479 --- /dev/null +++ b/src/Dolphin/os/OSMemory.c @@ -0,0 +1,247 @@ +#include + +#define TRUNC(n, a) (((u32)(n)) & ~((a)-1)) +#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1)) + +vu16 __MEMRegs[64] : 0xCC004000; +extern OSErrorHandler __OSErrorTable[16]; + +static BOOL OnReset(BOOL final); + +static OSResetFunctionInfo ResetFunctionInfo = { + OnReset, + 127, +}; + +#if NONMATCHING +static BOOL OnReset(BOOL final) { + if (final != FALSE) { + __MEMRegs[8] = 0xFF; + __OSMaskInterrupts(0xf0000000); + } + return TRUE; +} +#else +/* clang-format off */ +#pragma push +#pragma optimization_level 0 +#pragma optimizewithasm off +static asm BOOL OnReset(BOOL final) { + nofralloc + mflr r0 + cmpwi r3, 0 + stw r0, 4(r1) + stwu r1, -8(r1) + beq @1 + lis r3, __MEMRegs+16@ha + li r0, 0xff + sth r0, __MEMRegs+16@l(r3) + lis r3, 0xf000 + bl __OSMaskInterrupts +@1 + li r3, 1 + lwz r0, 0xc(r1) + addi r1, r1, 8 + mtlr r0 + blr +} +#pragma pop +/* clang-format on */ +#endif + +u32 OSGetPhysicalMemSize() { return *(u32*)(OSPhysicalToCached(0x0028)); } + +u32 OSGetConsoleSimulatedMemSize() { return *(u32*)(OSPhysicalToCached(0x00F0)); } + +static void MEMIntrruptHandler(__OSInterrupt interrupt, OSContext* context) { + u32 addr; + u32 cause; + + cause = __MEMRegs[0xf]; + addr = (((u32)__MEMRegs[0x12] & 0x3ff) << 16) | __MEMRegs[0x11]; + __MEMRegs[0x10] = 0; + + if (__OSErrorTable[OS_ERROR_PROTECTION]) { + __OSErrorTable[OS_ERROR_PROTECTION](OS_ERROR_PROTECTION, context, cause, addr); + return; + } + + __OSUnhandledException(OS_ERROR_PROTECTION, context, cause, addr); +} + +void OSProtectRange(u32 chan, void* addr, u32 nBytes, u32 control) { + BOOL enabled; + u32 start; + u32 end; + u16 reg; + if (4 <= chan) { + return; + } + + control &= OS_PROTECT_CONTROL_RDWR; + + end = (u32)addr + nBytes; + start = TRUNC(addr, 1u << 10); + end = ROUND(end, 1u << 10); + + DCFlushRange((void*)start, end - start); + + enabled = OSDisableInterrupts(); + + __OSMaskInterrupts(OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_0 + chan)); + + __MEMRegs[0 + 2 * chan] = (u16)(start >> 10); + __MEMRegs[1 + 2 * chan] = (u16)(end >> 10); + + reg = __MEMRegs[8]; + reg &= ~(OS_PROTECT_CONTROL_RDWR << 2 * chan); + reg |= control << 2 * chan; + __MEMRegs[8] = reg; + + if (control != OS_PROTECT_CONTROL_RDWR) { + __OSUnmaskInterrupts(OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_0 + chan)); + } + + OSRestoreInterrupts(enabled); +} + +asm void Config24MB() { + // clang-format off + nofralloc + + addi r7,r0,0 + + addis r4,r0,0x00000002@ha + addi r4,r4,0x00000002@l + addis r3,r0,0x800001ff@ha + addi r3,r3,0x800001ff@l + + addis r6,r0,0x01000002@ha + addi r6,r6,0x01000002@l + addis r5,r0,0x810000ff@ha + addi r5,r5,0x810000ff@l + + isync + + mtspr dbat0u,r7 + mtspr dbat0l,r4 + mtspr dbat0u,r3 + isync + + mtspr ibat0u,r7 + mtspr ibat0l,r4 + mtspr ibat0u,r3 + isync + + mtspr dbat2u,r7 + mtspr dbat2l,r6 + mtspr dbat2u,r5 + isync + + mtspr ibat2u,r7 + mtspr ibat2l,r6 + mtspr ibat2u,r5 + isync + + mfmsr r3 + ori r3, r3, 0x30 + mtsrr1 r3 + + mflr r3 + mtsrr0 r3 + rfi + // clang-format on +} + +asm void Config48MB() { + // clang-format off + nofralloc + + addi r7,r0,0x0000 + + addis r4,r0,0x00000002@ha + addi r4,r4,0x00000002@l + addis r3,r0,0x800003ff@ha + addi r3,r3,0x800003ff@l + + addis r6,r0,0x02000002@ha + addi r6,r6,0x02000002@l + addis r5,r0,0x820001ff@ha + addi r5,r5,0x820001ff@l + + isync + + mtspr dbat0u,r7 + mtspr dbat0l,r4 + mtspr dbat0u,r3 + isync + + mtspr ibat0u,r7 + mtspr ibat0l,r4 + mtspr ibat0u,r3 + isync + + mtspr dbat2u,r7 + mtspr dbat2l,r6 + mtspr dbat2u,r5 + isync + + mtspr ibat2u,r7 + mtspr ibat2l,r6 + mtspr ibat2u,r5 + isync + + mfmsr r3 + ori r3, r3, 0x30 + mtsrr1 r3 + + mflr r3 + mtsrr0 r3 + rfi + // clang-format on +} + +asm void RealMode(register u32 addr) { + // clang-format off + nofralloc + clrlwi r3, r3, 2 + mtsrr0 r3 + mfmsr r3 + rlwinm r3, r3, 0, 28, 25 + mtsrr1 r3 + rfi + // clang-format on +} + +void __OSInitMemoryProtection() { + u32 padding[8]; + u32 simulatedSize; + BOOL enabled; + simulatedSize = OSGetConsoleSimulatedMemSize(); + enabled = OSDisableInterrupts(); + if (simulatedSize <= 0x1800000) { + RealMode((u32)&Config24MB); + } else if (simulatedSize <= 0x3000000) { + RealMode((u32)&Config48MB); + } + + __MEMRegs[16] = 0; + __MEMRegs[8] = 0xFF; + + __OSMaskInterrupts(OS_INTERRUPTMASK_MEM_0 | OS_INTERRUPTMASK_MEM_1 | OS_INTERRUPTMASK_MEM_2 | + OS_INTERRUPTMASK_MEM_3); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_0, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_1, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_2, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_3, MEMIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_MEM_ADDRESS, MEMIntrruptHandler); + OSRegisterResetFunction(&ResetFunctionInfo); + + if (OSGetConsoleSimulatedMemSize() < OSGetPhysicalMemSize() && + OSGetConsoleSimulatedMemSize() == 0x1800000) { + __MEMRegs[20] = 2; + } + + __OSUnmaskInterrupts(OS_INTERRUPTMASK_MEM_ADDRESS); + OSRestoreInterrupts(enabled); +}