2 * $Id: mmu.c,v 1.15 2007-11-08 11:54:16 nkeynes Exp $
6 * Copyright (c) 2005 Nathan Keynes.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 #define MODULE sh4_module
21 #include "sh4/sh4mmio.h"
22 #include "sh4/sh4core.h"
25 #define OCRAM_START (0x1C000000>>PAGE_BITS)
26 #define OCRAM_END (0x20000000>>PAGE_BITS)
28 #define ITLB_ENTRY_COUNT 4
29 #define UTLB_ENTRY_COUNT 64
32 #define TLB_VALID 0x00000100
33 #define TLB_USERMODE 0x00000040
34 #define TLB_WRITABLE 0x00000020
35 #define TLB_SIZE_MASK 0x00000090
36 #define TLB_SIZE_1K 0x00000000
37 #define TLB_SIZE_4K 0x00000010
38 #define TLB_SIZE_64K 0x00000080
39 #define TLB_SIZE_1M 0x00000090
40 #define TLB_CACHEABLE 0x00000008
41 #define TLB_DIRTY 0x00000004
42 #define TLB_SHARE 0x00000002
43 #define TLB_WRITETHRU 0x00000001
47 sh4addr_t vpn; // Virtual Page Number
48 uint32_t asid; // Process ID
49 sh4addr_t ppn; // Physical Page Number
54 sh4addr_t vpn; // Virtual Page Number
55 uint32_t asid; // Process ID
56 sh4addr_t ppn; // Physical Page Number
58 uint32_t pcmcia; // extra pcmcia data - not used
61 static struct itlb_entry mmu_itlb[ITLB_ENTRY_COUNT];
62 static struct utlb_entry mmu_utlb[UTLB_ENTRY_COUNT];
63 static uint32_t mmu_urc;
64 static uint32_t mmu_urb;
65 static uint32_t mmu_lrui;
67 static sh4ptr_t cache = NULL;
69 static void mmu_invalidate_tlb();
72 int32_t mmio_region_MMU_read( uint32_t reg )
76 return MMIO_READ( MMU, MMUCR) | (mmu_urc<<10) | (mmu_urb<<18) | (mmu_lrui<<26);
78 return MMIO_READ( MMU, reg );
82 void mmio_region_MMU_write( uint32_t reg, uint32_t val )
95 if( val & MMUCR_TI ) {
98 mmu_urc = (val >> 10) & 0x3F;
99 mmu_urb = (val >> 18) & 0x3F;
100 mmu_lrui = (val >> 26) & 0x3F;
104 mmu_set_cache_mode( val & (CCR_OIX|CCR_ORA) );
109 MMIO_WRITE( MMU, reg, val );
115 cache = mem_alloc_pages(2);
120 mmio_region_MMU_write( CCR, 0 );
123 void MMU_save_state( FILE *f )
125 fwrite( cache, 4096, 2, f );
126 fwrite( &mmu_itlb, sizeof(mmu_itlb), 1, f );
127 fwrite( &mmu_utlb, sizeof(mmu_utlb), 1, f );
130 int MMU_load_state( FILE *f )
132 /* Setup the cache mode according to the saved register value
133 * (mem_load runs before this point to load all MMIO data)
135 mmio_region_MMU_write( CCR, MMIO_READ(MMU, CCR) );
136 if( fread( cache, 4096, 2, f ) != 2 ) {
139 if( fread( &mmu_itlb, sizeof(mmu_itlb), 1, f ) != 1 ) {
142 if( fread( &mmu_utlb, sizeof(mmu_utlb), 1, f ) != 1 ) {
148 void mmu_set_cache_mode( int mode )
152 case MEM_OC_INDEX0: /* OIX=0 */
153 for( i=OCRAM_START; i<OCRAM_END; i++ )
154 page_map[i] = cache + ((i&0x02)<<(PAGE_BITS-1));
156 case MEM_OC_INDEX1: /* OIX=1 */
157 for( i=OCRAM_START; i<OCRAM_END; i++ )
158 page_map[i] = cache + ((i&0x02000000)>>(25-PAGE_BITS));
160 default: /* disabled */
161 for( i=OCRAM_START; i<OCRAM_END; i++ )
167 /* TLB maintanence */
170 * LDTLB instruction implementation. Copies PTEH, PTEL and PTEA into the UTLB
171 * entry identified by MMUCR.URC. Does not modify MMUCR or the ITLB.
175 mmu_utlb[mmu_urc].vpn = MMIO_READ(MMU, PTEH) & 0xFFFFFC00;
176 mmu_utlb[mmu_urc].asid = MMIO_READ(MMU, PTEH) & 0x000000FF;
177 mmu_utlb[mmu_urc].ppn = MMIO_READ(MMU, PTEL) & 0x1FFFFC00;
178 mmu_utlb[mmu_urc].flags = MMIO_READ(MMU, PTEL) & 0x00001FF;
179 mmu_utlb[mmu_urc].pcmcia = MMIO_READ(MMU, PTEA);
182 uint64_t mmu_translate_read( sh4addr_t addr )
184 uint32_t mmucr = MMIO_READ(MMU,MMUCR);
185 if( IS_SH4_PRIVMODE() ) {
186 switch( addr & 0xE0000000 ) {
187 case 0x80000000: case 0xA0000000:
188 /* Non-translated read P1,P2 */
191 /* Non-translated read P4 */
194 if( mmucr&MMUCR_AT ) {
200 if( addr & 0x80000000 ) {
201 if( ((addr&0xFC000000) == 0xE0000000 ) &&
202 ((mmucr&MMUCR_SQMD) == 0) ) {
206 // MMU_READ_ADDR_ERROR();
208 if( mmucr&MMUCR_AT ) {
209 uint32_t vpn = addr & 0xFFFFFC00;
210 uint32_t asid = MMIO_READ(MMU,PTEH)&0xFF;
217 static void mmu_invalidate_tlb()
220 for( i=0; i<ITLB_ENTRY_COUNT; i++ ) {
221 mmu_itlb[i].flags &= (~TLB_VALID);
223 for( i=0; i<UTLB_ENTRY_COUNT; i++ ) {
224 mmu_utlb[i].flags &= (~TLB_VALID);
228 #define ITLB_ENTRY(addr) ((addr>>7)&0x03)
230 int32_t mmu_itlb_addr_read( sh4addr_t addr )
232 struct itlb_entry *ent = &mmu_itlb[ITLB_ENTRY(addr)];
233 return ent->vpn | ent->asid | (ent->flags & TLB_VALID);
235 int32_t mmu_itlb_data_read( sh4addr_t addr )
237 struct itlb_entry *ent = &mmu_itlb[ITLB_ENTRY(addr)];
238 return ent->ppn | ent->flags;
241 void mmu_itlb_addr_write( sh4addr_t addr, uint32_t val )
243 struct itlb_entry *ent = &mmu_itlb[ITLB_ENTRY(addr)];
244 ent->vpn = val & 0xFFFFFC00;
245 ent->asid = val & 0x000000FF;
246 ent->flags = (ent->flags & ~(TLB_VALID)) | (val&TLB_VALID);
249 void mmu_itlb_data_write( sh4addr_t addr, uint32_t val )
251 struct itlb_entry *ent = &mmu_itlb[ITLB_ENTRY(addr)];
252 ent->ppn = val & 0x1FFFFC00;
253 ent->flags = val & 0x00001DA;
256 #define UTLB_ENTRY(addr) ((addr>>8)&0x3F)
257 #define UTLB_ASSOC(addr) (addr&0x80)
258 #define UTLB_DATA2(addr) (addr&0x00800000)
260 int32_t mmu_utlb_addr_read( sh4addr_t addr )
262 struct utlb_entry *ent = &mmu_utlb[UTLB_ENTRY(addr)];
263 return ent->vpn | ent->asid | (ent->flags & TLB_VALID) |
264 ((ent->flags & TLB_DIRTY)<<7);
266 int32_t mmu_utlb_data_read( sh4addr_t addr )
268 struct utlb_entry *ent = &mmu_utlb[UTLB_ENTRY(addr)];
269 if( UTLB_DATA2(addr) ) {
272 return ent->ppn | ent->flags;
276 void mmu_utlb_addr_write( sh4addr_t addr, uint32_t val )
278 if( UTLB_ASSOC(addr) ) {
280 struct utlb_entry *ent = &mmu_utlb[UTLB_ENTRY(addr)];
281 ent->vpn = (val & 0xFFFFFC00);
282 ent->asid = (val & 0xFF);
283 ent->flags = (ent->flags & ~(TLB_DIRTY|TLB_VALID));
284 ent->flags |= (val & TLB_VALID);
285 ent->flags |= ((val & 0x200)>>7);
289 void mmu_utlb_data_write( sh4addr_t addr, uint32_t val )
291 struct utlb_entry *ent = &mmu_utlb[UTLB_ENTRY(addr)];
292 if( UTLB_DATA2(addr) ) {
293 ent->pcmcia = val & 0x0000000F;
295 ent->ppn = (val & 0x1FFFFC00);
296 ent->flags = (val & 0x000001FF);
300 /* Cache access - not implemented */
302 int32_t mmu_icache_addr_read( sh4addr_t addr )
304 return 0; // not implemented
306 int32_t mmu_icache_data_read( sh4addr_t addr )
308 return 0; // not implemented
310 int32_t mmu_ocache_addr_read( sh4addr_t addr )
312 return 0; // not implemented
314 int32_t mmu_ocache_data_read( sh4addr_t addr )
316 return 0; // not implemented
319 void mmu_icache_addr_write( sh4addr_t addr, uint32_t val )
323 void mmu_icache_data_write( sh4addr_t addr, uint32_t val )
327 void mmu_ocache_addr_write( sh4addr_t addr, uint32_t val )
331 void mmu_ocache_data_write( sh4addr_t addr, uint32_t val )
.