diff --git a/include/gint/mmu.h b/include/gint/mmu.h index fbb7dab..0412f2d 100644 --- a/include/gint/mmu.h +++ b/include/gint/mmu.h @@ -17,8 +17,9 @@ page-aligned. @virtual Virtual page address + @size If provided, set to the size of the page Returns the page's physical address, or -1 if not mapped. */ -uint32_t mmu_translate(uint32_t page); +uint32_t mmu_translate(uint32_t page, uint32_t *size); /* mmu_uram(): Get pointer to physical start of user RAM @@ -28,6 +29,13 @@ uint32_t mmu_translate(uint32_t page); platform-dependent. */ void *mmu_uram(void); +/* mmu_uram_size(): Get size of user RAM area + + Returns the size of the static memory at 0x08100000, whose address is + returned by mmu_uram(). This is typically 8k on SH3 fx-9860G, 32k on SH4 + fx-9860G, and 512k on fx-CG 50. */ +uint32_t mmu_uram_size(void); + //--- // SH7705 TLB //--- @@ -56,7 +64,7 @@ tlb_data_t const *tlb_data(uint way, uint E); void tlb_mapped_memory(uint32_t *p_rom, uint32_t *p_ram); /* tlb_translate(): Get the physical address for a virtual page */ -uint32_t tlb_translate(uint32_t page); +uint32_t tlb_translate(uint32_t page, uint32_t *size); //--- // SH7305 Unified TLB @@ -84,6 +92,6 @@ utlb_data_t const *utlb_data(uint E); void utlb_mapped_memory(uint32_t *rom, uint32_t *ram); /* utlb_translate(): Get the physical address for a virtual page */ -uint32_t utlb_translate(uint32_t page); +uint32_t utlb_translate(uint32_t page, uint32_t *size); #endif /* GINT_MMU */ diff --git a/src/mmu/mmu.c b/src/mmu/mmu.c index e302003..04a4165 100644 --- a/src/mmu/mmu.c +++ b/src/mmu/mmu.c @@ -11,16 +11,30 @@ //--- /* mmu_translate(): Get the physical address for a virtual page */ -uint32_t mmu_translate(uint32_t page) +uint32_t mmu_translate(uint32_t page, uint32_t *size) { - return isSH3() ? tlb_translate(page) : utlb_translate(page); + return isSH3() ? tlb_translate(page,size) : utlb_translate(page,size); } /* mmu_uram(): Get pointer to physical start of user RAM */ void *mmu_uram(void) { /* Use P1 access */ - return (void *)(mmu_translate(0x08100000) | 0x80000000); + return (void *)(mmu_translate(0x08100000, NULL) | 0x80000000); +} + +/* mmu_uram_size(): Get size of user RAM area */ +uint32_t mmu_uram_size(void) +{ + uint32_t size = 0; + uint32_t pagesize; + + while(mmu_translate(0x08100000 + size, &pagesize) != (uint32_t)-1) + { + size += pagesize; + } + + return size; } //--- @@ -72,7 +86,7 @@ void tlb_mapped_memory(uint32_t *p_rom, uint32_t *p_ram) } /* tlb_translate(): Get the physical address for a virtual page */ -uint32_t tlb_translate(uint32_t page) +uint32_t tlb_translate(uint32_t page, uint32_t *size) { for(int way = 0; way < 4; way++) for(int E = 0; E < 32; E++) @@ -85,7 +99,11 @@ uint32_t tlb_translate(uint32_t page) if(data->SZ) src = (((addr->VPN >> 2) | E) << 12); else src = (addr->VPN | (E << 2)) << 10; - if(src == page) return data->PPN << 10; + if(src == page) + { + if(size) *size = (data->SZ ? 4096 : 1024); + return data->PPN << 10; + } } return -1; } @@ -137,7 +155,7 @@ void utlb_mapped_memory(uint32_t *p_rom, uint32_t *p_ram) } /* utlb_translate(): Get the physical address for a virtual page */ -uint32_t utlb_translate(uint32_t page) +uint32_t utlb_translate(uint32_t page, uint32_t *size) { for(int E = 0; E < 64; E++) { @@ -145,7 +163,14 @@ uint32_t utlb_translate(uint32_t page) const utlb_data_t *data = utlb_data(E); if(!addr->V || !data->V) continue; - if((uint32_t)addr->VPN << 10 == page) return data->PPN << 10; + if((uint32_t)addr->VPN << 10 == page) + { + /* Same magic formula as utlb_mapped_memory() */ + int sz = ((data->SZ1 << 1) | data->SZ2) << 3; + if(size) *size = 1 << ((0x14100c0a >> sz) & 0xff); + + return data->PPN << 10; + } } return -1; }