diff --git a/arm11/link.ld b/arm11/link.ld index 3b81b9e..9315821 100644 --- a/arm11/link.ld +++ b/arm11/link.ld @@ -4,7 +4,7 @@ ENTRY(__boot) MEMORY { - AXIWRAM (RWX) : ORIGIN = 0x1FF80000, LENGTH = 128K + AXIWRAM (RWX) : ORIGIN = 0x1FF80000, LENGTH = 96K HIGHRAM (RWX) : ORIGIN = 0xFFFF0000, LENGTH = 4K } diff --git a/arm11/source/arm/mmu.c b/arm11/source/arm/mmu.c index ee70bca..8259c03 100755 --- a/arm11/source/arm/mmu.c +++ b/arm11/source/arm/mmu.c @@ -76,7 +76,7 @@ typedef struct { static mmuLevel1Table mmuGlobalTT; // simple watermark allocator for 2nd level page tables -#define MAX_SECOND_LEVEL (4) +#define MAX_SECOND_LEVEL (8) static mmuLevel2Table mmuCoarseTables[MAX_SECOND_LEVEL]; static u32 mmuCoarseAllocated = 0; static mmuLevel2Table *mmuAllocateLevel2Table(void) diff --git a/arm11/source/hw/gpulcd.c b/arm11/source/hw/gpulcd.c index 69f4fe8..39c5daa 100644 --- a/arm11/source/hw/gpulcd.c +++ b/arm11/source/hw/gpulcd.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "arm/timer.h" @@ -58,7 +59,7 @@ unsigned GFX_init(GfxFbFmt mode) // Reset REG_PDN_GPU_CNT = PDN_GPU_CNT_CLK_E; - waitClks(12); + ARM_WaitCycles(12); REG_PDN_GPU_CNT = PDN_GPU_CNT_CLK_E | PDN_GPU_CNT_RST_ALL; REG_GX_GPU_CLK = 0x100; REG_GX_PSC_VRAM = 0; diff --git a/arm11/source/system/sys.c b/arm11/source/system/sys.c index abc92da..77b83f2 100755 --- a/arm11/source/system/sys.c +++ b/arm11/source/system/sys.c @@ -86,6 +86,9 @@ void SYS_CoreZeroInit(void) mmuMapArea(SECTION_TRI(bss), MMU_FLAGS(MMU_CACHE_WBA, MMU_READ_WRITE, 1, 1)); mmuMapArea(SECTION_TRI(shared), MMU_FLAGS(MMU_STRONG_ORDER, MMU_READ_WRITE, 1, 1)); + // BootROM + mmuMapArea(0x00010000, 0x00010000, 32UL << 10, MMU_FLAGS(MMU_CACHE_WT, MMU_READ_ONLY, 0, 1)); + // IO Registers mmuMapArea(0x10100000, 0x10100000, 4UL << 20, MMU_FLAGS(MMU_DEV_SHARED, MMU_READ_WRITE, 1, 1)); diff --git a/arm9/source/start.s b/arm9/source/start.s index 603c4da..547f11b 100644 --- a/arm9/source/start.s +++ b/arm9/source/start.s @@ -3,7 +3,7 @@ .arm #include -#include +#include #include #include "memmap.h" @@ -27,9 +27,9 @@ _start: strlo r2, [r0], #4 blo .LBSS_Clear - ldr r0, =BRF_WB_INV_DCACHE + ldr r0, =BFN_WRITEBACK_INVALIDATE_DCACHE blx r0 @ Writeback & Invalidate Data Cache - ldr r0, =BRF_INVALIDATE_ICACHE + ldr r0, =BFN_INVALIDATE_ICACHE blx r0 @ Invalidate Instruction Cache @ Disable caches / TCMs / MPU diff --git a/arm9/source/system/xrq_handler.s b/arm9/source/system/xrq_handler.s index f017a5c..a35b49a 100644 --- a/arm9/source/system/xrq_handler.s +++ b/arm9/source/system/xrq_handler.s @@ -6,7 +6,6 @@ .arm #include -#include #include "memmap.h" .macro TRAP_ENTRY xrq_id diff --git a/common/arm.c b/common/arm.c deleted file mode 100644 index 37013a9..0000000 --- a/common/arm.c +++ /dev/null @@ -1,230 +0,0 @@ -#include - -#define ARM_TARGET __attribute__((noinline, target("arm"))) - -#ifdef ARM11 - #define ARM_CPS(m) asm_v("CPS " #m) - #define ARM_CPSID(m) asm_v("CPSID " #m) - #define ARM_CPSIE(m) asm_v("CPSIE " #m) - - /* - * An Instruction Synchronization Barrier (ISB) flushes the pipeline in the processor - * so that all instructions following the ISB are fetched from cache or memory - * after the ISB has been completed. - */ - void ARM_TARGET ARM_ISB(void) { - ARM_MCR(p15, 0, 0, c7, c5, 4); - } - - /* - * A Data Memory Barrier (DMB) ensures that all explicit memory accesses before - * the DMB instruction complete before any explicit memory accesses after the DMB instruction start. - */ - void ARM_TARGET ARM_DMB(void) { - ARM_MCR(p15, 0, 0, c7, c10, 5); - } - - /* Wait For Interrupt */ - void ARM_TARGET ARM_WFI(void) { - asm_v("wfi\n\t"); - } - - /* Wait For Event */ - void ARM_TARGET ARM_WFE(void) { - asm_v("wfe\n\t"); - } - - /* Send Event */ - void ARM_TARGET ARM_SEV(void) { - asm_v("sev\n\t"); - } - - /* Auxiliary Control Registers */ - u32 ARM_TARGET ARM_GetACR(void) { - u32 acr; - ARM_MRC(p15, 0, acr, c1, c0, 1); - return acr; - } - - void ARM_TARGET ARM_SetACR(u32 acr) { - ARM_MCR(p15, 0, acr, c1, c0, 1); - } -#endif - - -/* - * A Data Synchronization Barrier (DSB) completes when all - * instructions before this instruction complete. - */ -void ARM_TARGET ARM_DSB(void) { - ARM_MCR(p15, 0, 0, c7, c10, 4); -} - - -/* Control Registers */ -u32 ARM_TARGET ARM_GetCR(void) { - u32 cr; - ARM_MRC(p15, 0, cr, c1, c0, 0); - return cr; -} - -void ARM_TARGET ARM_SetCR(u32 cr) { - ARM_MCR(p15, 0, cr, c1, c0, 0); -} - -/* Thread ID Registers */ -u32 ARM_TARGET ARM_GetTID(void) { - u32 tid; - #ifdef ARM9 - ARM_MRC(p15, 0, tid, c13, c0, 1); - #else - ARM_MRC(p15, 0, tid, c13, c0, 4); - #endif - return tid; -} - -void ARM_TARGET ARM_SetTID(u32 tid) { - #ifdef ARM9 - ARM_MCR(p15, 0, tid, c13, c0, 1); - #else - ARM_MCR(p15, 0, tid, c13, c0, 4); - #endif -} - -/* CPU ID */ -u32 ARM_TARGET ARM_CoreID(void) { - u32 id; - #ifdef ARM9 - id = 0; - #else - ARM_MRC(p15, 0, id, c0, c0, 5); - #endif - return id & 3; -} - -/* Status Register */ -u32 ARM_TARGET ARM_GetCPSR(void) { - u32 sr; - ARM_MRS(sr, cpsr); - return sr; -} - -void ARM_TARGET ARM_SetCPSR_c(u32 sr) { - ARM_MSR(cpsr_c, sr); -} - -void ARM_TARGET ARM_DisableInterrupts(void) { - #ifdef ARM9 - ARM_SetCPSR_c(ARM_GetCPSR() | SR_NOINT); - #else - ARM_CPSID(if); - #endif -} - -void ARM_TARGET ARM_EnableInterrupts(void) { - #ifdef ARM9 - ARM_SetCPSR_c(ARM_GetCPSR() & ~SR_NOINT); - #else - ARM_CPSIE(if); - #endif -} - -u32 ARM_TARGET ARM_EnterCritical(void) { - u32 stat = ARM_GetCPSR(); - ARM_DisableInterrupts(); - return stat & SR_NOINT; -} - -void ARM_TARGET ARM_LeaveCritical(u32 stat) { - ARM_SetCPSR_c((ARM_GetCPSR() & ~SR_NOINT) | stat); -} - - -/* Cache functions */ -void ARM_TARGET ARM_InvIC(void) { - #ifdef ARM9 - ARM_MCR(p15, 0, 0, c7, c5, 0); - #else - ARM_MCR(p15, 0, 0, c7, c7, 0); - #endif -} - -void ARM_TARGET ARM_InvIC_Range(void *base, u32 len) { - u32 addr = (u32)base & ~0x1F; - len >>= 5; - - do { - #ifdef ARM9 - ARM_MCR(p15, 0, addr, c7, c5, 1); - #else - ARM_MCR(p15, 0, addr, c7, c7, 1); - #endif - addr += 0x20; - } while(len--); -} - -void ARM_TARGET ARM_InvDC(void) { - ARM_MCR(p15, 0, 0, c7, c6, 0); -} - -void ARM_TARGET ARM_InvDC_Range(void *base, u32 len) { - u32 addr = (u32)base & ~0x1F; - len >>= 5; - - do { - ARM_MCR(p15, 0, addr, c7, c6, 1); - addr += 0x20; - } while(len--); -} - -void ARM_TARGET ARM_WbDC(void) { - #ifdef ARM9 - u32 seg = 0, ind; - do { - ind = 0; - do { - ARM_MCR(p15, 0, seg | ind, c7, c10, 2); - ind += 0x20; - } while(ind < 0x400); - seg += 0x40000000; - } while(seg != 0); - #else - ARM_MCR(p15, 0, 0, c7, c10, 0); - #endif -} - -void ARM_TARGET ARM_WbDC_Range(void *base, u32 len) { - u32 addr = (u32)base & ~0x1F; - len >>= 5; - - do { - ARM_MCR(p15, 0, addr, c7, c10, 1); - addr += 0x20; - } while(len--); -} - -void ARM_TARGET ARM_WbInvDC(void) { - #ifdef ARM9 - u32 seg = 0, ind; - do { - ind = 0; - do { - ARM_MCR(p15, 0, seg | ind, c7, c14, 2); - ind += 0x20; - } while(ind < 0x400); - seg += 0x40000000; - } while(seg != 0); - #else - ARM_MCR(p15, 0, 0, c7, c14, 0); - #endif -} - -void ARM_TARGET ARM_WbInvDC_Range(void *base, u32 len) { - u32 addr = (u32)base & ~0x1F; - len >>= 5; - - do { - ARM_MCR(p15, 0, addr, c7, c14, 1); - addr += 0x20; - } while(len--); -} diff --git a/common/arm.h b/common/arm.h index 778e6a0..1c4d5c1 100644 --- a/common/arm.h +++ b/common/arm.h @@ -2,6 +2,8 @@ #include "types.h" +#include + /* Status Register flags */ #define SR_USR_MODE (0x10) #define SR_FIQ_MODE (0x11) @@ -91,47 +93,126 @@ #ifdef ARM11 #define REG_ARM_PMR(off, type) ((volatile type*)(0x17E00000 + (off))) - void ARM_ISB(void); - void ARM_DMB(void); - void ARM_WFI(void); - void ARM_WFE(void); - void ARM_SEV(void); - u32 ARM_GetACR(void); - void ARM_SetACR(u32 acr); + static inline void ARM_ISB(void) { + ((void (*)(void))(BFN_INSTSYNCBARRIER))(); + } + + static inline void ARM_DMB(void) { + ((void (*)(void))(BFN_DATAMEMBARRIER))(); + } + + static inline void ARM_WFI(void) { + // replace with a bootrom call if + // switching to thumb is necessary + asm_v("wfi\n\t":::"memory"); + } + + static inline void ARM_WFE(void) { + asm_v("wfe\n\t":::"memory"); // same as above + } + + static inline void ARM_SEV(void) { + asm_v("sev\n\t":::"memory"); // same as above + } + + /* Control Registers */ + static inline u32 ARM_GetCR(void) { + u32 cr; + ARM_MRC(p15, 0, cr, c1, c0, 0); + return cr; + } + + static inline void ARM_SetCR(u32 cr) { + ARM_MCR(p15, 0, cr, c1, c0, 0); + } + + static inline u32 ARM_GetACR(void) { + u32 acr; + ARM_MRC(p15, 0, acr, c1, c0, 1); + return acr; + } + + static inline void ARM_SetACR(u32 acr) { + ARM_MCR(p15, 0, acr, c1, c0, 1); + } + #endif -// Data Synchronization Barrier -void ARM_DSB(void); +/* + * A Data Synchronization Barrier (DSB) completes when all + * instructions before this instruction complete. + */ +static inline void ARM_DSB(void) { + ((void (*)(void))(BFN_DATASYNCBARRIER))(); +} -// Get and set Control Register -u32 ARM_GetCR(void); -void ARM_SetCR(u32 cr); +/* CPU ID */ +static inline u32 ARM_CoreID(void) { + u32 id; + #ifdef ARM9 + id = 0; + #else + ARM_MRC(p15, 0, id, c0, c0, 5); + #endif + return id & 3; +} -// Get and set Thread ID -u32 ARM_GetTID(void); -void ARM_SetTID(u32 tid); +/* Status register management */ +static inline u32 ARM_EnterCritical(void) { + return ((u32 (*)(void))(BFN_ENTERCRITICALSECTION))(); +} -// Core ID (not CPU ID) -u32 ARM_CoreID(void); +static inline void ARM_LeaveCritical(u32 stat) { + ((void (*)(u32))(BFN_LEAVECRITICALSECTION))(stat); +} -// Get and set CPSR -u32 ARM_GetCPSR(void); -void ARM_SetCPSR_c(u32 sr); +static inline void ARM_DisableInterrupts(void) { + ARM_LeaveCritical(SR_NOINT); +} -// Manage interrupts -void ARM_DisableInterrupts(void); -void ARM_EnableInterrupts(void); -u32 ARM_EnterCritical(void); -void ARM_LeaveCritical(u32 stat); +static inline void ARM_EnableInterrupts(void) { + ARM_LeaveCritical(0x00); +} -void ARM_InvIC(void); -void ARM_InvIC_Range(void *base, u32 len); -void ARM_InvDC(void); -void ARM_InvDC_Range(void *base, u32 len); -void ARM_WbDC(void); -void ARM_WbDC_Range(void *base, u32 len); -void ARM_WbInvDC(void); -void ARM_WbInvDC_Range(void *base, u32 len); +/* Cache functions */ +static inline void ARM_InvIC(void) { + ((void (*)(void))(BFN_INVALIDATE_ICACHE))(); +} + +static inline void ARM_InvIC_Range(void *base, u32 len) { + ((void (*)(u32, u32))(BFN_INVALIDATE_ICACHE_RANGE))((u32)base, len); + #ifdef ARM11 // make sure to also invalidate the branch target cache + ((void (*)(u32, u32))(BFN_INVALIDATE_BT_CACHE_RANGE))((u32)base, len); + #endif +} + +static inline void ARM_InvDC(void) { + ((void (*)(void))(BFN_INVALIDATE_DCACHE))(); +} + +static inline void ARM_InvDC_Range(void *base, u32 len) { + ((void (*)(u32, u32))(BFN_INVALIDATE_DCACHE_RANGE))((u32)base, len); +} + +static inline void ARM_WbDC(void) { + ((void (*)(void))(BFN_WRITEBACK_DCACHE))(); +} + +static inline void ARM_WbDC_Range(void *base, u32 len) { + ((void (*)(u32, u32))(BFN_WRITEBACK_DCACHE_RANGE))((u32)base, len); +} + +static inline void ARM_WbInvDC(void) { + ((void (*)(void))(BFN_WRITEBACK_INVALIDATE_DCACHE))(); +} + +static inline void ARM_WbInvDC_Range(void *base, u32 len) { + ((void (*)(u32, u32))(BFN_WRITEBACK_INVALIDATE_DCACHE_RANGE))((u32)base, len); +} + +static inline void ARM_WaitCycles(u32 cycles) { + ((void (*)(u32))(BFN_WAITCYCLES))(cycles); +} static inline void ARM_BKPT(void) { __builtin_trap(); diff --git a/common/bfn.h b/common/bfn.h new file mode 100644 index 0000000..a476c7c --- /dev/null +++ b/common/bfn.h @@ -0,0 +1,135 @@ +#pragma once + +/* + Addresses and declarations of preexisting BootROM functions + All of these functions should follow the standard AAPCS convention +*/ + +#ifdef ARM9 + +// void waitCycles(u32 cycles) +// delays execution time by cycles +#define BFN_WAITCYCLES (0xFFFF0198) + +// void cpuSet(u32 val, u32 *dest, u32 count) +#define BFN_CPUSET (0xFFFF03A4) + +// void cpuCpy(const u32 *src, u32 *dest, u32 count) +#define BFN_CPUCPY (0xFFFF03F0) + +// u32 enterCriticalSection() +// disables interrupts and returns the old irq state +#define BFN_ENTERCRITICALSECTION (0xFFFF06EC) + +// void leaveCriticalSection(u32 irqstate) +// restores the old irq state +#define BFN_LEAVECRITICALSECTION (0xFFFF0700) + +// bool enableDCache() +// enables the data cache and returns the old dcache bit +#define BFN_ENABLE_DCACHE (0xFFFF0798) + +// bool disableDCache() +// disables the data cache +#define BFN_DISABLE_DCACHE (0xFFFF07B0) + +// bool setDCache(bool enable) +// toggles the data cache +#define BFN_SET_DCACHE (0xFFFF07C8) + +// void invalidateDCache() +// invalidates all data cache entries +#define BFN_INVALIDATE_DCACHE (0xFFFF07F0) + +// void writebackDCache() +// writes back all data cache entries +#define BFN_WRITEBACK_DCACHE (0xFFFF07FC) + +// void writebackInvalidateDCache() +// writes back and invalidates all data cache entries +#define BFN_WRITEBACK_INVALIDATE_DCACHE (0xFFFF0830) + +// void invalidateDCacheRange(u32 start, u32 end) +// invalidates data cache entries +#define BFN_INVALIDATE_DCACHE_RANGE (0xFFFF0868) + +// void writebackDCacheRange(u32 start, u32 end) +// writes back data cache entries +#define BFN_WRITEBACK_DCACHE_RANGE (0xFFFF0884) + +// void writebackInvalidateDCacheRange(u32 start, u32 end) +#define BFN_WRITEBACK_INVALIDATE_DCACHE_RANGE (0xFFFF08A8) + +// void dataSynchronizationBarrier() +#define BFN_DATASYNCBARRIER (0xFFFF096C) + +// bool enableICache() +#define BFN_ENABLE_ICACHE (0xFFFF0A5C) + +// bool disableICache() +#define BFN_DISABLE_ICACHE (0xFFFF0A74) + +// bool setICache(bool enable) +#define BFN_SET_ICACHE (0xFFFF0A8C) + +// void invalidateICache() +#define BFN_INVALIDATE_ICACHE (0xFFFF0AB4) + +// void invalidateICacheRange(u32 start, u32 end) +#define BFN_INVALIDATE_ICACHE_RANGE (0xFFFF0AC0) + +// void enableMPU() +#define BFN_ENABLE_MPU (0xFFFF0C38) + +// void disableMPU() +#define BFN_DISABLE_MPU (0xFFFF0C48) + +// void resetControlRegisters() +// set CR0 to its reset state (MPU & caches disabled, high vectors, TCMs enabled) +// invalidates both instruction and data caches (without previously writing back!!) +#define BFN_RESET_CRS (0xFFFF0C58) + +#else + +#define BFN_WAITCYCLES (0x00011A38) + +#define BFN_CPUSET (0x000116E4) +#define BFN_CPUCPY (0x00011730) + +#define BFN_ENTERCRITICALSECTION (0x00011AC4) +#define BFN_LEAVECRITICALSECTION (0x00011AD8) + +#define BFN_ENABLE_DCACHE (0x00011288) +#define BFN_DISABLE_DCACHE (0x000112A0) +#define BFN_SET_DCACHE (0x000112B8) + +#define BFN_INVALIDATE_DCACHE (0x000112E0) +#define BFN_WRITEBACK_DCACHE (0x000112EC) +#define BFN_WRITEBACK_INVALIDATE_DCACHE (0x00011320) + +#define BFN_INVALIDATE_DCACHE_RANGE (0x00011358) +#define BFN_WRITEBACK_DCACHE_RANGE (0x00011374) +#define BFN_WRITEBACK_INVALIDATE_DCACHE_RANGE (0x00011398) + +#define BFN_DATASYNCBARRIER (0x000113C0) + +#define BFN_DATAMEMBARRIER (0x000113E8) + +#define BFN_ENABLE_ICACHE (0x000113F4) +#define BFN_DISABLE_ICACHE (0x0001140C) +#define BFN_SET_ICACHE (0x00011424) + +// also invalidates the branch target cache in ARM11 +#define BFN_INVALIDATE_ICACHE (0x0001144C) + +// WARNING: DOES NOT INVALIDATE THE BRANCH TARGET CACHE +// NEEDS TO INVALIDATE IT AND FLUSH THE PREFETCH BUFFER +#define BFN_INVALIDATE_ICACHE_RANGE (0x00011458) + +// void instructionSynchronizationBarrier() +#define BFN_INSTSYNCBARRIER (0x00011490) + +// void invalidateBranchTargetCache() +#define BFN_INVALIDATE_BT_CACHE_RANGE (0x000114F4) + +#endif diff --git a/common/brf.h b/common/brf.h deleted file mode 100644 index fc6cc8d..0000000 --- a/common/brf.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#ifdef ARM9 - -/* None of these functions require a working stack */ -/* Assume R0-R3, R12 are always clobbered */ -#define BRF_INVALIDATE_DCACHE (0xFFFF07F0) -#define BRF_INVALIDATE_DCACHE_RANGE (0xFFFF0868) -#define BRF_WRITEBACK_DCACHE (0xFFFF07FC) -#define BRF_WRITEBACK_DCACHE_RANGE (0xFFFF0884) -#define BRF_WB_INV_DCACHE (0xFFFF0830) -#define BRF_WB_INV_DCACHE_RANGE (0xFFFF08A8) -#define BRF_INVALIDATE_ICACHE (0xFFFF0AB4) -#define BRF_INVALIDATE_ICACHE_RANGE (0xFFFF0AC0) -#define BRF_RESETCP15 (0xFFFF0C58) - -#else - -#endif diff --git a/common/common.h b/common/common.h index 9d02ddf..cf23116 100755 --- a/common/common.h +++ b/common/common.h @@ -58,13 +58,6 @@ #define assert(x) \ (!!(x) ? (void)0 : __builtin_trap()) -static inline void waitClks(unsigned clk) { - clk >>= 1; - while(clk--) { - asm_v("nop":::"memory", "cc"); - } -} - #define STATIC_ASSERT(...) \ _Static_assert((__VA_ARGS__), #__VA_ARGS__)