3 * sh4mem.c is responsible for interfacing between the SH4's internal memory
5 * Copyright (c) 2005 Nathan Keynes.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
18 #define MODULE sh4_module
25 #include "dreamcast.h"
26 #include "sh4/sh4core.h"
27 #include "sh4/sh4mmio.h"
28 #include "sh4/xltcache.h"
29 #include "pvr2/pvr2.h"
31 /* System regions (probably should be defined elsewhere) */
32 extern struct mem_region_fn mem_region_unmapped;
33 extern struct mem_region_fn mem_region_sdram;
34 extern struct mem_region_fn mem_region_vram32;
35 extern struct mem_region_fn mem_region_vram64;
36 extern struct mem_region_fn mem_region_audioram;
37 extern struct mem_region_fn mem_region_flashram;
38 extern struct mem_region_fn mem_region_bootrom;
40 /* On-chip regions other than defined MMIO regions */
41 extern struct mem_region_fn p4_region_storequeue;
42 extern struct mem_region_fn p4_region_icache_addr;
43 extern struct mem_region_fn p4_region_icache_data;
44 extern struct mem_region_fn p4_region_ocache_addr;
45 extern struct mem_region_fn p4_region_ocache_data;
46 extern struct mem_region_fn p4_region_itlb_addr;
47 extern struct mem_region_fn p4_region_itlb_data;
48 extern struct mem_region_fn p4_region_utlb_addr;
49 extern struct mem_region_fn p4_region_utlb_data;
51 /********************* The main ram address space **********************/
52 static int32_t FASTCALL ext_sdram_read_long( sh4addr_t addr )
54 return *((int32_t *)(dc_main_ram + (addr&0x00FFFFFF)));
56 static int32_t FASTCALL ext_sdram_read_word( sh4addr_t addr )
58 return SIGNEXT16(*((int16_t *)(dc_main_ram + (addr&0x00FFFFFF))));
60 static int32_t FASTCALL ext_sdram_read_byte( sh4addr_t addr )
62 return SIGNEXT8(*((int16_t *)(dc_main_ram + (addr&0x00FFFFFF))));
64 static void FASTCALL ext_sdram_write_long( sh4addr_t addr, uint32_t val )
66 *(uint32_t *)(dc_main_ram + (addr&0x00FFFFFF)) = val;
67 xlat_invalidate_long(addr);
69 static void FASTCALL ext_sdram_write_word( sh4addr_t addr, uint32_t val )
71 *(uint16_t *)(dc_main_ram + (addr&0x00FFFFFF)) = (uint16_t)val;
72 xlat_invalidate_word(addr);
74 static void FASTCALL ext_sdram_write_byte( sh4addr_t addr, uint32_t val )
76 *(uint8_t *)(dc_main_ram + (addr&0x00FFFFFF)) = (uint8_t)val;
77 xlat_invalidate_word(addr);
79 static void FASTCALL ext_sdram_read_burst( unsigned char *dest, sh4addr_t addr )
81 memcpy( dest, dc_main_ram+(addr&0x00FFFFFF), 32 );
83 static void FASTCALL ext_sdram_write_burst( sh4addr_t addr, unsigned char *src )
85 memcpy( dc_main_ram+(addr&0x00FFFFFF), src, 32 );
88 struct mem_region_fn mem_region_sdram = { ext_sdram_read_long, ext_sdram_write_long,
89 ext_sdram_read_word, ext_sdram_write_word,
90 ext_sdram_read_byte, ext_sdram_write_byte,
91 ext_sdram_read_burst, ext_sdram_write_burst };
94 /***************************** P4 Regions ************************************/
96 /* Store-queue (long-write only?) */
97 static void FASTCALL p4_storequeue_write_long( sh4addr_t addr, uint32_t val )
99 sh4r.store_queue[(addr>>2)&0xF] = val;
101 static int32_t FASTCALL p4_storequeue_read_long( sh4addr_t addr )
103 return sh4r.store_queue[(addr>>2)&0xF];
106 struct mem_region_fn p4_region_storequeue = {
107 p4_storequeue_read_long, p4_storequeue_write_long,
108 p4_storequeue_read_long, p4_storequeue_write_long,
109 p4_storequeue_read_long, p4_storequeue_write_long,
110 unmapped_read_burst, unmapped_write_burst }; // No burst access.
113 struct mem_region_fn p4_region_itlb_addr = {
114 mmu_itlb_addr_read, mmu_itlb_addr_write,
115 mmu_itlb_addr_read, mmu_itlb_addr_write,
116 mmu_itlb_addr_read, mmu_itlb_addr_write,
117 unmapped_read_burst, unmapped_write_burst };
118 struct mem_region_fn p4_region_itlb_data = {
119 mmu_itlb_data_read, mmu_itlb_data_write,
120 mmu_itlb_data_read, mmu_itlb_data_write,
121 mmu_itlb_data_read, mmu_itlb_data_write,
122 unmapped_read_burst, unmapped_write_burst };
123 struct mem_region_fn p4_region_utlb_addr = {
124 mmu_utlb_addr_read, mmu_utlb_addr_write,
125 mmu_utlb_addr_read, mmu_utlb_addr_write,
126 mmu_utlb_addr_read, mmu_utlb_addr_write,
127 unmapped_read_burst, unmapped_write_burst };
128 struct mem_region_fn p4_region_utlb_data = {
129 mmu_utlb_data_read, mmu_utlb_data_write,
130 mmu_utlb_data_read, mmu_utlb_data_write,
131 mmu_utlb_data_read, mmu_utlb_data_write,
132 unmapped_read_burst, unmapped_write_burst };
134 /********************** Initialization *************************/
136 mem_region_fn_t *sh4_address_space;
138 static void sh4_register_mem_region( uint32_t start, uint32_t end, mem_region_fn_t fn )
140 int count = (end - start) >> 12;
141 mem_region_fn_t *ptr = &sh4_address_space[start>>12];
142 while( count-- > 0 ) {
147 static gboolean sh4_ext_page_remapped( sh4addr_t page, mem_region_fn_t fn, void *user_data )
150 for( i=0; i<= 0xC0000000; i+= 0x20000000 ) {
151 sh4_address_space[(page|i)>>12] = fn;
159 mem_region_fn_t *ptr;
160 sh4_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 256 );
161 for( i=0, ptr = sh4_address_space; i<7; i++, ptr += LXDREAM_PAGE_TABLE_ENTRIES ) {
162 memcpy( ptr, ext_address_space, sizeof(mem_region_fn_t) * LXDREAM_PAGE_TABLE_ENTRIES );
165 /* Setup main P4 regions */
166 sh4_register_mem_region( 0xE0000000, 0xE4000000, &p4_region_storequeue );
167 sh4_register_mem_region( 0xE4000000, 0xF0000000, &mem_region_unmapped );
168 sh4_register_mem_region( 0xF0000000, 0xF1000000, &p4_region_icache_addr );
169 sh4_register_mem_region( 0xF1000000, 0xF2000000, &p4_region_icache_data );
170 sh4_register_mem_region( 0xF2000000, 0xF3000000, &p4_region_itlb_addr );
171 sh4_register_mem_region( 0xF3000000, 0xF4000000, &p4_region_itlb_data );
172 sh4_register_mem_region( 0xF4000000, 0xF5000000, &p4_region_ocache_addr );
173 sh4_register_mem_region( 0xF5000000, 0xF6000000, &p4_region_ocache_data );
174 sh4_register_mem_region( 0xF6000000, 0xF7000000, &p4_region_utlb_addr );
175 sh4_register_mem_region( 0xF7000000, 0xF8000000, &p4_region_utlb_data );
176 sh4_register_mem_region( 0xF8000000, 0x00000000, &mem_region_unmapped );
178 /* Setup P4 control region */
179 sh4_register_mem_region( 0xFF000000, 0xFF001000, &mmio_region_MMU.fn );
180 sh4_register_mem_region( 0xFF100000, 0xFF101000, &mmio_region_PMM.fn );
181 sh4_register_mem_region( 0xFF200000, 0xFF201000, &mmio_region_UBC.fn );
182 sh4_register_mem_region( 0xFF800000, 0xFF801000, &mmio_region_BSC.fn );
183 sh4_register_mem_region( 0xFF900000, 0xFFA00000, &mem_region_unmapped ); // SDMR2 + SDMR3
184 sh4_register_mem_region( 0xFFA00000, 0xFFA01000, &mmio_region_DMAC.fn );
185 sh4_register_mem_region( 0xFFC00000, 0xFFC01000, &mmio_region_CPG.fn );
186 sh4_register_mem_region( 0xFFC80000, 0xFFC81000, &mmio_region_RTC.fn );
187 sh4_register_mem_region( 0xFFD00000, 0xFFD01000, &mmio_region_INTC.fn );
188 sh4_register_mem_region( 0xFFD80000, 0xFFD81000, &mmio_region_TMU.fn );
189 sh4_register_mem_region( 0xFFE00000, 0xFFE01000, &mmio_region_SCI.fn );
190 sh4_register_mem_region( 0xFFE80000, 0xFFE81000, &mmio_region_SCIF.fn );
191 sh4_register_mem_region( 0xFFF00000, 0xFFF01000, &mem_region_unmapped ); // H-UDI
193 register_mem_page_remapped_hook( sh4_ext_page_remapped, NULL );
196 /************** Access methods ***************/
197 #ifdef HAVE_FRAME_ADDRESS
198 #define RETURN_VIA(exc) do{ *(((void **)__builtin_frame_address(0))+1) = exc; return; } while(0)
200 #define RETURN_VIA(exc) return NULL
204 int32_t FASTCALL sh4_read_long( sh4addr_t addr )
206 return sh4_address_space[addr>>12]->read_long(addr);
209 int32_t FASTCALL sh4_read_word( sh4addr_t addr )
211 return sh4_address_space[addr>>12]->read_word(addr);
214 int32_t FASTCALL sh4_read_byte( sh4addr_t addr )
216 return sh4_address_space[addr>>12]->read_byte(addr);
219 void FASTCALL sh4_write_long( sh4addr_t addr, uint32_t val )
221 sh4_address_space[addr>>12]->write_long(addr, val);
224 void FASTCALL sh4_write_word( sh4addr_t addr, uint32_t val )
226 sh4_address_space[addr>>12]->write_word(addr,val);
229 void FASTCALL sh4_write_byte( sh4addr_t addr, uint32_t val )
231 sh4_address_space[addr>>12]->write_byte(addr, val);
234 /* FIXME: Handle all the many special cases when the range doesn't fall cleanly
235 * into the same memory block
237 void mem_copy_from_sh4( sh4ptr_t dest, sh4addr_t srcaddr, size_t count ) {
238 if( srcaddr >= 0x04000000 && srcaddr < 0x05000000 ) {
239 pvr2_vram64_read( dest, srcaddr, count );
241 sh4ptr_t src = mem_get_region(srcaddr);
243 WARN( "Attempted block read from unknown address %08X", srcaddr );
245 memcpy( dest, src, count );
250 void mem_copy_to_sh4( sh4addr_t destaddr, sh4ptr_t src, size_t count ) {
251 if( destaddr >= 0x10000000 && destaddr < 0x14000000 ) {
252 pvr2_dma_write( destaddr, src, count );
254 } else if( (destaddr & 0x1F800000) == 0x05000000 ) {
255 pvr2_render_buffer_invalidate( destaddr, TRUE );
256 } else if( (destaddr & 0x1F800000) == 0x04000000 ) {
257 pvr2_vram64_write( destaddr, src, count );
260 sh4ptr_t dest = mem_get_region(destaddr);
262 WARN( "Attempted block write to unknown address %08X", destaddr );
264 xlat_invalidate_block( destaddr, count );
265 memcpy( dest, src, count );
.