2 * $Id: sh4mem.c,v 1.16 2006-12-12 09:18:47 nkeynes Exp $
3 * sh4mem.c is responsible for the SH4's access to memory (including memory
4 * mapped I/O), using the page maps created in mem.c
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.
19 #define MODULE sh4_module
28 #include "dreamcast.h"
29 #include "pvr2/pvr2.h"
31 #define OC_BASE 0x1C000000
32 #define OC_TOP 0x20000000
34 #define TRANSLATE_VIDEO_64BIT_ADDRESS(a) ( (((a)&0x00FFFFF8)>>1)|(((a)&0x00000004)<<20)|((a)&0x03)|0x05000000 )
37 #define CHECK_READ_WATCH( addr, size ) \
38 if( mem_is_watched(addr,size,WATCH_READ) != NULL ) { \
39 WARN( "Watch triggered at %08X by %d byte read", addr, size ); \
42 #define CHECK_WRITE_WATCH( addr, size, val ) \
43 if( mem_is_watched(addr,size,WATCH_WRITE) != NULL ) { \
44 WARN( "Watch triggered at %08X by %d byte write <= %0*X", addr, size, size*2, val ); \
48 #define CHECK_READ_WATCH( addr, size )
49 #define CHECK_WRITE_WATCH( addr, size, val )
52 #define TRACE_IO( str, p, r, ... ) if(io_rgn[(uint32_t)p]->trace_flag && !MMIO_NOTRACE_BYNUM((uint32_t)p,r)) \
53 TRACE( str " [%s.%s: %s]", __VA_ARGS__, \
54 MMIO_NAME_BYNUM((uint32_t)p), MMIO_REGID_BYNUM((uint32_t)p, r), \
55 MMIO_REGDESC_BYNUM((uint32_t)p, r) )
56 #define TRACE_P4IO( str, io, r, ... ) if(io->trace_flag && !MMIO_NOTRACE_IOBYNUM(io,r)) \
57 TRACE( str " [%s.%s: %s]", __VA_ARGS__, \
58 io->id, MMIO_REGID_IOBYNUM(io, r), \
59 MMIO_REGDESC_IOBYNUM(io, r) )
61 extern struct mem_region mem_rgn[];
62 extern struct mmio_region *P4_io[];
64 int32_t sh4_read_p4( uint32_t addr )
66 struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
68 ERROR( "Attempted read from unknown P4 region: %08X", addr );
71 int32_t val = io->io_read( addr&0xFFF );
72 TRACE_P4IO( "Long read %08X <= %08X", io, (addr&0xFFF), val, addr );
77 void sh4_write_p4( uint32_t addr, int32_t val )
79 struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
81 if( (addr & 0xFC000000) == 0xE0000000 ) {
83 SH4_WRITE_STORE_QUEUE( addr, val );
84 } else if( (addr & 0xFF000000) != 0xF4000000 ) {
85 /* OC address cache isn't implemented, but don't complain about it.
86 * Complain about anything else though */
87 ERROR( "Attempted write to unknown P4 region: %08X", addr );
90 TRACE_P4IO( "Long write %08X => %08X", io, (addr&0xFFF), val, addr );
91 io->io_write( addr&0xFFF, val );
95 int32_t sh4_read_phys_word( uint32_t addr )
98 if( addr >= 0xE0000000 ) /* P4 Area, handled specially */
99 return SIGNEXT16(sh4_read_p4( addr ));
101 if( (addr&0x1F800000) == 0x04000000 ) {
102 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
105 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
106 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
108 ERROR( "Attempted word read to missing page: %08X",
112 return SIGNEXT16(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
114 return SIGNEXT16(*(int16_t *)(page+(addr&0xFFF)));
118 int32_t sh4_read_long( uint32_t addr )
122 CHECK_READ_WATCH(addr,4);
124 if( addr >= 0xE0000000 ) /* P4 Area, handled specially */
125 return sh4_read_p4( addr );
127 if( (addr&0x1F800000) == 0x04000000 ) {
128 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
129 pvr2_render_invalidate(addr);
130 } else if( (addr&0x1F800000) == 0x05000000 ) {
131 pvr2_render_invalidate(addr);
134 if( IS_MMU_ENABLED() ) {
135 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
140 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
141 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
144 ERROR( "Attempted long read to missing page: %08X", addr );
147 val = io_rgn[(uint32_t)page]->io_read(addr&0xFFF);
148 TRACE_IO( "Long read %08X <= %08X", page, (addr&0xFFF), val, addr );
151 return *(int32_t *)(page+(addr&0xFFF));
155 int32_t sh4_read_word( uint32_t addr )
159 CHECK_READ_WATCH(addr,2);
161 if( addr >= 0xE0000000 ) /* P4 Area, handled specially */
162 return SIGNEXT16(sh4_read_p4( addr ));
164 if( (addr&0x1F800000) == 0x04000000 ) {
165 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
166 pvr2_render_invalidate(addr);
167 } else if( (addr&0x1F800000) == 0x05000000 ) {
168 pvr2_render_invalidate(addr);
172 if( IS_MMU_ENABLED() ) {
173 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
178 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
179 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
182 ERROR( "Attempted word read to missing page: %08X", addr );
185 val = SIGNEXT16(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
186 TRACE_IO( "Word read %04X <= %08X", page, (addr&0xFFF), val&0xFFFF, addr );
189 return SIGNEXT16(*(int16_t *)(page+(addr&0xFFF)));
193 int32_t sh4_read_byte( uint32_t addr )
197 CHECK_READ_WATCH(addr,1);
199 if( addr >= 0xE0000000 ) /* P4 Area, handled specially */
200 return SIGNEXT8(sh4_read_p4( addr ));
201 if( (addr&0x1F800000) == 0x04000000 ) {
202 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
203 pvr2_render_invalidate(addr);
204 } else if( (addr&0x1F800000) == 0x05000000 ) {
205 pvr2_render_invalidate(addr);
209 if( IS_MMU_ENABLED() ) {
210 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
215 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
216 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
219 ERROR( "Attempted byte read to missing page: %08X", addr );
222 val = SIGNEXT8(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
223 TRACE_IO( "Byte read %02X <= %08X", page, (addr&0xFFF), val&0xFF, addr );
226 return SIGNEXT8(*(int8_t *)(page+(addr&0xFFF)));
230 void sh4_write_long( uint32_t addr, uint32_t val )
234 CHECK_WRITE_WATCH(addr,4,val);
236 if( addr >= 0xE0000000 ) {
237 sh4_write_p4( addr, val );
240 if( (addr&0x1F800000) == 0x04000000 ||
241 (addr&0x1F800000) == 0x11000000 ) {
242 texcache_invalidate_page(addr& 0x7FFFFF);
243 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
244 pvr2_render_invalidate(addr);
245 } else if( (addr&0x1F800000) == 0x05000000 ) {
246 pvr2_render_invalidate(addr);
249 if( IS_MMU_ENABLED() ) {
250 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
254 if( (addr&0x1FFFFFFF) < 0x200000 ) {
255 ERROR( "Attempted write to read-only memory: %08X => %08X", val, addr);
259 if( (addr&0x1F800000) == 0x00800000 )
260 asic_g2_write_word();
262 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
263 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
265 if( (addr & 0x1F000000) >= 0x04000000 &&
266 (addr & 0x1F000000) < 0x07000000 )
268 ERROR( "Long write to missing page: %08X => %08X", val, addr );
271 TRACE_IO( "Long write %08X => %08X", page, (addr&0xFFF), val, addr );
272 io_rgn[(uint32_t)page]->io_write(addr&0xFFF, val);
274 *(uint32_t *)(page+(addr&0xFFF)) = val;
278 void sh4_write_word( uint32_t addr, uint32_t val )
282 CHECK_WRITE_WATCH(addr,2,val);
284 if( addr >= 0xE0000000 ) {
285 sh4_write_p4( addr, (int16_t)val );
288 if( (addr&0x1F800000) == 0x04000000 ||
289 (addr&0x1F800000) == 0x11000000 ) {
290 texcache_invalidate_page(addr& 0x7FFFFF);
291 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
292 pvr2_render_invalidate(addr);
293 } else if( (addr&0x1F800000) == 0x05000000 ) {
294 pvr2_render_invalidate(addr);
296 if( IS_MMU_ENABLED() ) {
297 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
301 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
302 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
304 ERROR( "Attempted word write to missing page: %08X", addr );
307 TRACE_IO( "Word write %04X => %08X", page, (addr&0xFFF), val&0xFFFF, addr );
308 io_rgn[(uint32_t)page]->io_write(addr&0xFFF, val);
310 *(uint16_t *)(page+(addr&0xFFF)) = val;
314 void sh4_write_byte( uint32_t addr, uint32_t val )
318 CHECK_WRITE_WATCH(addr,1,val);
320 if( addr >= 0xE0000000 ) {
321 sh4_write_p4( addr, (int8_t)val );
324 if( (addr&0x1F800000) == 0x04000000 ||
325 (addr&0x1F800000) == 0x11000000 ) {
326 texcache_invalidate_page(addr& 0x7FFFFF);
327 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
328 pvr2_render_invalidate(addr);
329 } else if( (addr&0x1F800000) == 0x05000000 ) {
330 pvr2_render_invalidate(addr);
333 if( IS_MMU_ENABLED() ) {
334 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
338 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
339 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
341 ERROR( "Attempted byte write to missing page: %08X", addr );
344 TRACE_IO( "Byte write %02X => %08X", page, (addr&0xFFF), val&0xFF, addr );
345 io_rgn[(uint32_t)page]->io_write( (addr&0xFFF), val);
347 *(uint8_t *)(page+(addr&0xFFF)) = val;
353 /* FIXME: Handle all the many special cases when the range doesn't fall cleanly
354 * into the same memory black
356 void mem_copy_from_sh4( char *dest, uint32_t srcaddr, size_t count ) {
357 if( srcaddr >= 0x04000000 && srcaddr < 0x05000000 ) {
358 pvr2_vram64_read( dest, srcaddr, count );
360 char *src = mem_get_region(srcaddr);
362 ERROR( "Attempted block read from unknown address %08X", srcaddr );
364 memcpy( dest, src, count );
369 void mem_copy_to_sh4( uint32_t destaddr, char *src, size_t count ) {
370 if( destaddr >= 0x10000000 && destaddr < 0x11000000 ) {
371 pvr2_ta_write( src, count );
372 } else if( destaddr >= 0x04000000 && destaddr < 0x05000000 ||
373 destaddr >= 0x11000000 && destaddr < 0x12000000 ) {
374 pvr2_vram64_write( destaddr, src, count );
376 if( (destaddr & 0x1F800000) == 0x05000000 )
377 pvr2_render_invalidate( destaddr );
378 char *dest = mem_get_region(destaddr);
380 ERROR( "Attempted block write to unknown address %08X", destaddr );
382 memcpy( dest, src, count );
.