From f4d01bda0ac84ac2fa843de5e2f324a461bcf484 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Fri, 24 Mar 2023 13:03:11 -0700 Subject: [PATCH 01/14] load_fragment2 --- animalforest.jp.yaml | 4 +- include/load.h | 38 ++++++ linker_scripts/jp/symbol_addrs_boot.txt | 4 +- src/boot/load_fragment2.c | 168 ++++++++++++++++++++++++ 4 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 include/load.h create mode 100644 src/boot/load_fragment2.c diff --git a/animalforest.jp.yaml b/animalforest.jp.yaml index 2d42b8bd..7df64d5d 100644 --- a/animalforest.jp.yaml +++ b/animalforest.jp.yaml @@ -85,7 +85,7 @@ segments: - [0x005BE0, asm, boot/005BE0] - [0x005E30, asm, boot/005E30] - [0x006BA0, asm, boot/006BA0] - - [0x006D10, asm, boot/006D10] + - [0x006D10, c, boot/load_fragment2] - [0x007000, asm, boot/007000] - [0x007060, asm, boot/007060] - [0x007530, asm, boot/007530] @@ -265,6 +265,8 @@ segments: - [0x016EF0, data, libultra/rsp/rspboot] - [0x016FC0, data, boot/016FC0] + - [0x017950, .data, boot/load_fragment2] # Not 100% sure correct address as data is unused + - [0x017960, data, boot/017960] - [0x018580, rodata, boot/018580] diff --git a/include/load.h b/include/load.h new file mode 100644 index 00000000..d4c96969 --- /dev/null +++ b/include/load.h @@ -0,0 +1,38 @@ +#ifndef LOAD_H +#define LOAD_H + +#include "ultra64.h" + +extern s32 gOverlayLogSeverity; + +#define RELOC_SECTION(reloc) ((reloc) >> 30) +#define RELOC_OFFSET(reloc) ((reloc) & 0xFFFFFF) +#define RELOC_TYPE_MASK(reloc) ((reloc) & 0x3F000000) +#define RELOC_TYPE_SHIFT 24 + +/* MIPS Relocation Types, matches the MIPS ELF spec */ +#define R_MIPS_32 2 +#define R_MIPS_26 4 +#define R_MIPS_HI16 5 +#define R_MIPS_LO16 6 + +typedef enum { + /* 0 */ RELOC_SECTION_NULL, + /* 1 */ RELOC_SECTION_TEXT, + /* 2 */ RELOC_SECTION_DATA, + /* 3 */ RELOC_SECTION_RODATA, + /* 4 */ RELOC_SECTION_MAX +} RelocSectionId; + +typedef struct OverlayRelocationSection { + /* 0x00 */ u32 textSize; + /* 0x04 */ u32 dataSize; + /* 0x08 */ u32 rodataSize; + /* 0x0C */ u32 bssSize; + /* 0x10 */ u32 nRelocations; + /* 0x14 */ u32 relocations[1]; // size is nRelocations +} OverlayRelocationSection; // size >= 0x18 + +s32 Overlay_Load(void *vromStart, void *vromEnd, void *ovlStart, void *ovlEnd, void *vramStart, void *vramEnd, void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs); + +#endif diff --git a/linker_scripts/jp/symbol_addrs_boot.txt b/linker_scripts/jp/symbol_addrs_boot.txt index ec6f2a1a..70a91d52 100644 --- a/linker_scripts/jp/symbol_addrs_boot.txt +++ b/linker_scripts/jp/symbol_addrs_boot.txt @@ -141,8 +141,8 @@ func_8002B750_jp = 0x8002B750; // type:func func_8002B770_jp = 0x8002B770; // type:func func_8002B7A0_jp = 0x8002B7A0; // type:func func_8002B8E8_jp = 0x8002B8E8; // type:func -func_8002B910_jp = 0x8002B910; // type:func -func_8002B9C0_jp = 0x8002B9C0; // type:func +Overlay_Load = 0x8002B910; // type:func +Overlay_Relocate = 0x8002B9C0; // type:func func_8002BC00_jp = 0x8002BC00; // type:func func_8002BC34_jp = 0x8002BC34; // type:func func_8002BC60_jp = 0x8002BC60; // type:func diff --git a/src/boot/load_fragment2.c b/src/boot/load_fragment2.c new file mode 100644 index 00000000..7eeb8df1 --- /dev/null +++ b/src/boot/load_fragment2.c @@ -0,0 +1,168 @@ +/** + * @file loadfragment2.c + * + * Functions used to process and relocate overlays. + * + */ +#include "global.h" +#include "load.h" + +s32 gOverlayLogSeverity = 0; + +void func_80026B44_jp(void* arg0, void* arg1, size_t arg2); + +void Overlay_Relocate(void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs, void *vramStart); + +s32 Overlay_Load(void *vromStart, void *vromEnd, void *ovlStart, void *ovlEnd, void *vramStart, void *vramEnd, + void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs) { + OverlayRelocationSection *ovl = ovlRelocs; + s32 vromSize = (uintptr_t)vromEnd - (uintptr_t)vromStart; + s32 ovlSize = (uintptr_t)ovlEnd - (uintptr_t)ovlStart; + s32 vramSize = (uintptr_t)vramEnd - (uintptr_t)vramStart; + void *end = (void *)((uintptr_t)allocatedRamAddress + vromSize); + + func_80026B44_jp(allocatedRamAddress, vromStart, vromSize); + func_80026B44_jp(ovl, ovlStart, ovlSize); + Overlay_Relocate(allocatedRamAddress, ovl, vramStart); + + if (ovl->bssSize != 0) { + bzero(end, ovl->bssSize); + } + + osWritebackDCache(allocatedRamAddress, vramSize); + osInvalICache(allocatedRamAddress, vramSize); + return vramSize; +} + +#define MIPS_REG_RS(insn) (((insn) >> 0x15) & 0x1F) + +// Extract MIPS register rt from an instruction word +#define MIPS_REG_RT(insn) (((insn) >> 0x10) & 0x1F) + +// Extract MIPS jump target from an instruction word +#define MIPS_JUMP_TARGET(insn) (((insn)&0x03FFFFFF) << 2) + +void Overlay_Relocate(void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs, void *vramStart) { + uintptr_t sections[RELOC_SECTION_MAX]; + u32 *relocDataP; + u32 reloc; + u32 relocData; + UNUSED u32 dbg; + uintptr_t allocu32 = (uintptr_t)allocatedRamAddress; + u32 i; + u32 *regValP; + //! MIPS ELF relocation does not generally require tracking register values, so at first glance it appears this + //! register tracking was an unnecessary complication. However there is a bug in the IDO compiler that can cause + //! relocations to be emitted in the wrong order under rare circumstances when the compiler attempts to reuse a + //! previous HI16 relocation for a different LO16 relocation as an optimization. This register tracking is likely + //! a workaround to prevent improper matching of unrelated HI16 and LO16 relocations that would otherwise arise + //! due to the incorrect ordering. + u32 *luiRefs[32]; + u32 luiVals[32]; + u32 *luiInstRef; + size_t relocOffset; + u32 isLoNeg; + u32 relocatedValue; + UNUSED uintptr_t unrelocatedAddress; + uintptr_t relocatedAddress; + UNUSED s32 pad; + + relocOffset = 0; + relocatedValue = 0; + unrelocatedAddress = 0; + relocatedAddress = 0; + + if (gOverlayLogSeverity >= 3) {} + + sections[RELOC_SECTION_NULL] = 0; + sections[RELOC_SECTION_TEXT] = allocu32; + sections[RELOC_SECTION_DATA] = ovlRelocs->textSize + allocu32; + sections[RELOC_SECTION_RODATA] = ovlRelocs->dataSize + sections[RELOC_SECTION_DATA]; + + for (i = 0; i < ovlRelocs->nRelocations; i++) { + reloc = ovlRelocs->relocations[i]; + // This will always resolve to a 32-bit aligned address as each section + // containing code or pointers must be aligned to at least 4 bytes and the + // MIPS ABI defines the offset of both 16-bit and 32-bit relocations to be + // the start of the 32-bit word containing the target. + relocDataP = (u32 *)(sections[RELOC_SECTION(reloc)] + RELOC_OFFSET(reloc)); + relocData = *relocDataP; + + switch (RELOC_TYPE_MASK(reloc)) { + case R_MIPS_32 << RELOC_TYPE_SHIFT: + // Handles 32-bit address relocation, used for things such as jump tables + // and pointers in data. Just relocate the full address. + + // Check address is valid for relocation + if ((*relocDataP & 0x0F000000) == 0) { + relocOffset = *relocDataP - (uintptr_t)vramStart; + relocatedValue = relocOffset + allocu32; + unrelocatedAddress = relocData; + relocatedAddress = relocatedValue; + *relocDataP = relocatedAddress; + } + break; + + case R_MIPS_26 << RELOC_TYPE_SHIFT: + // Handles 26-bit address relocation, used for jumps and jals. + // Extract the address from the target field of the J-type MIPS + // instruction. Relocate the address and update the instruction. + if (1) { + relocOffset = PHYS_TO_K0(MIPS_JUMP_TARGET(*relocDataP)) - (uintptr_t)vramStart; + unrelocatedAddress = PHYS_TO_K0(MIPS_JUMP_TARGET(*relocDataP)); + relocatedValue = (*relocDataP & 0xFC000000) | (((allocu32 + relocOffset) & 0x0FFFFFFF) >> 2); + relocatedAddress = PHYS_TO_K0(MIPS_JUMP_TARGET(relocatedValue)); + *relocDataP = relocatedValue; + } + break; + + case R_MIPS_HI16 << RELOC_TYPE_SHIFT: + // Handles relocation for a hi/lo pair, part 1. + // Store the reference to the LUI instruction (hi) using the `rt` register + // of the instruction. This will be updated later in the `R_MIPS_LO16` + // section. + + luiRefs[MIPS_REG_RT(*relocDataP)] = relocDataP; + luiVals[MIPS_REG_RT(*relocDataP)] = *relocDataP; + break; + + case R_MIPS_LO16 << RELOC_TYPE_SHIFT: + // Handles relocation for a hi/lo pair, part 2. + // Grab the stored LUI (hi) from the `R_MIPS_HI16` section using the `rs` + // register of the instruction. The full address is calculated, relocated, + // and then used to update both the LUI and lo instructions. If the lo + // part is negative, add 1 to the LUI value. Note: The lo instruction is + // assumed to have a signed immediate. + + luiInstRef = luiRefs[MIPS_REG_RS(*relocDataP)]; + regValP = &luiVals[MIPS_REG_RS(*relocDataP)]; + + // Check address is valid for relocation + if ((((*regValP << 0x10) + (s16)*relocDataP) & 0x0F000000) == 0) { + relocOffset = ((*regValP << 0x10) + (s16)*relocDataP) - (uintptr_t)vramStart; + isLoNeg = ((relocOffset + allocu32) & 0x8000) ? 1 : 0; // adjust for signed immediate + unrelocatedAddress = (*luiInstRef << 0x10) + (s16)relocData; + *luiInstRef = + (*luiInstRef & 0xFFFF0000) | ((((relocOffset + allocu32) >> 0x10) & 0xFFFF) + isLoNeg); + relocatedValue = (*relocDataP & 0xFFFF0000) | ((relocOffset + allocu32) & 0xFFFF); + + relocatedAddress = (*luiInstRef << 0x10) + (s16)relocatedValue; + *relocDataP = relocatedValue; + } + break; + } + + dbg = 16; + switch (RELOC_TYPE_MASK(reloc)) { + case R_MIPS_32 << RELOC_TYPE_SHIFT: + dbg += 6; + FALLTHROUGH; + case R_MIPS_26 << RELOC_TYPE_SHIFT: + dbg += 10; + FALLTHROUGH; + case R_MIPS_LO16 << RELOC_TYPE_SHIFT: + if (gOverlayLogSeverity >= 3) {} + // Adding a break prevents matching + } + } +} From ed55b3c7b0f155b44f4e1641bd97e062d4b4b560 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Tue, 28 Mar 2023 20:24:08 -0700 Subject: [PATCH 02/14] dma.h --- include/dma.h | 8 ++++++++ linker_scripts/jp/symbol_addrs_boot.txt | 2 +- src/boot/load_fragment2.c | 24 +++++++++--------------- 3 files changed, 18 insertions(+), 16 deletions(-) create mode 100644 include/dma.h diff --git a/include/dma.h b/include/dma.h new file mode 100644 index 00000000..aa18ec72 --- /dev/null +++ b/include/dma.h @@ -0,0 +1,8 @@ +#ifndef DMA_H +#define DMA_H + +#include "ultra64.h" + +void DmaMgr_RequestSync(void* ram, void* vrom, size_t size); + +#endif diff --git a/linker_scripts/jp/symbol_addrs_boot.txt b/linker_scripts/jp/symbol_addrs_boot.txt index 70a91d52..b27054bd 100644 --- a/linker_scripts/jp/symbol_addrs_boot.txt +++ b/linker_scripts/jp/symbol_addrs_boot.txt @@ -24,7 +24,7 @@ func_80026814_jp = 0x80026814; // type:func func_80026828_jp = 0x80026828; // type:func func_800269E4_jp = 0x800269E4; // type:func func_80026A64_jp = 0x80026A64; // type:func -func_80026B44_jp = 0x80026B44; // type:func +DmaMgr_RequestSync = 0x80026B44; // type:func func_80026BC0_jp = 0x80026BC0; // type:func func_80026C00_jp = 0x80026C00; // type:func func_80026C28_jp = 0x80026C28; // type:func diff --git a/src/boot/load_fragment2.c b/src/boot/load_fragment2.c index 7eeb8df1..cb0a3bc8 100644 --- a/src/boot/load_fragment2.c +++ b/src/boot/load_fragment2.c @@ -5,12 +5,11 @@ * */ #include "global.h" +#include "dma.h" #include "load.h" s32 gOverlayLogSeverity = 0; -void func_80026B44_jp(void* arg0, void* arg1, size_t arg2); - void Overlay_Relocate(void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs, void *vramStart); s32 Overlay_Load(void *vromStart, void *vromEnd, void *ovlStart, void *ovlEnd, void *vramStart, void *vramEnd, @@ -21,8 +20,8 @@ s32 Overlay_Load(void *vromStart, void *vromEnd, void *ovlStart, void *ovlEnd, v s32 vramSize = (uintptr_t)vramEnd - (uintptr_t)vramStart; void *end = (void *)((uintptr_t)allocatedRamAddress + vromSize); - func_80026B44_jp(allocatedRamAddress, vromStart, vromSize); - func_80026B44_jp(ovl, ovlStart, ovlSize); + DmaMgr_RequestSync(allocatedRamAddress, vromStart, vromSize); + DmaMgr_RequestSync(ovl, ovlStart, ovlSize); Overlay_Relocate(allocatedRamAddress, ovl, vramStart); if (ovl->bssSize != 0) { @@ -47,7 +46,7 @@ void Overlay_Relocate(void *allocatedRamAddress, OverlayRelocationSection *ovlRe u32 *relocDataP; u32 reloc; u32 relocData; - UNUSED u32 dbg; + u32 isLoNeg; uintptr_t allocu32 = (uintptr_t)allocatedRamAddress; u32 i; u32 *regValP; @@ -60,18 +59,13 @@ void Overlay_Relocate(void *allocatedRamAddress, OverlayRelocationSection *ovlRe u32 *luiRefs[32]; u32 luiVals[32]; u32 *luiInstRef; - size_t relocOffset; - u32 isLoNeg; - u32 relocatedValue; - UNUSED uintptr_t unrelocatedAddress; - uintptr_t relocatedAddress; + UNUSED u32 dbg; + size_t relocOffset = 0; + u32 relocatedValue = 0; + UNUSED uintptr_t unrelocatedAddress = 0; + uintptr_t relocatedAddress = 0; UNUSED s32 pad; - relocOffset = 0; - relocatedValue = 0; - unrelocatedAddress = 0; - relocatedAddress = 0; - if (gOverlayLogSeverity >= 3) {} sections[RELOC_SECTION_NULL] = 0; From 535ab0480626ac988de860560c2dd86d42323ddb Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Tue, 28 Mar 2023 20:44:54 -0700 Subject: [PATCH 03/14] og DoRelocation --- linker_scripts/jp/symbol_addrs_boot.txt | 2 +- src/boot/load_fragment2.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/linker_scripts/jp/symbol_addrs_boot.txt b/linker_scripts/jp/symbol_addrs_boot.txt index b27054bd..b756ddec 100644 --- a/linker_scripts/jp/symbol_addrs_boot.txt +++ b/linker_scripts/jp/symbol_addrs_boot.txt @@ -142,7 +142,7 @@ func_8002B770_jp = 0x8002B770; // type:func func_8002B7A0_jp = 0x8002B7A0; // type:func func_8002B8E8_jp = 0x8002B8E8; // type:func Overlay_Load = 0x8002B910; // type:func -Overlay_Relocate = 0x8002B9C0; // type:func +DoRelocation = 0x8002B9C0; // type:func func_8002BC00_jp = 0x8002BC00; // type:func func_8002BC34_jp = 0x8002BC34; // type:func func_8002BC60_jp = 0x8002BC60; // type:func diff --git a/src/boot/load_fragment2.c b/src/boot/load_fragment2.c index cb0a3bc8..121f5357 100644 --- a/src/boot/load_fragment2.c +++ b/src/boot/load_fragment2.c @@ -10,7 +10,7 @@ s32 gOverlayLogSeverity = 0; -void Overlay_Relocate(void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs, void *vramStart); +void DoRelocation(void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs, void *vramStart); s32 Overlay_Load(void *vromStart, void *vromEnd, void *ovlStart, void *ovlEnd, void *vramStart, void *vramEnd, void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs) { @@ -22,7 +22,7 @@ s32 Overlay_Load(void *vromStart, void *vromEnd, void *ovlStart, void *ovlEnd, v DmaMgr_RequestSync(allocatedRamAddress, vromStart, vromSize); DmaMgr_RequestSync(ovl, ovlStart, ovlSize); - Overlay_Relocate(allocatedRamAddress, ovl, vramStart); + DoRelocation(allocatedRamAddress, ovl, vramStart); if (ovl->bssSize != 0) { bzero(end, ovl->bssSize); @@ -41,7 +41,7 @@ s32 Overlay_Load(void *vromStart, void *vromEnd, void *ovlStart, void *ovlEnd, v // Extract MIPS jump target from an instruction word #define MIPS_JUMP_TARGET(insn) (((insn)&0x03FFFFFF) << 2) -void Overlay_Relocate(void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs, void *vramStart) { +void DoRelocation(void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs, void *vramStart) { uintptr_t sections[RELOC_SECTION_MAX]; u32 *relocDataP; u32 reloc; From 8a42654bb764e25b232820cdbb383ddbbed25ce8 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Tue, 28 Mar 2023 21:06:37 -0700 Subject: [PATCH 04/14] comment format --- src/boot/load_fragment2.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/boot/load_fragment2.c b/src/boot/load_fragment2.c index 121f5357..8dfd25a4 100644 --- a/src/boot/load_fragment2.c +++ b/src/boot/load_fragment2.c @@ -84,8 +84,8 @@ void DoRelocation(void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs switch (RELOC_TYPE_MASK(reloc)) { case R_MIPS_32 << RELOC_TYPE_SHIFT: - // Handles 32-bit address relocation, used for things such as jump tables - // and pointers in data. Just relocate the full address. + // Handles 32-bit address relocation, used for things such as jump tables and pointers in data. + // Just relocate the full address. // Check address is valid for relocation if ((*relocDataP & 0x0F000000) == 0) { @@ -99,8 +99,8 @@ void DoRelocation(void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs case R_MIPS_26 << RELOC_TYPE_SHIFT: // Handles 26-bit address relocation, used for jumps and jals. - // Extract the address from the target field of the J-type MIPS - // instruction. Relocate the address and update the instruction. + // Extract the address from the target field of the J-type MIPS instruction. + // Relocate the address and update the instruction. if (1) { relocOffset = PHYS_TO_K0(MIPS_JUMP_TARGET(*relocDataP)) - (uintptr_t)vramStart; unrelocatedAddress = PHYS_TO_K0(MIPS_JUMP_TARGET(*relocDataP)); @@ -112,9 +112,8 @@ void DoRelocation(void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs case R_MIPS_HI16 << RELOC_TYPE_SHIFT: // Handles relocation for a hi/lo pair, part 1. - // Store the reference to the LUI instruction (hi) using the `rt` register - // of the instruction. This will be updated later in the `R_MIPS_LO16` - // section. + // Store the reference to the LUI instruction (hi) using the `rt` register of the instruction. + // This will be updated later in the `R_MIPS_LO16` section. luiRefs[MIPS_REG_RT(*relocDataP)] = relocDataP; luiVals[MIPS_REG_RT(*relocDataP)] = *relocDataP; @@ -122,11 +121,10 @@ void DoRelocation(void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs case R_MIPS_LO16 << RELOC_TYPE_SHIFT: // Handles relocation for a hi/lo pair, part 2. - // Grab the stored LUI (hi) from the `R_MIPS_HI16` section using the `rs` - // register of the instruction. The full address is calculated, relocated, - // and then used to update both the LUI and lo instructions. If the lo - // part is negative, add 1 to the LUI value. Note: The lo instruction is - // assumed to have a signed immediate. + // Grab the stored LUI (hi) from the `R_MIPS_HI16` section using the `rs` register of the instruction. + // The full address is calculated, relocated, and then used to update both the LUI and lo instructions. + // If the lo part is negative, add 1 to the LUI value. + // Note: The lo instruction is assumed to have a signed immediate. luiInstRef = luiRefs[MIPS_REG_RS(*relocDataP)]; regValP = &luiVals[MIPS_REG_RS(*relocDataP)]; From 5f3217930146ae59582cc7742fd54bdb1f3c9fc0 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Tue, 28 Mar 2023 21:34:33 -0700 Subject: [PATCH 05/14] A few more docs --- include/load.h | 2 +- src/boot/load_fragment2.c | 41 +++++++++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/include/load.h b/include/load.h index d4c96969..9b3c8a94 100644 --- a/include/load.h +++ b/include/load.h @@ -33,6 +33,6 @@ typedef struct OverlayRelocationSection { /* 0x14 */ u32 relocations[1]; // size is nRelocations } OverlayRelocationSection; // size >= 0x18 -s32 Overlay_Load(void *vromStart, void *vromEnd, void *ovlStart, void *ovlEnd, void *vramStart, void *vramEnd, void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs); +s32 Overlay_Load(void *vromStart, void *vromEnd, void *ovlStart, void *ovlEnd, void *vramStart, void *vramEnd, void *allocatedRamAddr, OverlayRelocationSection *ovlRelocs); #endif diff --git a/src/boot/load_fragment2.c b/src/boot/load_fragment2.c index 8dfd25a4..811aff9f 100644 --- a/src/boot/load_fragment2.c +++ b/src/boot/load_fragment2.c @@ -1,7 +1,7 @@ /** * @file loadfragment2.c * - * Functions used to process and relocate overlays. + * Functions used to process and relocate dynamically loadable code segments (overlays). * */ #include "global.h" @@ -10,29 +10,30 @@ s32 gOverlayLogSeverity = 0; -void DoRelocation(void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs, void *vramStart); +void DoRelocation(void *allocatedRamAddr, OverlayRelocationSection *ovlRelocs, void *vramStart); s32 Overlay_Load(void *vromStart, void *vromEnd, void *ovlStart, void *ovlEnd, void *vramStart, void *vramEnd, - void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs) { + void *allocatedRamAddr, OverlayRelocationSection *ovlRelocs) { OverlayRelocationSection *ovl = ovlRelocs; s32 vromSize = (uintptr_t)vromEnd - (uintptr_t)vromStart; s32 ovlSize = (uintptr_t)ovlEnd - (uintptr_t)ovlStart; s32 vramSize = (uintptr_t)vramEnd - (uintptr_t)vramStart; - void *end = (void *)((uintptr_t)allocatedRamAddress + vromSize); + void *end = (void *)((uintptr_t)allocatedRamAddr + vromSize); - DmaMgr_RequestSync(allocatedRamAddress, vromStart, vromSize); + DmaMgr_RequestSync(allocatedRamAddr, vromStart, vromSize); DmaMgr_RequestSync(ovl, ovlStart, ovlSize); - DoRelocation(allocatedRamAddress, ovl, vramStart); + DoRelocation(allocatedRamAddr, ovl, vramStart); if (ovl->bssSize != 0) { bzero(end, ovl->bssSize); } - osWritebackDCache(allocatedRamAddress, vramSize); - osInvalICache(allocatedRamAddress, vramSize); + osWritebackDCache(allocatedRamAddr, vramSize); + osInvalICache(allocatedRamAddr, vramSize); return vramSize; } +// Extract MIPS register rs from an instruction word #define MIPS_REG_RS(insn) (((insn) >> 0x15) & 0x1F) // Extract MIPS register rt from an instruction word @@ -41,13 +42,33 @@ s32 Overlay_Load(void *vromStart, void *vromEnd, void *ovlStart, void *ovlEnd, v // Extract MIPS jump target from an instruction word #define MIPS_JUMP_TARGET(insn) (((insn)&0x03FFFFFF) << 2) -void DoRelocation(void *allocatedRamAddress, OverlayRelocationSection *ovlRelocs, void *vramStart) { +/** + * Performs runtime relocation of overlay files, loadable code segments. + * + * Overlays are expected to be loadable anywhere in direct-mapped cached (KSEG0) memory, with some appropriate + * alignment requirements; memory addresses in such code must be updated once loaded in order to execute properly. + * When compiled, overlays are given 'fake' KSEG0 RAM addresses larger than the total possible available main memory + * (>= 0x80800000), such addresses are referred to as Virtual RAM (VRAM) to distinguish them. When loading the overlay + * the relocation table produced at compile time is consulted to determine where and how to update these VRAM addresses + * to correct RAM addresses based on the location the overlay was loaded at, enabling the code to execute at this + * address as if it were compiled to run at this address. + * + * Each relocation is represented by a packed 32-bit value, formatted in the following way: + * - [31:30] 2-bit section id, taking values from the `RelocSectionId` enum. + * - [29:24] 6-bit relocation type describing which relocation operation should be performed. Same as ELF32 MIPS. + * - [23: 0] 24-bit section-relative offset indicating where in the section to apply this relocation. + * + * @param allocatedRamAddr Memory address the binary was loaded at. + * @param ovlRelocs Overlay relocation section containing overlay section layout and runtime relocations. + * @param vramStart Virtual RAM address that the overlay was compiled at. + */ +void DoRelocation(void *allocatedRamAddr, OverlayRelocationSection *ovlRelocs, void *vramStart) { uintptr_t sections[RELOC_SECTION_MAX]; u32 *relocDataP; u32 reloc; u32 relocData; u32 isLoNeg; - uintptr_t allocu32 = (uintptr_t)allocatedRamAddress; + uintptr_t allocu32 = (uintptr_t)allocatedRamAddr; u32 i; u32 *regValP; //! MIPS ELF relocation does not generally require tracking register values, so at first glance it appears this From ea4d39e08afefc7b3ea941a2c4f941010f103f79 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Wed, 29 Mar 2023 17:06:35 -0700 Subject: [PATCH 06/14] symbol --- linker_scripts/jp/symbol_addrs_boot.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/linker_scripts/jp/symbol_addrs_boot.txt b/linker_scripts/jp/symbol_addrs_boot.txt index b756ddec..8be7d906 100644 --- a/linker_scripts/jp/symbol_addrs_boot.txt +++ b/linker_scripts/jp/symbol_addrs_boot.txt @@ -258,6 +258,7 @@ D_8003BCB0_jp = 0x8003BCB0; // D_8003BD30_jp = 0x8003BD30; // D_8003BD50_jp = 0x8003BD50; // D_8003BD58_jp = 0x8003BD58; // +gOverlayLogSeverity = 0x8003C550; // D_8003C560_jp = 0x8003C560; // D_FLT_8003C584_jp = 0x8003C584; // type:f32 D_8003C590_jp = 0x8003C590; // From 5bec44670548fcf56e44002feaefcc2654586564 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Wed, 29 Mar 2023 22:35:57 -0700 Subject: [PATCH 07/14] remove _ from loadfragment2 --- animalforest.jp.yaml | 4 ++-- src/boot/{load_fragment2.c => loadfragment2.c} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename src/boot/{load_fragment2.c => loadfragment2.c} (100%) diff --git a/animalforest.jp.yaml b/animalforest.jp.yaml index 7df64d5d..891f8cb3 100644 --- a/animalforest.jp.yaml +++ b/animalforest.jp.yaml @@ -85,7 +85,7 @@ segments: - [0x005BE0, asm, boot/005BE0] - [0x005E30, asm, boot/005E30] - [0x006BA0, asm, boot/006BA0] - - [0x006D10, c, boot/load_fragment2] + - [0x006D10, c, boot/loadfragment2] - [0x007000, asm, boot/007000] - [0x007060, asm, boot/007060] - [0x007530, asm, boot/007530] @@ -265,7 +265,7 @@ segments: - [0x016EF0, data, libultra/rsp/rspboot] - [0x016FC0, data, boot/016FC0] - - [0x017950, .data, boot/load_fragment2] # Not 100% sure correct address as data is unused + - [0x017950, .data, boot/loadfragment2] # Not 100% sure correct address as data is unused - [0x017960, data, boot/017960] - [0x018580, rodata, boot/018580] diff --git a/src/boot/load_fragment2.c b/src/boot/loadfragment2.c similarity index 100% rename from src/boot/load_fragment2.c rename to src/boot/loadfragment2.c From f813b144f563c1bb2a600657e1258682cb9c0584 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Thu, 30 Mar 2023 07:40:51 -0700 Subject: [PATCH 08/14] ptrdiff_t --- src/boot/loadfragment2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boot/loadfragment2.c b/src/boot/loadfragment2.c index 811aff9f..1058b57a 100644 --- a/src/boot/loadfragment2.c +++ b/src/boot/loadfragment2.c @@ -81,7 +81,7 @@ void DoRelocation(void *allocatedRamAddr, OverlayRelocationSection *ovlRelocs, v u32 luiVals[32]; u32 *luiInstRef; UNUSED u32 dbg; - size_t relocOffset = 0; + ptrdiff_t relocOffset = 0; u32 relocatedValue = 0; UNUSED uintptr_t unrelocatedAddress = 0; uintptr_t relocatedAddress = 0; From f42c6fa867922ed4355a154214029c346e89425b Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Mon, 3 Apr 2023 17:42:08 -0700 Subject: [PATCH 09/14] z_std_dma.h --- include/dma.h | 8 -------- include/z_std_dma.h | 2 +- src/boot/loadfragment2.c | 2 +- src/boot/logseverity.c | 2 +- 4 files changed, 3 insertions(+), 11 deletions(-) delete mode 100644 include/dma.h diff --git a/include/dma.h b/include/dma.h deleted file mode 100644 index aa18ec72..00000000 --- a/include/dma.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef DMA_H -#define DMA_H - -#include "ultra64.h" - -void DmaMgr_RequestSync(void* ram, void* vrom, size_t size); - -#endif diff --git a/include/z_std_dma.h b/include/z_std_dma.h index 36a40510..c1474c4f 100644 --- a/include/z_std_dma.h +++ b/include/z_std_dma.h @@ -13,7 +13,7 @@ // void func_80026828_jp(); // void func_800269E4_jp(); // void func_80026A64_jp(); -// void func_80026B44_jp(); +void DmaMgr_RequestSync(void* ram, void* vrom, size_t size); // void func_80026BC0_jp(); // void func_80026C00_jp(); // void func_80026C28_jp(); diff --git a/src/boot/loadfragment2.c b/src/boot/loadfragment2.c index 70040098..90e604fa 100644 --- a/src/boot/loadfragment2.c +++ b/src/boot/loadfragment2.c @@ -5,8 +5,8 @@ * */ #include "global.h" -#include "dma.h" #include "load.h" +#include "z_std_dma.h" void DoRelocation(void *allocatedRamAddr, OverlayRelocationSection *ovlRelocs, void *vramStart); diff --git a/src/boot/logseverity.c b/src/boot/logseverity.c index 0f1efbc5..940aa87c 100644 --- a/src/boot/logseverity.c +++ b/src/boot/logseverity.c @@ -1,3 +1,3 @@ #include "global.h" -s32 gOverlayLogSeverity = 2; \ No newline at end of file +s32 gOverlayLogSeverity = 2; From b572fddf8fa1ba3ab4f25bf83a5ed9bc36889872 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Mon, 8 May 2023 22:24:20 -0700 Subject: [PATCH 10/14] Format --- src/boot/loadfragment2.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/boot/loadfragment2.c b/src/boot/loadfragment2.c index 90e604fa..383cde07 100644 --- a/src/boot/loadfragment2.c +++ b/src/boot/loadfragment2.c @@ -8,15 +8,15 @@ #include "load.h" #include "z_std_dma.h" -void DoRelocation(void *allocatedRamAddr, OverlayRelocationSection *ovlRelocs, void *vramStart); +void DoRelocation(void* allocatedRamAddr, OverlayRelocationSection* ovlRelocs, void* vramStart); -s32 Overlay_Load(void *vromStart, void *vromEnd, void *ovlStart, void *ovlEnd, void *vramStart, void *vramEnd, - void *allocatedRamAddr, OverlayRelocationSection *ovlRelocs) { - OverlayRelocationSection *ovl = ovlRelocs; +s32 Overlay_Load(void* vromStart, void* vromEnd, void* ovlStart, void* ovlEnd, void* vramStart, void* vramEnd, + void* allocatedRamAddr, OverlayRelocationSection* ovlRelocs) { + OverlayRelocationSection* ovl = ovlRelocs; s32 vromSize = (uintptr_t)vromEnd - (uintptr_t)vromStart; s32 ovlSize = (uintptr_t)ovlEnd - (uintptr_t)ovlStart; s32 vramSize = (uintptr_t)vramEnd - (uintptr_t)vramStart; - void *end = (void *)((uintptr_t)allocatedRamAddr + vromSize); + void* end = (void*)((uintptr_t)allocatedRamAddr + vromSize); DmaMgr_RequestSync(allocatedRamAddr, vromStart, vromSize); DmaMgr_RequestSync(ovl, ovlStart, ovlSize); @@ -60,24 +60,24 @@ s32 Overlay_Load(void *vromStart, void *vromEnd, void *ovlStart, void *ovlEnd, v * @param ovlRelocs Overlay relocation section containing overlay section layout and runtime relocations. * @param vramStart Virtual RAM address that the overlay was compiled at. */ -void DoRelocation(void *allocatedRamAddr, OverlayRelocationSection *ovlRelocs, void *vramStart) { +void DoRelocation(void* allocatedRamAddr, OverlayRelocationSection* ovlRelocs, void* vramStart) { uintptr_t sections[RELOC_SECTION_MAX]; - u32 *relocDataP; + u32* relocDataP; u32 reloc; u32 relocData; u32 isLoNeg; uintptr_t allocu32 = (uintptr_t)allocatedRamAddr; u32 i; - u32 *regValP; + u32* regValP; //! MIPS ELF relocation does not generally require tracking register values, so at first glance it appears this //! register tracking was an unnecessary complication. However there is a bug in the IDO compiler that can cause //! relocations to be emitted in the wrong order under rare circumstances when the compiler attempts to reuse a //! previous HI16 relocation for a different LO16 relocation as an optimization. This register tracking is likely //! a workaround to prevent improper matching of unrelated HI16 and LO16 relocations that would otherwise arise //! due to the incorrect ordering. - u32 *luiRefs[32]; + u32* luiRefs[32]; u32 luiVals[32]; - u32 *luiInstRef; + u32* luiInstRef; UNUSED u32 dbg; ptrdiff_t relocOffset = 0; u32 relocatedValue = 0; @@ -98,7 +98,7 @@ void DoRelocation(void *allocatedRamAddr, OverlayRelocationSection *ovlRelocs, v // containing code or pointers must be aligned to at least 4 bytes and the // MIPS ABI defines the offset of both 16-bit and 32-bit relocations to be // the start of the 32-bit word containing the target. - relocDataP = (u32 *)(sections[RELOC_SECTION(reloc)] + RELOC_OFFSET(reloc)); + relocDataP = (u32*)(sections[RELOC_SECTION(reloc)] + RELOC_OFFSET(reloc)); relocData = *relocDataP; switch (RELOC_TYPE_MASK(reloc)) { From 8ba3d66cedb979df6231c12f071d2f1eedb12dca Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Mon, 8 May 2023 22:33:38 -0700 Subject: [PATCH 11/14] load.h -> loadfragment.h --- include/{load.h => loadfragment.h} | 4 ++-- src/boot/loadfragment2.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename include/{load.h => loadfragment.h} (95%) diff --git a/include/load.h b/include/loadfragment.h similarity index 95% rename from include/load.h rename to include/loadfragment.h index 9b3c8a94..37a747ce 100644 --- a/include/load.h +++ b/include/loadfragment.h @@ -1,5 +1,5 @@ -#ifndef LOAD_H -#define LOAD_H +#ifndef LOADFRAGMENT_H +#define LOADFRAGMENT_H #include "ultra64.h" diff --git a/src/boot/loadfragment2.c b/src/boot/loadfragment2.c index 383cde07..595353ec 100644 --- a/src/boot/loadfragment2.c +++ b/src/boot/loadfragment2.c @@ -5,7 +5,7 @@ * */ #include "global.h" -#include "load.h" +#include "loadfragment.h" #include "z_std_dma.h" void DoRelocation(void* allocatedRamAddr, OverlayRelocationSection* ovlRelocs, void* vramStart); From d9e44da6f8c573a7c58beaca6f8e13159d6785ee Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Sat, 13 May 2023 12:37:16 -0700 Subject: [PATCH 12/14] laodframgnet2 file optflags --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bf4eabdd..5227c638 100644 --- a/Makefile +++ b/Makefile @@ -140,7 +140,7 @@ AS_DEFINES := -DMIPSEB -D_LANGUAGE_ASSEMBLY -D_ULTRA64 C_DEFINES := -DLANGUAGE_C -D_LANGUAGE_C ENDIAN := -EB -OPTFLAGS := -O2 +OPTFLAGS := -O2 -g3 MIPS_VERSION := -mips2 ICONV_FLAGS := --from-code=UTF-8 --to-code=EUC-JP @@ -183,6 +183,7 @@ $(shell mkdir -p $(BUILD_DIR)/linker_scripts/$(VERSION) $(BUILD_DIR)/linker_scri # directory flags # per-file flags +build/src/boot/loadfragment2.o: OPTFLAGS := -O2 # cc & asm-processor build/src/%.o: CC := $(ASM_PROC) $(ASM_PROC_FLAGS) $(CC) -- $(AS) $(ASFLAGS) -- From c19f7e6b0ebd2f6b9c15dbfa1ed5c202cb4b1e87 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Wed, 14 Jun 2023 17:07:27 -0700 Subject: [PATCH 13/14] Small notes --- src/boot/loadfragment2.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/boot/loadfragment2.c b/src/boot/loadfragment2.c index 595353ec..42a826d4 100644 --- a/src/boot/loadfragment2.c +++ b/src/boot/loadfragment2.c @@ -3,6 +3,8 @@ * * Functions used to process and relocate dynamically loadable code segments (overlays). * + * @note: + * These are for specific fragment overlays with the .ovl file extension */ #include "global.h" #include "loadfragment.h" @@ -10,6 +12,7 @@ void DoRelocation(void* allocatedRamAddr, OverlayRelocationSection* ovlRelocs, void* vramStart); +// Unknown original name s32 Overlay_Load(void* vromStart, void* vromEnd, void* ovlStart, void* ovlEnd, void* vramStart, void* vramEnd, void* allocatedRamAddr, OverlayRelocationSection* ovlRelocs) { OverlayRelocationSection* ovl = ovlRelocs; From f216a509514f4a9ad6d510ee2f342a2088237537 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Sun, 23 Jul 2023 11:15:42 -0700 Subject: [PATCH 14/14] Per directory O2 --- Makefile | 2 +- src/boot/{ => O2}/loadfragment2.c | 0 yamls/jp/boot.yaml | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename src/boot/{ => O2}/loadfragment2.c (100%) diff --git a/Makefile b/Makefile index 5227c638..1f7b355d 100644 --- a/Makefile +++ b/Makefile @@ -181,9 +181,9 @@ $(shell mkdir -p $(BUILD_DIR)/linker_scripts/$(VERSION) $(BUILD_DIR)/linker_scri # directory flags +build/src/boot/O2/%.o: OPTFLAGS := -O2 # per-file flags -build/src/boot/loadfragment2.o: OPTFLAGS := -O2 # cc & asm-processor build/src/%.o: CC := $(ASM_PROC) $(ASM_PROC_FLAGS) $(CC) -- $(AS) $(ASFLAGS) -- diff --git a/src/boot/loadfragment2.c b/src/boot/O2/loadfragment2.c similarity index 100% rename from src/boot/loadfragment2.c rename to src/boot/O2/loadfragment2.c diff --git a/yamls/jp/boot.yaml b/yamls/jp/boot.yaml index 8309f0ba..b4ccd21c 100644 --- a/yamls/jp/boot.yaml +++ b/yamls/jp/boot.yaml @@ -20,7 +20,7 @@ - [0x005BE0, asm, boot/stackcheck] - [0x005E30, asm, boot/gfxprint] - [0x006BA0, asm, boot/mtxuty-cvt] - - [0x006D10, c, boot/loadfragment2] + - [0x006D10, c, boot/O2/loadfragment2] - [0x007000, asm, boot/debug] - [0x007060, asm, boot/007060] - [0x0073A0, asm, boot/0073A0]