2 * $Id: sh4mem.c,v 1.5 2006-01-21 11:38:10 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"
30 #define OC_BASE 0x1C000000
31 #define OC_TOP 0x20000000
33 #define TRANSLATE_VIDEO_64BIT_ADDRESS(a) ( (((a)&0x00FFFFF8)>>1)|(((a)&0x00000004)<<20)|((a)&0x03)|0x05000000 );
36 #define CHECK_READ_WATCH( addr, size ) \
37 if( mem_is_watched(addr,size,WATCH_READ) != NULL ) { \
38 WARN( "Watch triggered at %08X by %d byte read", addr, size ); \
41 #define CHECK_WRITE_WATCH( addr, size, val ) \
42 if( mem_is_watched(addr,size,WATCH_WRITE) != NULL ) { \
43 WARN( "Watch triggered at %08X by %d byte write <= %0*X", addr, size, size*2, val ); \
47 #define CHECK_READ_WATCH( addr, size )
48 #define CHECK_WRITE_WATCH( addr, size )
51 #define TRACE_IO( str, p, r, ... ) if(io_rgn[(uint32_t)p]->trace_flag) \
52 TRACE( str " [%s.%s: %s]", __VA_ARGS__, \
53 MMIO_NAME_BYNUM((uint32_t)p), MMIO_REGID_BYNUM((uint32_t)p, r), \
54 MMIO_REGDESC_BYNUM((uint32_t)p, r) )
56 extern struct mem_region mem_rgn[];
57 extern struct mmio_region *P4_io[];
59 int32_t sh4_read_p4( uint32_t addr )
61 struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
63 ERROR( "Attempted read from unknown P4 region: %08X", addr );
66 return io->io_read( addr&0xFFF );
70 void sh4_write_p4( uint32_t addr, int32_t val )
72 struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
74 if( (addr & 0xFC000000) == 0xE0000000 ) {
76 SH4_WRITE_STORE_QUEUE( addr, val );
77 } else if( (addr & 0xFF000000) != 0xF4000000 ) {
78 /* OC address cache isn't implemented, but don't complain about it.
79 * Complain about anything else though */
80 ERROR( "Attempted write to unknown P4 region: %08X", addr );
83 io->io_write( addr&0xFFF, val );
87 int32_t sh4_read_phys_word( uint32_t addr )
90 if( addr >= 0xE0000000 ) /* P4 Area, handled specially */
91 return SIGNEXT16(sh4_read_p4( addr ));
93 if( (addr&0x1F800000) == 0x04000000 ) {
94 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
97 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
98 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
100 ERROR( "Attempted word read to missing page: %08X",
104 return SIGNEXT16(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
106 return SIGNEXT16(*(int16_t *)(page+(addr&0xFFF)));
110 int32_t sh4_read_long( uint32_t addr )
114 CHECK_READ_WATCH(addr,4);
116 if( addr >= 0xE0000000 ) /* P4 Area, handled specially */
117 return sh4_read_p4( addr );
119 if( (addr&0x1F800000) == 0x04000000 ) {
120 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
123 if( IS_MMU_ENABLED() ) {
124 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
129 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
130 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
133 ERROR( "Attempted long read to missing page: %08X", addr );
136 val = io_rgn[(uint32_t)page]->io_read(addr&0xFFF);
137 TRACE_IO( "Long read %08X <= %08X", page, (addr&0xFFF), val, addr );
140 return *(int32_t *)(page+(addr&0xFFF));
144 int32_t sh4_read_word( uint32_t addr )
148 CHECK_READ_WATCH(addr,2);
150 if( addr >= 0xE0000000 ) /* P4 Area, handled specially */
151 return SIGNEXT16(sh4_read_p4( addr ));
153 if( (addr&0x1F800000) == 0x04000000 ) {
154 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
157 if( IS_MMU_ENABLED() ) {
158 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
163 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
164 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
167 ERROR( "Attempted word read to missing page: %08X", addr );
170 val = SIGNEXT16(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
171 TRACE_IO( "Word read %04X <= %08X", page, (addr&0xFFF), val&0xFFFF, addr );
174 return SIGNEXT16(*(int16_t *)(page+(addr&0xFFF)));
178 int32_t sh4_read_byte( uint32_t addr )
182 CHECK_READ_WATCH(addr,1);
184 if( addr >= 0xE0000000 ) /* P4 Area, handled specially */
185 return SIGNEXT8(sh4_read_p4( addr ));
186 if( (addr&0x1F800000) == 0x04000000 ) {
187 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
190 if( IS_MMU_ENABLED() ) {
191 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
196 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
197 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
200 ERROR( "Attempted byte read to missing page: %08X", addr );
203 val = SIGNEXT8(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
204 TRACE_IO( "Byte read %02X <= %08X", page, (addr&0xFFF), val&0xFF, addr );
207 return SIGNEXT8(*(int8_t *)(page+(addr&0xFFF)));
211 void sh4_write_long( uint32_t addr, uint32_t val )
215 CHECK_WRITE_WATCH(addr,4,val);
217 if( addr >= 0xE0000000 ) {
218 sh4_write_p4( addr, val );
221 if( (addr&0x1F800000) == 0x04000000 ) {
222 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
225 if( IS_MMU_ENABLED() ) {
226 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
230 if( (addr&0x1FFFFFFF) < 0x200000 ) {
231 ERROR( "Attempted write to read-only memory: %08X => %08X", val, addr);
235 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
236 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
238 ERROR( "Long write to missing page: %08X => %08X", val, addr );
241 TRACE_IO( "Long write %08X => %08X", page, (addr&0xFFF), val, addr );
242 io_rgn[(uint32_t)page]->io_write(addr&0xFFF, val);
244 *(uint32_t *)(page+(addr&0xFFF)) = val;
248 void sh4_write_word( uint32_t addr, uint32_t val )
252 CHECK_WRITE_WATCH(addr,2,val);
254 if( addr >= 0xE0000000 ) {
255 sh4_write_p4( addr, (int16_t)val );
258 if( (addr&0x1F800000) == 0x04000000 ) {
259 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
261 if( IS_MMU_ENABLED() ) {
262 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
266 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
267 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
269 ERROR( "Attempted word write to missing page: %08X", addr );
272 TRACE_IO( "Word write %04X => %08X", page, (addr&0xFFF), val&0xFFFF, addr );
273 io_rgn[(uint32_t)page]->io_write(addr&0xFFF, val);
275 *(uint16_t *)(page+(addr&0xFFF)) = val;
279 void sh4_write_byte( uint32_t addr, uint32_t val )
283 CHECK_WRITE_WATCH(addr,1,val);
285 if( addr >= 0xE0000000 ) {
286 sh4_write_p4( addr, (int8_t)val );
289 if( (addr&0x1F800000) == 0x04000000 ) {
290 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
293 if( IS_MMU_ENABLED() ) {
294 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
298 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
299 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
301 ERROR( "Attempted byte write to missing page: %08X", addr );
304 TRACE_IO( "Byte write %02X => %08X", page, (addr&0xFFF), val&0xFF, addr );
305 io_rgn[(uint32_t)page]->io_write( (addr&0xFFF), val);
307 *(uint8_t *)(page+(addr&0xFFF)) = val;
313 /* FIXME: Handle all the many special cases when the range doesn't fall cleanly
314 * into the same memory black
316 void mem_copy_from_sh4( char *dest, uint32_t srcaddr, size_t count ) {
317 char *src = mem_get_region(srcaddr);
318 memcpy( dest, src, count );
321 void mem_copy_to_sh4( uint32_t destaddr, char *src, size_t count ) {
322 char *dest = mem_get_region(destaddr);
323 memcpy( dest, src, count );
.