diff --git a/docs/piracychecks.md b/docs/piracychecks.md index 1ed35eb42..78b655475 100644 --- a/docs/piracychecks.md +++ b/docs/piracychecks.md @@ -8,7 +8,7 @@ The decomp project wraps all decompiled piracy checks in `#if PIRACYCHECKS` stat ## List of Piracy Checks -### bootPhase1 +### boot **When Called:** On power-on before the legal screen appears. @@ -20,7 +20,7 @@ The decomp project wraps all decompiled piracy checks in `#if PIRACYCHECKS` stat **When Called:** On every frame. -**What It Checks:** Checksums `bootPhase1` to make sure it hasn't been modified. +**What It Checks:** Checksums `boot` to make sure it hasn't been modified. **Payload:** Writes 40 bytes of 0xff to 0x80095210. This appears to be related to sound effects but has no obvious effect. diff --git a/ld/libfiles.jpn-final.inc b/ld/libfiles.jpn-final.inc index 2a3b003fd..88d91f941 100644 --- a/ld/libfiles.jpn-final.inc +++ b/ld/libfiles.jpn-final.inc @@ -1,5 +1,5 @@ #define LIBFILES(section) \ - build/ROMID/lib/tlb.o (section); \ + build/ROMID/lib/vm.o (section); \ build/ROMID/lib/segments.o (section); \ build/ROMID/lib/boot.o (section); \ build/ROMID/lib/sched.o (section); \ @@ -26,7 +26,7 @@ build/ROMID/lib/ultra/io/conteeplongwrite.o (section); \ build/ROMID/lib/ultra/io/pfsresizefile.o (section); \ build/ROMID/lib/ultra/io/pfsinitpak.o (section); \ - build/ROMID/lib/vm.o (section); \ + build/ROMID/lib/vminit.o (section); \ build/ROMID/lib/rzip.o (section); \ build/ROMID/lib/audiomgr.o (section); \ build/ROMID/lib/audiodma.o (section); \ diff --git a/ld/libfiles.ntsc-beta.inc b/ld/libfiles.ntsc-beta.inc index a33cfbd31..5ff9d8ff0 100644 --- a/ld/libfiles.ntsc-beta.inc +++ b/ld/libfiles.ntsc-beta.inc @@ -1,5 +1,5 @@ #define LIBFILES(section) \ - build/ROMID/lib/tlb.o (section); \ + build/ROMID/lib/vm.o (section); \ build/ROMID/lib/segments.o (section); \ build/ROMID/lib/boot.o (section); \ build/ROMID/lib/sched.o (section); \ @@ -27,7 +27,7 @@ build/ROMID/lib/ultra/io/conteeplongwrite.o (section); \ build/ROMID/lib/ultra/io/pfsresizefile.o (section); \ build/ROMID/lib/ultra/io/pfsinitpak.o (section); \ - build/ROMID/lib/vm.o (section); \ + build/ROMID/lib/vminit.o (section); \ build/ROMID/lib/rzip.o (section); \ build/ROMID/lib/audiomgr.o (section); \ build/ROMID/lib/audiodma.o (section); \ diff --git a/ld/libfiles.ntsc-final.inc b/ld/libfiles.ntsc-final.inc index 0d14cee3a..82fbf5a2f 100644 --- a/ld/libfiles.ntsc-final.inc +++ b/ld/libfiles.ntsc-final.inc @@ -1,5 +1,5 @@ #define LIBFILES(section) \ - build/ROMID/lib/tlb.o (section); \ + build/ROMID/lib/vm.o (section); \ build/ROMID/lib/segments.o (section); \ build/ROMID/lib/boot.o (section); \ build/ROMID/lib/sched.o (section); \ @@ -26,7 +26,7 @@ build/ROMID/lib/ultra/io/conteeplongwrite.o (section); \ build/ROMID/lib/ultra/io/pfsresizefile.o (section); \ build/ROMID/lib/ultra/io/pfsinitpak.o (section); \ - build/ROMID/lib/vm.o (section); \ + build/ROMID/lib/vminit.o (section); \ build/ROMID/lib/rzip.o (section); \ build/ROMID/lib/audiomgr.o (section); \ build/ROMID/lib/audiodma.o (section); \ diff --git a/ld/libfiles.pal-beta.inc b/ld/libfiles.pal-beta.inc index 2a3b003fd..88d91f941 100644 --- a/ld/libfiles.pal-beta.inc +++ b/ld/libfiles.pal-beta.inc @@ -1,5 +1,5 @@ #define LIBFILES(section) \ - build/ROMID/lib/tlb.o (section); \ + build/ROMID/lib/vm.o (section); \ build/ROMID/lib/segments.o (section); \ build/ROMID/lib/boot.o (section); \ build/ROMID/lib/sched.o (section); \ @@ -26,7 +26,7 @@ build/ROMID/lib/ultra/io/conteeplongwrite.o (section); \ build/ROMID/lib/ultra/io/pfsresizefile.o (section); \ build/ROMID/lib/ultra/io/pfsinitpak.o (section); \ - build/ROMID/lib/vm.o (section); \ + build/ROMID/lib/vminit.o (section); \ build/ROMID/lib/rzip.o (section); \ build/ROMID/lib/audiomgr.o (section); \ build/ROMID/lib/audiodma.o (section); \ diff --git a/ld/libfiles.pal-final.inc b/ld/libfiles.pal-final.inc index 2a3b003fd..88d91f941 100644 --- a/ld/libfiles.pal-final.inc +++ b/ld/libfiles.pal-final.inc @@ -1,5 +1,5 @@ #define LIBFILES(section) \ - build/ROMID/lib/tlb.o (section); \ + build/ROMID/lib/vm.o (section); \ build/ROMID/lib/segments.o (section); \ build/ROMID/lib/boot.o (section); \ build/ROMID/lib/sched.o (section); \ @@ -26,7 +26,7 @@ build/ROMID/lib/ultra/io/conteeplongwrite.o (section); \ build/ROMID/lib/ultra/io/pfsresizefile.o (section); \ build/ROMID/lib/ultra/io/pfsinitpak.o (section); \ - build/ROMID/lib/vm.o (section); \ + build/ROMID/lib/vminit.o (section); \ build/ROMID/lib/rzip.o (section); \ build/ROMID/lib/audiomgr.o (section); \ build/ROMID/lib/audiodma.o (section); \ diff --git a/ld/pd.ld b/ld/pd.ld index 4d4a4fd14..a00183abf 100644 --- a/ld/pd.ld +++ b/ld/pd.ld @@ -145,11 +145,11 @@ SECTIONS END_SEG(preamble) /** - /* tlbInit()'s address is 0x70001050, but preamble calls it by 0x80001050 + /* vmBoot()'s address is 0x70001050, but preamble calls it by 0x80001050 * due to it not being TLB mapped yet. So we set up this variable to allow * this to happen. */ - tlbInitFromPreamble = tlbInit + 0x10000000; + vmBootFromPreamble = vmBoot + 0x10000000; /*************************************************************************** * lib diff --git a/src/include/bss.h b/src/include/bss.h index 7f81eb1f2..070fa6792 100644 --- a/src/include/bss.h +++ b/src/include/bss.h @@ -25,7 +25,7 @@ extern u32 g_VmNumPageMisses; extern u32 g_VmNumPageReplaces; extern u8 *g_VmMarker; extern u32 g_VmRamEnd; -extern u32 g_VmStateTableEnd; +extern u32 g_VmVirtualToPhysicalTableEnd; extern AMAudioMgr g_AudioManager; extern Mtx *var80092870; extern s32 g_SndMaxFxBusses; diff --git a/src/include/lib/boot.h b/src/include/lib/boot.h index 10d82748e..2c359a0fc 100644 --- a/src/include/lib/boot.h +++ b/src/include/lib/boot.h @@ -2,10 +2,10 @@ #define _IN_LIB_BOOT_H #include -void bootPhase1(void); +void boot(void); s32 bootGetMemSize(void); void *bootAllocateStack(s32 threadid, s32 size); -void bootPhase2(void *arg); +void bootCreateThreads(void *arg); void bootCheckStackOverflow(void); #endif diff --git a/src/include/lib/tlb.h b/src/include/lib/tlb.h index b4fc228f1..a0835a530 100644 --- a/src/include/lib/tlb.h +++ b/src/include/lib/tlb.h @@ -2,10 +2,10 @@ #define _IN_LIB_TLB_H #include -void tlbInit(void); -void tlb000010a4(void); -void tlb0000113c(void); -void tlbHandleMiss(void); -void tlbUnmapRange(u32 first, u32 last); +void vmBoot(void); +void vmInitVars(void); +void vmInitVacant(void); +void vmHandleMiss(void); +void vmUnmapRange(u32 first, u32 last); #endif diff --git a/src/include/lib/vm.h b/src/include/lib/vm.h index 87fa050fb..5baffc527 100644 --- a/src/include/lib/vm.h +++ b/src/include/lib/vm.h @@ -1,11 +1,29 @@ #ifndef _IN_LIB_VM_H #define _IN_LIB_VM_H + +#ifdef _LANGUAGE_C #include #include "data.h" #include "types.h" extern u8 g_VmShowStats; -u32 vmInit(void); +void vmInit(void); +#endif + +#if VERSION >= VERSION_NTSC_1_0 +#define VM_NUM_SLOTS 268 +#else +#define VM_NUM_SLOTS 266 +#endif + +#define VM_PAGE_SIZE_SHIFT 12 +#define VM_PAGE_SIZE (1 << VM_PAGE_SIZE_SHIFT) + +#define VM_BIGGEST_ZIP 0x1c80 + +#define VM_VACANTBITS_LEN ((VM_NUM_SLOTS + 7) / 8) + +#define VM_VIRTUAL_ADDR 0x7f000000 #endif diff --git a/src/lib/boot.c b/src/lib/boot.c index 8f8ef6a9d..a1b83259f 100644 --- a/src/lib/boot.c +++ b/src/lib/boot.c @@ -72,7 +72,7 @@ u32 __osSetFpcCsr(u32 arg0); * in RAM thanks to this but need to be relocated, and .data and lib need to be * unzipped too. */ -void bootPhase1(void) +void boot(void) { s32 datacomplen; s32 inflatelen; @@ -135,7 +135,7 @@ void bootPhase1(void) } #endif - tlbUnmapRange(1, NTLBENTRIES); + vmUnmapRange(1, NTLBENTRIES); // Clear the stack allocation pointers for (i = 0; i < ARRAYCOUNT(g_StackLeftAddrs); i++) { @@ -168,7 +168,7 @@ void bootPhase1(void) #endif // Create and start the main thread - osCreateThread(&g_MainThread, THREAD_MAIN, bootPhase2, NULL, bootAllocateStack(THREAD_MAIN, STACKSIZE_MAIN), THREADPRI_MAIN); + osCreateThread(&g_MainThread, THREAD_MAIN, bootCreateThreads, NULL, bootAllocateStack(THREAD_MAIN, STACKSIZE_MAIN), THREADPRI_MAIN); osStartThread(&g_MainThread); } @@ -266,7 +266,7 @@ void bootCreateSchedThread(void) g_SchedCmdQ = osScGetCmdQ(&g_Sched); } -void bootPhase2(void *arg) +void bootCreateThreads(void *arg) { bootCreateIdleThread(); videbugCreate(); diff --git a/src/lib/crash.c b/src/lib/crash.c index 73cdcb838..b64b7da40 100644 --- a/src/lib/crash.c +++ b/src/lib/crash.c @@ -355,7 +355,7 @@ u32 crashGetParentStackFrame(u32 *origptr, u32 *minaddr, u32 origsp, u32 *regs) bool crashIsReturnAddress(u32 *instruction) { if (((uintptr_t)instruction % 4) == 0 - && (uintptr_t)instruction >= (uintptr_t)tlbInit + && (uintptr_t)instruction >= (uintptr_t)vmBoot && (uintptr_t)instruction <= (uintptr_t)&_libSegmentEnd) { // This condition can never pass because 9 is masked out if ((instruction[-2] & 0xfc00003c) == 9) { diff --git a/src/lib/main.c b/src/lib/main.c index 2907df57d..f00bf5e48 100644 --- a/src/lib/main.c +++ b/src/lib/main.c @@ -412,9 +412,9 @@ void mainInit(void) addr -= STACKSIZE_AUDIO; addr -= 8; // markers for stack overflow detection addr -= g_VmNumPages * 8; // vm state table - addr -= 268 * 4096; // vm loaded pages buffer + addr -= VM_NUM_SLOTS * VM_PAGE_SIZE; // vm loaded pages buffer addr -= addr % 0x2000; // align down to a multiple of 0x2000 - addr -= 0x1c80; // buffer for single biggest game zip + addr -= VM_BIGGEST_ZIP; // buffer for single biggest game zip } else { addr = K0BASE + 8 * 1024 * 1024; } @@ -557,9 +557,9 @@ void mainInit(void) addr -= STACKSIZE_SCHED; addr -= STACKSIZE_AUDIO; addr -= g_VmNumPages * 8; // vm state table - addr -= 266 * 4096; // vm loaded pages buffer + addr -= VM_NUM_SLOTS * VM_PAGE_SIZE; // vm loaded pages buffer addr -= addr % 0x2000; // align down to a multiple of 0x2000 - addr -= 0x1c80; // buffer for single biggest game zip + addr -= VM_BIGGEST_ZIP; // buffer for single biggest game zip } else { addr = K0BASE + 8 * 1024 * 1024; } diff --git a/src/lib/sched.c b/src/lib/sched.c index a0eec9f42..8ae080c83 100644 --- a/src/lib/sched.c +++ b/src/lib/sched.c @@ -402,7 +402,7 @@ void __scHandleTasks(OSSched *sc) { u32 checksum = 0; s32 *end = (s32 *)&bootAllocateStack; - s32 *ptr = (s32 *)&bootPhase1; + s32 *ptr = (s32 *)&boot; s32 i; while (ptr < end) { diff --git a/src/lib/tlb.s b/src/lib/tlb.s deleted file mode 100644 index cecf89fd6..000000000 --- a/src/lib/tlb.s +++ /dev/null @@ -1,527 +0,0 @@ -#include "os_tlb.h" -#include "asm_helper.h" -#include "macros.inc" -#include "versions.h" -.set noat -.set noreorder - -.bss -.balign 4 - -glabel var8008ae20 -.space 4 - -glabel g_VmStateTable -.space 4 - -glabel g_VmInitialised -.space 4 - -glabel g_VmZipBuffer -.space 4 - -glabel g_VmZipTable -.space 8 - -glabel var8008ae38 -.space 0x1000 - -glabel var8008be38 -.space 0x1400 - -glabel var8008d238 -.space 0x20 - -glabel var8008d258 -.space 4 - -glabel var8008d25c -.space 4 - -glabel var8008d260 -.space 4 - -glabel var8008d264 -.space 4 - -glabel var8008d268 -.space 4 - -.text - -/** - * Sets up TLB index 0 (0x70000000), then calls bootPhase1. - */ -glabel tlbInit - li $t0, OS_PM_4M - mtc0 $t0, C0_PAGEMASK - lui $t0, 0x7000 - mtc0 $t0, C0_ENTRYHI - li $t0, 0x1f - mtc0 $t0, C0_ENTRYLO0 - lui $t0, 0x1 - ori $t0, $t0, 0x1f - mtc0 $t0, C0_ENTRYLO1 - li $t0, 0 - mtc0 $t0, C0_INX - nop - tlbwi - nop - nop - nop - lui $t0, %hi(bootPhase1) - addiu $t0, $t0, %lo(bootPhase1) - jr $t0 - nop - -glabel tlb000010a4 - addiu $sp, $sp, -8 - sw $ra, 0x0($sp) - mtc0 $zero, C0_CONTEXT - li $t0, 0x2 - mtc0 $t0, C0_WIRED - li $t1, 0x1ff - lui $at, %hi(var8008d264+0x2) - sh $t1, %lo(var8008d264+0x2)($at) -#if VERSION >= VERSION_NTSC_1_0 - li $a0, 268 -#else - li $a0, 266 -#endif - lui $at, %hi(g_VmInitialised+0x2) - sh $a0, %lo(g_VmInitialised+0x2)($at) - lui $at, %hi(var8008d258+0x2) - sh $a0, %lo(var8008d258+0x2)($at) - sll $a0, $a0, 0xc - lui $v0, %hi(var8008ae20) - lw $v0, %lo(var8008ae20)($v0) - lui $t1, %hi(_gameSegmentEnd) - addiu $t1, $t1, %lo(_gameSegmentEnd) - lui $t2, %hi(_gameSegmentStart) - addiu $t2, $t2, %lo(_gameSegmentStart) - subu $t1, $t1, $t2 - lui $t0, 0xfff - ori $t0, $t0, 0xffff - and $v0, $v0, $t0 - lui $at, %hi(var8008d268) - sw $v0, %lo(var8008d268)($at) - lui $v0, %hi(var8008d238) - addiu $v0, $v0, %lo(var8008d238) - li $a0, 0x21 - lui $at, %hi(var8008d25c) - sw $v0, %lo(var8008d25c)($at) - addu $v1, $v0, $a0 - lui $at, %hi(var8008d260) - sw $v1, %lo(var8008d260)($at) - lw $ra, 0x0($sp) - addiu $sp, $sp, 0x8 - jr $ra - nop - -glabel tlb0000113c - li $t0, 0xff - lui $v0, %hi(var8008d25c) - lw $v0, %lo(var8008d25c)($v0) - lui $v1, %hi(var8008d260) - lw $v1, %lo(var8008d260)($v1) -.L00001150: - sb $t0, 0x0($v0) - bne $v0, $v1, .L00001150 - addiu $v0, $v0, 1 -#if VERSION >= VERSION_NTSC_1_0 - li $a0, 4 -#else - li $a0, 2 -#endif - beqz $a0, .L00001178 - addiu $a0, $a0, -1 - li $t0, 2 - sllv $t0, $t0, $a0 - addiu $t0, $t0, -1 - sb $t0, 0x0($v1) -.L00001178: - jr $ra - nop - -glabel tlbHandleMiss - mfc0 $t0, C0_CONTEXT - sll $s5, $t0, 0x9 - lui $t1, 0x7f00 - sub $t0, $s5, $t1 - srl $t0, $t0, 0xc - sll $t0, $t0, 0x3 - lui $t1, %hi(g_VmStateTable) - lw $t1, %lo(g_VmStateTable)($t1) - addu $s0, $t0, $t1 - lui $s8, 0x7f00 - slt $at, $s5, $s8 - bnez $at, .L0000162c - nop - lui $t1, %hi(g_VmRamEnd) - lw $t1, %lo(g_VmRamEnd)($t1) - slt $at, $s5, $t1 - beqz $at, .L0000162c - nop -#if VERSION < VERSION_NTSC_1_0 - lui $t2, %hi(g_VmNumTlbMisses) - addiu $t2, $t2, %lo(g_VmNumTlbMisses) - lw $t6, 0($t2) - addiu $t6, $t6, 1 - sw $t6, 0($t2) -#endif - mfc0 $t9, C0_BADVADDR - srl $t9, $t9, 0xc - andi $t9, $t9, 0x1 - beqzl $t9, .L000011e0 - lw $s1, 0x0($s0) - lw $s1, 0x8($s0) -.L000011e0: - bnezl $s1, .L000014c4 - li $t5, 0x1 - li $t5, 0x0 - lui $t1, %hi(var8008d25c) - lw $t1, %lo(var8008d25c)($t1) - lui $t2, %hi(var8008d260) - lw $t2, %lo(var8008d260)($t2) -.L000011fc: - lbu $t0, 0x0($t1) - beqz $t0, .L0000122c - nop - li $t6, 0x0 - li $t7, 0x1 -.L00001210: - and $t8, $t0, $t7 - bnez $t8, .L0000123c - nop - addiu $t6, $t6, 0x1 - li $at, 0x8 - bne $t6, $at, .L00001210 - sll $t7, $t7, 0x1 -.L0000122c: - bne $t1, $t2, .L000011fc - addiu $t1, $t1, 0x1 - j .L00001570 - nop -.L0000123c: - xor $t0, $t0, $t7 - sb $t0, 0x0($t1) - lui $t2, %hi(var8008d25c) - lw $t2, %lo(var8008d25c)($t2) - lui $s1, %hi(var8008d268) - lw $s1, %lo(var8008d268)($s1) - subu $t1, $t1, $t2 - sll $t1, $t1, 0x3 - addu $t0, $t6, $t1 - sll $t0, $t0, 0xc - addu $s1, $s1, $t0 -.L00001268: -#if VERSION < VERSION_NTSC_1_0 - lui $t2, %hi(g_VmNumPageMisses) - addiu $t2, $t2, %lo(g_VmNumPageMisses) - lw $t0, 0($t2) - addiu $t0, $t0, 1 - sw $t0, 0($t2) -#endif - mfc0 $t2, C0_BADVADDR - lui $t0, 0xff - ori $t0, $t0, 0xf000 - and $t2, $t2, $t0 - srl $t2, $t2, 0xa - lui $t0, %hi(g_VmZipTable) - lw $t0, %lo(g_VmZipTable)($t0) - addu $t0, $t0, $t2 - lw $t2, 0x0($t0) - lw $t0, 0x4($t0) - subu $t0, $t0, $t2 - li $t1, -16 - addiu $t0, $t0, 0xf - and $t6, $t0, $t1 - lui $t0, 0xa460 - ori $t0, $t0, 0x10 -.L000012a8: - lw $t1, 0x0($t0) - andi $t1, $t1, 0x3 - bnez $t1, .L000012a8 - nop - lui $s6, 0xa430 - lw $s6, 0x8($s6) - andi $s6, $s6, 0x10 - lui $t0, 0xa460 - lui $t1, %hi(g_VmZipBuffer) - lw $t1, %lo(g_VmZipBuffer)($t1) - lui $t7, 0xfff - ori $t7, $t7, 0xffff - and $t1, $t1, $t7 - sw $t1, 0x0($t0) - lui $t0, 0xa460 - ori $t0, $t0, 0x4 - lui $t1, 0x8000 - lw $t1, 0x308($t1) - or $t1, $t1, $t2 - lui $t2, 0x1fff - ori $t2, $t2, 0xffff - and $t1, $t1, $t2 - sw $t1, 0x0($t0) - lui $t0, 0xa460 - ori $t0, $t0, 0xc - addiu $t6, $t6, -1 - sw $t6, 0x0($t0) - beqzl $t9, .L00001324 - nop - beqzl $zero, .L00001328 - sw $s1, 0x8($s0) -.L00001324: - sw $s1, 0x0($s0) -.L00001328: - lui $t0, 0xa460 - ori $t0, $t0, 0x10 -.L00001330: - lw $t1, 0x0($t0) - andi $t1, $t1, 0x3 - bnez $t1, .L00001330 - nop - lui $t0, %hi(g_VmZipBuffer) - lw $t0, %lo(g_VmZipBuffer)($t0) - addiu $t1, $t0, 0x1000 -.L0000134c: - cache 0x15, 0x0($t0) - sltu $at, $t0, $t1 - bnez $at, .L0000134c - addiu $t0, $t0, 16 - bnez $s6, .L00001370 - nop - li $t0, 0x2 - lui $at, 0xa460 - sw $t0, 0x10($at) -.L00001370: - lui $a0, %hi(var8008ae38) - addiu $a0, $a0, %lo(var8008ae38) - addiu $a0, $a0, 0xff8 - sw $sp, 0x0($a0) - addiu $sp, $a0, 0x0 - lui $a0, %hi(g_VmZipBuffer) - lw $a0, %lo(g_VmZipBuffer)($a0) - addiu $a0, $a0, 0x2 - lui $t0, 0x8000 - or $a1, $s1, $t0 - lui $a2, %hi(var8008be38) - addiu $a2, $a2, %lo(var8008be38) - addiu $sp, $sp, -128 - sw $ra, 0x0($sp) - sw $at, 0x4($sp) - sw $v0, 0x8($sp) - sw $v1, 0xc($sp) - sw $a0, 0x10($sp) - sw $a1, 0x14($sp) - sw $a2, 0x18($sp) - sw $a3, 0x1c($sp) - sw $t0, 0x20($sp) - sw $t1, 0x24($sp) - sw $t2, 0x28($sp) - sw $t3, 0x2c($sp) - sw $t4, 0x30($sp) - sw $t5, 0x34($sp) - sw $t6, 0x38($sp) - sw $t7, 0x3c($sp) - sw $s0, 0x40($sp) - sw $s1, 0x44($sp) - sw $s2, 0x48($sp) - sw $s3, 0x4c($sp) - sw $s4, 0x50($sp) - sw $s5, 0x54($sp) - sw $s6, 0x58($sp) - sw $s7, 0x5c($sp) - sw $t8, 0x60($sp) - sw $t9, 0x64($sp) - sw $gp, 0x70($sp) - sw $sp, 0x74($sp) - sw $s8, 0x78($sp) - jal rzipInflate - nop - lw $ra, 0x0($sp) - lw $at, 0x4($sp) - lw $v0, 0x8($sp) - lw $v1, 0xc($sp) - lw $a0, 0x10($sp) - lw $a1, 0x14($sp) - lw $a2, 0x18($sp) - lw $a3, 0x1c($sp) - lw $t0, 0x20($sp) - lw $t1, 0x24($sp) - lw $t2, 0x28($sp) - lw $t3, 0x2c($sp) - lw $t4, 0x30($sp) - lw $t5, 0x34($sp) - lw $t6, 0x38($sp) - lw $t7, 0x3c($sp) - lw $s0, 0x40($sp) - lw $s1, 0x44($sp) - lw $s2, 0x48($sp) - lw $s3, 0x4c($sp) - lw $s4, 0x50($sp) - lw $s5, 0x54($sp) - lw $s6, 0x58($sp) - lw $s7, 0x5c($sp) - lw $t8, 0x60($sp) - lw $t9, 0x64($sp) - lw $gp, 0x70($sp) - lw $sp, 0x74($sp) - lw $s8, 0x78($sp) - addiu $sp, $sp, 0x80 - lui $a0, %hi(var8008ae38) - addiu $a0, $a0, %lo(var8008ae38) - addiu $a0, $a0, 4088 - lw $sp, 0x0($a0) - lui $t0, 0x8000 - or $t0, $s1, $t0 - addiu $t1, $t0, 0xff0 -.L000014b4: - cache 0x19, 0x0($t0) - sltu $at, $t0, $t1 - bnez $at, .L000014b4 - addiu $t0, $t0, 0x10 -.L000014c4: - li $t0, OS_PM_4K - mtc0 $t0, C0_PAGEMASK - mtc0 $s5, C0_ENTRYHI - nop - nop - nop - tlbp - nop - nop - mfc0 $t1, C0_INX - mtc0 $t0, C0_PAGEMASK - mtc0 $s5, C0_ENTRYHI - lw $t0, 0x0($s0) - srl $t0, $t0, 0xc - sll $t0, $t0, 0x6 - bnezl $t0, .L00001508 - ori $t0, $t0, 0x1e -.L00001508: - mtc0 $t0, C0_ENTRYLO0 - lw $t0, 0x8($s0) - srl $t0, $t0, 0xc - sll $t0, $t0, 0x6 - bnezl $t0, .L00001520 - ori $t0, $t0, 0x1e -.L00001520: - mtc0 $t0, C0_ENTRYLO1 - bltzl $t1, .L00001534 - nop - b .L00001538 - tlbwi -.L00001534: - tlbwr -.L00001538: - bnez $t5, .L00001568 - nop - move $t0, $s5 - bnezl $t9, .L0000154c - addiu $t0, $t0, 0x1000 -.L0000154c: - addiu $t1, $t0, 0xfe0 - andi $t2, $t0, 0x1f - subu $t0, $t0, $t2 -.L00001558: - cache 0x10, 0x0($t0) - sltu $at, $t0, $t1 - bnez $at, .L00001558 - addiu $t0, $t0, 0x20 -.L00001568: - jr $ra - nop -.L00001570: -#if VERSION < VERSION_NTSC_1_0 - lui $t0, %hi(g_VmNumPageReplaces) - addiu $t0, $t0, %lo(g_VmNumPageReplaces) - lw $t1, 0($t0) - addiu $t1, $t1, 1 - sw $t1, 0($t0) -#endif -.L00001570_2: - lui $s4, %hi(g_VmStateTable) - lw $s4, %lo(g_VmStateTable)($s4) - lui $gp, %hi(g_VmStateTableEnd) - lw $gp, %lo(g_VmStateTableEnd)($gp) - mfc0 $t0, C0_COUNT - lui $t1, %hi(var8008d264+0x2) - lhu $t1, %lo(var8008d264+0x2)($t1) - lui $t2, %hi(g_VmNumPages) - lw $t2, %lo(g_VmNumPages)($t2) - and $t0, $t0, $t1 - slt $at, $t0, $t2 - beqzl $at, .L000015a4 - subu $t0, $t0, $t2 -.L000015a4: - sll $t1, $t0, 0x3 - addu $t1, $t1, $s4 -.L000015ac: - lw $s1, 0x0($t1) - bnez $s1, .L000015cc - nop - addiu $t1, $t1, 8 - bne $t1, $gp, .L000015ac - nop - j .L000015ac - move $t1, $s4 -.L000015cc: - subu $t0, $t1, $s4 - srl $t0, $t0, 0x3 - sll $t0, $t0, 0xc - addu $t0, $t0, $s8 - li $t2, -4096 - and $t0, $t0, $t2 - mtc0 $t0, C0_ENTRYHI - li $t0, 0x0 - mtc0 $t0, C0_PAGEMASK - nop - nop - nop - tlbp - nop - nop - mfc0 $t2, C0_INX - mfc0 $t0, C0_ENTRYHI - bltz $t2, .L00001620 - nop - j .L00001570_2 - nop -.L00001620: - sw $zero, 0x0($t1) - j .L00001268 - nop -.L0000162c: - j handle_fault - nop - -glabel tlbUnmapRange - mfc0 $t0, C0_ENTRYHI - lui $t2, 0x8000 - mtc0 $t2, C0_ENTRYHI - mtc0 $zero, C0_ENTRYLO0 - mtc0 $zero, C0_ENTRYLO1 -.L00001648: - mtc0 $a1, C0_INX - nop - tlbwi - nop - nop - bne $a1, $a0, .L00001648 - addi $a1, $a1, -1 - mtc0 $t0, C0_ENTRYHI - jr $ra - nop - -#if VERSION < VERSION_NTSC_1_0 -glabel tlb000016acnb - lui $t0, 0x8000 - addiu $t1, $t0, 0x1ff0 -.L000016b4: - cache 0x1, 0x0($t0) - sltu $at, $t0, $t1 - bnez $at, .L000016b4 - addiu $t0, $t0, 0x10 - jr $ra - nop -#endif diff --git a/src/lib/ultra/os/exceptasm.s b/src/lib/ultra/os/exceptasm.s index c59d1250e..d13a215a6 100644 --- a/src/lib/ultra/os/exceptasm.s +++ b/src/lib/ultra/os/exceptasm.s @@ -436,7 +436,7 @@ glabel __osException and $s0, $s0, $at .handle_rmiss: - jal tlbHandleMiss + jal vmHandleMiss nop b .dispatch_thread nop diff --git a/src/lib/vm.s b/src/lib/vm.s new file mode 100644 index 000000000..41052c046 --- /dev/null +++ b/src/lib/vm.s @@ -0,0 +1,631 @@ +#include "os_tlb.h" +#include "asm_helper.h" +#include "macros.inc" +#include "versions.h" +#include "lib/vm.h" +.set noat +.set noreorder + +.bss +.balign 4 + +/** + * Quick figures (correct for ntsc-final): + * 443 pages + * Page size is 4096 (ie. 4KB each) + * Virtual range is 0x7f000000 to 0x7f1bb000 (0x7f000000 + 443 * 4096) + * + * There are 268 physical slots, meaning 268 pages can be loaded at a time. + * There are 30-ish entries in the TLB, so only 30-ish can be mapped at a time. + * Physical slots are in physical memory at 0x80220000 to 0x8032c000. + */ + +# Pointer to the physical slots where pages can be loaded (ie. 0x80220000). +# Size = 268 * 4096 +glabel g_VmPhysicalSlots +.space 4 + +# Pointer to the virtual-to-physical (V2P) table. +# Each entry is 8 bytes and there is one entry for each virtual page. +# The first word is the physical address where the page is loaded, or 0 if not loaded. +# The second word is unused. +# An example physical address is 0x00220000. +# Size = 443 * 8 +glabel g_VmVirtualToPhysicalTable +.space 4 + +# Set but never read +glabel g_VmInitialised +.space 1 +.align 1 + +# The number of pages that can be loaded at any one time (268). +# Written but never read. +glabel g_VmNumSlots +.space 2 + +# Pointer to a buffer that's big enough to hold the biggest zip file. +glabel g_VmZipBuffer +.space 4 + +# Pointer to an array of ROM offsets where each zip can be found. +# Size = 443 * sizeof(void *) +glabel g_VmZipTable +.space 4 + +# Temporary stack space. Used when unzipping a page. +.align 3 +glabel g_VmTempStack +.space 0x1000 + +# A scratch area that can be used by rzipInflate. +glabel g_VmScratch +.space 0x1400 + +# Array where each bit represents a physical slot (268 bits). +# Bits are 1 if the slot is vacant. +glabel g_VmVacantBits +.space VM_VACANTBITS_LEN + +# The number of pages that can be loaded at any one time (268). +# Written but never read. +# Duplicate of g_VmNumSlots. +glabel g_VmNumSlots2 +.space 2 + +# Pointer to the first byte in the g_VmVacantBits array. Never changed once set. +glabel g_VmVacantFirstByte +.space 4 + +# Pointer to the last byte in the g_VmVacantBits array. Never changed once set. +glabel g_VmVacantLastByte +.space 4 + +# Unused. +glabel var8008d264 +.space 2 + +# Masked with C0_COUNT to choose which page to replace. +# Initialised with the value 0x1ff then never changed. +glabel g_VmEvictMask +.space 2 + +# The physical address of the slots (0x00220000). +glabel g_VmSlotsPhysicalAddr +.space 4 + +.text + +/** + * Sets up TLB index 0 (0x70000000), then calls boot. + */ +glabel vmBoot + li $t0, OS_PM_4M + mtc0 $t0, C0_PAGEMASK + li $t0, 0x70000000 + mtc0 $t0, C0_ENTRYHI + li $t0, 0x1f + mtc0 $t0, C0_ENTRYLO0 + li $t0, 0x1001f + mtc0 $t0, C0_ENTRYLO1 + li $t0, 0 + mtc0 $t0, C0_INX + nop + tlbwi + nop + nop + nop + la $t0, boot + jr $t0 + nop + +glabel vmInitVars + addiu $sp, $sp, -8 + sw $ra, 0x0($sp) + + mtc0 $zero, C0_CONTEXT + + li $t0, 2 + mtc0 $t0, C0_WIRED + + li $t1, 0x1ff + lui $at, %hi(g_VmEvictMask) + sh $t1, %lo(g_VmEvictMask)($at) + + li $a0, VM_NUM_SLOTS + lui $at, %hi(g_VmNumSlots) + sh $a0, %lo(g_VmNumSlots)($at) + + lui $at, %hi(g_VmNumSlots2) + sh $a0, %lo(g_VmNumSlots2)($at) + + sll $a0, $a0, VM_PAGE_SIZE_SHIFT + + lw $v0, g_VmPhysicalSlots + la $t1, _gameSegmentEnd # unused + la $t2, _gameSegmentStart # unused + subu $t1, $t1, $t2 # unused + li $t0, 0x0fffffff + and $v0, $v0, $t0 + lui $at, %hi(g_VmSlotsPhysicalAddr) + sw $v0, %lo(g_VmSlotsPhysicalAddr)($at) + + la $v0, g_VmVacantBits + li $a0, VM_VACANTBITS_LEN - 1 + lui $at, %hi(g_VmVacantFirstByte) + sw $v0, %lo(g_VmVacantFirstByte)($at) + + addu $v1, $v0, $a0 + lui $at, %hi(g_VmVacantLastByte) + sw $v1, %lo(g_VmVacantLastByte)($at) + + lw $ra, 0x0($sp) + addiu $sp, $sp, 8 + jr $ra + nop + +glabel vmInitVacant + # Fill array with 0xff (ie. all vacant) + li $t0, 0xff + lw $v0, g_VmVacantFirstByte + lw $v1, g_VmVacantLastByte +.fill_loop: + sb $t0, 0x0($v0) + bne $v0, $v1, .fill_loop + addiu $v0, $v0, 1 + + # Set the last byte with a partial bitmask based on the number of page slots + li $a0, VM_NUM_SLOTS % 8 + beqz $a0, .after_remainder + addiu $a0, $a0, -1 + li $t0, 2 + sllv $t0, $t0, $a0 + addiu $t0, $t0, -1 + sb $t0, 0x0($v1) +.after_remainder: + jr $ra + nop + +/** + * vmHandleMiss is called from the exception handler when a request is made to + * access a virtual memory address that isn't currently mapped in the TLB. + * vmHandleMiss must load the page from ROM if not already loaded, then map it + * in the TLB. + * + * In NTSC Final, there are 443 virtual pages, 268 slots where these can be loaded, + * and 30 of these can be mapped in the TLB at the same time. + */ +glabel vmHandleMiss + # C0_CONTEXT must be the 512-byte chunk index that was requested? + # Convert it to a virtual address + mfc0 $t0, C0_CONTEXT + sll $s5, $t0, 9 + li $t1, VM_VIRTUAL_ADDR + sub $t0, $s5, $t1 + srl $t0, $t0, VM_PAGE_SIZE_SHIFT # t0 = virtual page index + + # Multiply t0 by 8 to get the V2P table offset + sll $t0, $t0, 3 + lw $t1, g_VmVirtualToPhysicalTable + addu $s0, $t0, $t1 # s0 = pointer to V2P entry + + # Check that the requested address is within the virtual range + li $s8, VM_VIRTUAL_ADDR + slt $at, $s5, $s8 + bnez $at, .out_of_range + nop + lw $t1, g_VmRamEnd + slt $at, $s5, $t1 + beqz $at, .out_of_range + nop + +#if VERSION < VERSION_NTSC_1_0 + # Increment g_VmNumTlbMisses + la $t2, g_VmNumTlbMisses + lw $t6, 0($t2) + addiu $t6, $t6, 1 + sw $t6, 0($t2) +#endif + + # If the page index is even then read the current slot's unk00. + # If the page index is odd then read from the next slot's unk00. + mfc0 $t9, C0_BADVADDR + srl $t9, $t9, VM_PAGE_SIZE_SHIFT + andi $t9, $t9, 1 + beqzl $t9, .after_odd_even_check1 + lw $s1, 0x0($s0) + lw $s1, 0x8($s0) +.after_odd_even_check1: + bnezl $s1, .map_tlb # Page is already loaded, so just map it + li $t5, 1 + li $t5, 0 + lw $t1, g_VmVacantFirstByte + lw $t2, g_VmVacantLastByte + + # Find any bit that is set in the byte array +.find_byte_loop: + lbu $t0, 0x0($t1) + beqz $t0, .after_bit_loop + nop + li $t6, 0 + li $t7, 1 +.find_bit_loop: + and $t8, $t0, $t7 + bnez $t8, .use_empty_slot + nop + addiu $t6, $t6, 1 + li $at, 8 + bne $t6, $at, .find_bit_loop + sll $t7, $t7, 1 +.after_bit_loop: + bne $t1, $t2, .find_byte_loop + addiu $t1, $t1, 1 + + # All slots are allocated + j .choose_page_to_replace + nop + +.use_empty_slot: + # t0 is the available byte's value + # t1 is a pointer to the available byte + # t6 is the bit index (0-7) of the available bit + # t7 is the bit power (1, 2, 4.. 128) of the available bit + xor $t0, $t0, $t7 + sb $t0, 0x0($t1) + lw $t2, g_VmVacantFirstByte + lw $s1, g_VmSlotsPhysicalAddr + subu $t1, $t1, $t2 # t1 = byte index + sll $t1, $t1, 3 # t1 now a V2P table byte offset + addu $t0, $t6, $t1 # t0 = offset to V2P table entry + sll $t0, $t0, VM_PAGE_SIZE_SHIFT # t0 now the virtual page index of the empty slot + addu $s1, $s1, $t0 + +.load_page: +#if VERSION < VERSION_NTSC_1_0 + # Increment g_VmNumPageMisses + la $t2, g_VmNumPageMisses + lw $t0, 0($t2) + addiu $t0, $t0, 1 + sw $t0, 0($t2) +#endif + + # Calculate the offset of the entry in the zip table. + # The zip table is an array of ROM offsets where each zip can be found. + mfc0 $t2, C0_BADVADDR + li $t0, 0x01000000 - VM_PAGE_SIZE + and $t2, $t2, $t0 + srl $t2, $t2, 10 + lw $t0, g_VmZipTable + addu $t0, $t0, $t2 + + lw $t2, 0x0($t0) # t2 = zip ROM start address + lw $t0, 0x4($t0) # t0 = zip ROM end address + subu $t0, $t0, $t2 # t0 = zip length (compressed) + + # Align the zip length to 0x10 + li $t1, 0xfffffff0 + addiu $t0, $t0, 15 + and $t6, $t0, $t1 + + # Wait for the PI to be available + li $t0, PHYS_TO_K1(PI_STATUS_REG) +.wait_for_pi_ready_loop: + lw $t1, 0x0($t0) + andi $t1, $t1, PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY + bnez $t1, .wait_for_pi_ready_loop + nop + + # Check if the PI has a pending interrupt - this will be used after the DMA + lw $s6, PHYS_TO_K1(MI_INTR_REG) + andi $s6, $s6, MI_INTR_PI + + # Set PI_DRAM_ADDR_REG to g_VmZipBuffer (where the zip will be loaded to) + li $t0, PHYS_TO_K1(PI_DRAM_ADDR_REG) + lw $t1, g_VmZipBuffer + li $t7, 0x0fffffff + and $t1, $t1, $t7 + sw $t1, 0x0($t0) + + # Set PI_CART_ADDR_REG to the ROM address of the zip + li $t0, PHYS_TO_K1(PI_CART_ADDR_REG) + lw $t1, osRomBase + or $t1, $t1, $t2 + li $t2, 0x1fffffff + and $t1, $t1, $t2 + sw $t1, 0x0($t0) + + # Set PI_WR_LEN_REG to the aligned size of the zip + li $t0, PHYS_TO_K1(PI_WR_LEN_REG) + addiu $t6, $t6, -1 + sw $t6, 0x0($t0) + + beqzl $t9, .after_odd_even_check2 + nop + beqzl $zero, .pointless_branch + sw $s1, 0x8($s0) +.after_odd_even_check2: + sw $s1, 0x0($s0) + +.pointless_branch: + li $t0, PHYS_TO_K1(PI_STATUS_REG) +.wait_for_pi_dma_completed_loop: + lw $t1, 0x0($t0) + andi $t1, $t1, PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY + bnez $t1, .wait_for_pi_dma_completed_loop + nop + + # Invalidate cache in the zip buffer area + lw $t0, g_VmZipBuffer + addiu $t1, $t0, VM_PAGE_SIZE +.invalidate_dcache_loop: + cache 0x15, 0x0($t0) + sltu $at, $t0, $t1 + bnez $at, .invalidate_dcache_loop + addiu $t0, $t0, 16 + + # If the PI didn't previously have a pending interrupt, + # make sure the above work hasn't triggered one + bnez $s6, .after_clear_pi_interrupt + nop + li $t0, PI_CLR_INTR + lui $at, %hi(PHYS_TO_K1(PI_STATUS_REG)) + sw $t0, %lo(PHYS_TO_K1(PI_STATUS_REG))($at) + +.after_clear_pi_interrupt: + # Set stack pointer to g_VmTempStack + la $a0, g_VmTempStack + addiu $a0, $a0, 0xff8 + sw $sp, 0x0($a0) + addiu $sp, $a0, 0 + + # Prepare arguments for rzipInflate + lw $a0, g_VmZipBuffer + addiu $a0, $a0, 2 # Move past the 2-byte checksum + li $t0, K0BASE + or $a1, $s1, $t0 + la $a2, g_VmScratch + + # Save registers to the stack + addiu $sp, $sp, -0x80 + sw $ra, 0x0($sp) + sw $at, 0x4($sp) + sw $v0, 0x8($sp) + sw $v1, 0xc($sp) + sw $a0, 0x10($sp) + sw $a1, 0x14($sp) + sw $a2, 0x18($sp) + sw $a3, 0x1c($sp) + sw $t0, 0x20($sp) + sw $t1, 0x24($sp) + sw $t2, 0x28($sp) + sw $t3, 0x2c($sp) + sw $t4, 0x30($sp) + sw $t5, 0x34($sp) + sw $t6, 0x38($sp) + sw $t7, 0x3c($sp) + sw $s0, 0x40($sp) + sw $s1, 0x44($sp) + sw $s2, 0x48($sp) + sw $s3, 0x4c($sp) + sw $s4, 0x50($sp) + sw $s5, 0x54($sp) + sw $s6, 0x58($sp) + sw $s7, 0x5c($sp) + sw $t8, 0x60($sp) + sw $t9, 0x64($sp) + sw $gp, 0x70($sp) + sw $sp, 0x74($sp) + sw $s8, 0x78($sp) + + # Unzip the zip + jal rzipInflate + nop + + # Reload registers from the stack + lw $ra, 0x0($sp) + lw $at, 0x4($sp) + lw $v0, 0x8($sp) + lw $v1, 0xc($sp) + lw $a0, 0x10($sp) + lw $a1, 0x14($sp) + lw $a2, 0x18($sp) + lw $a3, 0x1c($sp) + lw $t0, 0x20($sp) + lw $t1, 0x24($sp) + lw $t2, 0x28($sp) + lw $t3, 0x2c($sp) + lw $t4, 0x30($sp) + lw $t5, 0x34($sp) + lw $t6, 0x38($sp) + lw $t7, 0x3c($sp) + lw $s0, 0x40($sp) + lw $s1, 0x44($sp) + lw $s2, 0x48($sp) + lw $s3, 0x4c($sp) + lw $s4, 0x50($sp) + lw $s5, 0x54($sp) + lw $s6, 0x58($sp) + lw $s7, 0x5c($sp) + lw $t8, 0x60($sp) + lw $t9, 0x64($sp) + lw $gp, 0x70($sp) + lw $sp, 0x74($sp) + lw $s8, 0x78($sp) + addiu $sp, $sp, 0x80 + + # Restore the stack pointer + la $a0, g_VmTempStack + addiu $a0, $a0, 0xff8 + lw $sp, 0x0($a0) + + # Invalidate the cache + li $t0, K0BASE + or $t0, $s1, $t0 + addiu $t1, $t0, VM_PAGE_SIZE - 0x10 +.invalidate_dcache_loop2: + cache 0x19, 0x0($t0) + sltu $at, $t0, $t1 + bnez $at, .invalidate_dcache_loop2 + addiu $t0, $t0, 0x10 + +.map_tlb: + li $t0, OS_PM_4K + mtc0 $t0, C0_PAGEMASK + mtc0 $s5, C0_ENTRYHI + nop + nop + nop + tlbp + nop + nop + mfc0 $t1, C0_INX + mtc0 $t0, C0_PAGEMASK + mtc0 $s5, C0_ENTRYHI + lw $t0, 0x0($s0) + srl $t0, $t0, VM_PAGE_SIZE_SHIFT + sll $t0, $t0, 6 + bnezl $t0, .set_entrylo0 + ori $t0, $t0, 0x1e +.set_entrylo0: + mtc0 $t0, C0_ENTRYLO0 + lw $t0, 0x8($s0) + srl $t0, $t0, VM_PAGE_SIZE_SHIFT + sll $t0, $t0, 6 + bnezl $t0, .set_entrylo1 + ori $t0, $t0, 0x1e +.set_entrylo1: + mtc0 $t0, C0_ENTRYLO1 + bltzl $t1, .write_random_tlb_entry + nop + b .after_write_tlb + tlbwi # Replace TLB entry at index C0_INX +.write_random_tlb_entry: + tlbwr # Replace a random TLB entry +.after_write_tlb: + bnez $t5, .after_invalidate_cache + nop + move $t0, $s5 + bnezl $t9, .after_odd_even_check3 + addiu $t0, $t0, VM_PAGE_SIZE +.after_odd_even_check3: + addiu $t1, $t0, VM_PAGE_SIZE - 0x20 + andi $t2, $t0, 0x1f + subu $t0, $t0, $t2 +.invalidate_dcache_loop3: + cache 0x10, 0x0($t0) + sltu $at, $t0, $t1 + bnez $at, .invalidate_dcache_loop3 + addiu $t0, $t0, 0x20 + +.after_invalidate_cache: + jr $ra + nop + +.choose_page_to_replace: + # This part of the function chooses a loaded-but-unmapped slot to be replaced. + # The physical address of the page is stored to s1, then it jumps to load_page. +#if VERSION < VERSION_NTSC_1_0 + # Increment g_VmNumPageReplaces + la $t0, g_VmNumPageReplaces + lw $t1, 0($t0) + addiu $t1, $t1, 1 + sw $t1, 0($t0) +#endif + +.evict_loop: + # Choose a slot to evict. This is done by taking C0_COUNT & 0x1ff. + # If this is still bigger than the number of pages then the number of pages + # is subtracted from the value. + lw $s4, g_VmVirtualToPhysicalTable + lw $gp, g_VmVirtualToPhysicalTableEnd + mfc0 $t0, C0_COUNT + lhu $t1, g_VmEvictMask + lw $t2, g_VmNumPages + and $t0, $t0, $t1 + slt $at, $t0, $t2 + beqzl $at, .after_subtract + subu $t0, $t0, $t2 + +.after_subtract: + # Convert it to a V2P table offset + sll $t1, $t0, 3 + addu $t1, $t1, $s4 + + # Move forward through the table until a loaded slot is found. + # If the end is reached, wrap back to the start. +.slot_loop: + lw $s1, 0x0($t1) + bnez $s1, .check_tlb_entry + nop + addiu $t1, $t1, 8 + bne $t1, $gp, .slot_loop + nop + j .slot_loop + move $t1, $s4 + +.check_tlb_entry: + # Query the TLB to make sure this page isn't currently mapped. + # If it is then it must have been used recently, so find another page to replace. + subu $t0, $t1, $s4 # t0 is now an offset in the V2P table + srl $t0, $t0, 3 # t0 is now an index in the V2P table + sll $t0, $t0, VM_PAGE_SIZE_SHIFT # t0 is now the byte offset in the physical slots + addu $t0, $t0, $s8 # t0 += 0x7f000000 + li $t2, 0x100000000 - VM_PAGE_SIZE + and $t0, $t0, $t2 # t0 is now aligned to a page + mtc0 $t0, C0_ENTRYHI + li $t0, OS_PM_4K + mtc0 $t0, C0_PAGEMASK + nop + nop + nop + # tlbp sets C0_INX to to the index of the TLB entry which has the given ENTRYHI + tlbp + nop + nop + mfc0 $t2, C0_INX + mfc0 $t0, C0_ENTRYHI + bltz $t2, .not_mapped + nop + j .evict_loop + nop + +.not_mapped: + # The page is not mapped in the TLB, so it's okay to replace it. + sw $zero, 0x0($t1) + j .load_page + nop + +.out_of_range: + j handle_fault + nop + +glabel vmUnmapRange + mfc0 $t0, C0_ENTRYHI + li $t2, K0BASE + mtc0 $t2, C0_ENTRYHI + mtc0 $zero, C0_ENTRYLO0 + mtc0 $zero, C0_ENTRYLO1 +.unmap_loop: + mtc0 $a1, C0_INX + nop + tlbwi + nop + nop + bne $a1, $a0, .unmap_loop + addi $a1, $a1, -1 + mtc0 $t0, C0_ENTRYHI + jr $ra + nop + +#if VERSION < VERSION_NTSC_1_0 +glabel vmInvalidateFirst8Kb + li $t0, K0BASE + addiu $t1, $t0, 0x1ff0 +.invalidate_dcache_loop4: + cache 0x1, 0x0($t0) + sltu $at, $t0, $t1 + bnez $at, .invalidate_dcache_loop4 + addiu $t0, $t0, 0x10 + jr $ra + nop +#endif diff --git a/src/lib/vm.c b/src/lib/vminit.c similarity index 92% rename from src/lib/vm.c rename to src/lib/vminit.c index ab3056646..86269d6b0 100644 --- a/src/lib/vm.c +++ b/src/lib/vminit.c @@ -7,6 +7,7 @@ #include "lib/rzip.h" #include "lib/dma.h" #include "lib/lib_48150.h" +#include "lib/vm.h" #include "data.h" #include "types.h" @@ -74,7 +75,7 @@ u32 g_VmNumPageMisses; u32 g_VmNumPageReplaces; u8 *g_VmMarker; u32 g_VmRamEnd; -u32 g_VmStateTableEnd; +u32 g_VmVirtualToPhysicalTableEnd; #ifdef DEBUG u8 g_VmShowStats = false; @@ -98,20 +99,12 @@ extern u8 _gameSegmentStart; extern u8 _gameSegmentEnd; extern u8 _gamezipSegmentRomStart; -extern u32 var8008ae20; -extern u32 *g_VmStateTable; +extern u32 g_VmPhysicalSlots; +extern u32 *g_VmVirtualToPhysicalTable; extern u8 g_VmInitialised; extern u32 g_VmZipBuffer; extern u32 *g_VmZipTable; -#define PAGE_SIZE (1024 * 4) - -#if VERSION >= VERSION_NTSC_1_0 -#define MAX_LOADED_PAGES 268 -#else -#define MAX_LOADED_PAGES 266 -#endif - /** * Initialise the virtual memory. * @@ -152,7 +145,7 @@ extern u32 *g_VmZipTable; * Addresses: 0x??? 0x80220000 0x803f50b8 0x80400000 * Lengths: 0x6ec 0x1b99e0 0xaf48 0 * - * zip buffer: is sized as PAGE_SIZE * 2, which guarantees it's big enough to + * zip buffer: is sized as VM_PAGE_SIZE * 2, which guarantees it's big enough to * hold any zip. * zip table: is the ROM offset table where each zip can be found. * game seg: is where the entire game segment is unzipped to. @@ -214,14 +207,14 @@ void vmInit(void) { g_Is4Mb = true; - g_VmNumPages = (s32)((&_gameSegmentEnd - &_gameSegmentStart) + (PAGE_SIZE - 1)) / PAGE_SIZE; + g_VmNumPages = (s32)((&_gameSegmentEnd - &_gameSegmentStart) + (VM_PAGE_SIZE - 1)) / VM_PAGE_SIZE; - g_VmRamEnd = 0x7f000000 + PAGE_SIZE * g_VmNumPages; - g_VmStateTableEnd = STACK_START; + g_VmRamEnd = 0x7f000000 + VM_PAGE_SIZE * g_VmNumPages; + g_VmVirtualToPhysicalTableEnd = STACK_START; gameseg = (u8 *) (STACK_START - g_VmNumPages * 8); - g_VmStateTable = (u32 *) gameseg; + g_VmVirtualToPhysicalTable = (u32 *) gameseg; - numpages = (u32) (((uintptr_t) &_gameSegmentEnd - (uintptr_t) &_gameSegmentStart) + (PAGE_SIZE - 1)) / PAGE_SIZE; + numpages = (u32) (((uintptr_t) &_gameSegmentEnd - (uintptr_t) &_gameSegmentStart) + (VM_PAGE_SIZE - 1)) / VM_PAGE_SIZE; numentries = numpages + 1; g_VmZipTable = (u32 *) ((uintptr_t) ((u32 *) gameseg - (numentries + 4)) & ~0xf); @@ -249,27 +242,27 @@ void vmInit(void) s1 &= (u32) ~0xf; g_VmZipBuffer = (uintptr_t) g_VmZipTable - s1; g_VmZipBuffer &= ~0xf; - gameseg = (u8 *) (g_VmZipBuffer - MAX_LOADED_PAGES * PAGE_SIZE); + gameseg = (u8 *) (g_VmZipBuffer - VM_NUM_SLOTS * VM_PAGE_SIZE); gameseg -= (uintptr_t) gameseg & 0x1fff; - var8008ae20 = (uintptr_t) gameseg; + g_VmPhysicalSlots = (uintptr_t) gameseg; g_VmMarker = gameseg; - tlb000010a4(); + vmInitVars(); // Clear the state table - ptr = g_VmStateTable; + ptr = g_VmVirtualToPhysicalTable; statetablelen = (g_VmNumPages * 8) >> 2; for (s1 = 0; s1 < statetablelen; s1++) { ptr[s1] = 0; } - tlb0000113c(); + vmInitVacant(); } else { // Expansion pak is being used g_Is4Mb = numentries * false; - numpages = (u32)((&_gameSegmentEnd - &_gameSegmentStart) + (PAGE_SIZE - 1)) / PAGE_SIZE; + numpages = (u32)((&_gameSegmentEnd - &_gameSegmentStart) + (VM_PAGE_SIZE - 1)) / VM_PAGE_SIZE; s7 = (u8 *) STACK_START; #if VERSION >= VERSION_NTSC_1_0 @@ -302,7 +295,7 @@ void vmInit(void) // Load each zip from the ROM and inflate them to the game segment s2 = gameseg; - chunkbuffer = (u8 *) ((uintptr_t) romaddrs - PAGE_SIZE * 2); + chunkbuffer = (u8 *) ((uintptr_t) romaddrs - VM_PAGE_SIZE * 2); zip = chunkbuffer + 2; for (ITER = 0; ITER < numentries2 - 1;) { diff --git a/src/preamble/preamble.s b/src/preamble/preamble.s index 05bbe8487..d7d2f9404 100644 --- a/src/preamble/preamble.s +++ b/src/preamble/preamble.s @@ -1,3 +1,4 @@ +#include "asm_helper.h" #include "macros.inc" .set noat .set noreorder @@ -6,21 +7,22 @@ /** * This function is generated automatically by makerom. It clears the BSS - * segment, sets the stack pointer to 0x80000f10 and then calls boot. + * segment, sets the stack pointer to 0x80000f10 and then calls vmBoot. */ glabel preamble lui $t0, %hi(_bssSegmentStart) lui $t1, %hi(_bssSegmentLen) addiu $t0, $t0, %lo(_bssSegmentStart) ori $t1, $t1, %lo(_bssSegmentLen) -.L00001010: +.bss_loop: addi $t1, $t1, -8 sw $zero, 0($t0) sw $zero, 4($t0) - bnez $t1, .L00001010 + bnez $t1, .bss_loop addi $t0, $t0, 8 - lui $t2, %hi(tlbInitFromPreamble) - lui $sp, 0x8000 - addiu $t2, $t2, %lo(tlbInitFromPreamble) + + lui $t2, %hi(vmBootFromPreamble) + li $sp, K0BASE + addiu $t2, $t2, %lo(vmBootFromPreamble) jr $t2 addiu $sp, $sp, 0xf10 diff --git a/tools/mkrom/piracy.c b/tools/mkrom/piracy.c index 2e63f4f80..dcd9701d8 100644 --- a/tools/mkrom/piracy.c +++ b/tools/mkrom/piracy.c @@ -163,7 +163,7 @@ static void patch(Algo algo, char *patchfunc, char *sumfunc) void piracy_patch_checksums(void) { // algorithm, patch function, sum function - patch(algo01, "__scHandleTasks", "bootPhase1"); + patch(algo01, "__scHandleTasks", "boot"); patch(algo02, "cheatMenuHandleDialog", "__scHandleTasks"); patch(algo03, "botPickupProp", "doorFinishClose"); patch(algo04, "chrUncloak", "botPickupProp");