filename | src/sh4/sh4mem.c |
changeset | 10:c898b37506e0 |
next | 35:21a4be098304 |
author | nkeynes |
date | Sun Dec 11 05:15:36 2005 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Add CPU disasembly options to mode dropdown Split sh4/mem.c into core mem.c and sh4/mem.c Start adding copyright comments to file headers |
view | annotate | diff | log | raw |
1 /**
2 * $Id: sh4mem.c,v 1.1 2005-12-11 05:15:36 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
5 *
6 * Copyright (c) 2005 Nathan Keynes.
7 *
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.
12 *
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.
17 */
19 #include <string.h>
20 #include <zlib.h>
21 #include "dream.h"
22 #include "mem.h"
23 #include "mmio.h"
24 #include "sh4mmio.h"
25 #include "dreamcast.h"
27 #define OC_BASE 0x1C000000
28 #define OC_TOP 0x20000000
30 #define TRANSLATE_VIDEO_64BIT_ADDRESS(a) ( (((a)&0x00FFFFF8)>>1)|(((a)&0x00000004)<<20)|((a)&0x03)|0x05000000 );
32 #ifdef ENABLE_WATCH
33 #define CHECK_READ_WATCH( addr, size ) \
34 if( mem_is_watched(addr,size,WATCH_READ) != NULL ) { \
35 WARN( "Watch triggered at %08X by %d byte read", addr, size ); \
36 dreamcast_stop(); \
37 }
38 #define CHECK_WRITE_WATCH( addr, size, val ) \
39 if( mem_is_watched(addr,size,WATCH_WRITE) != NULL ) { \
40 WARN( "Watch triggered at %08X by %d byte write <= %0*X", addr, size, size*2, val ); \
41 dreamcast_stop(); \
42 }
43 #else
44 #define CHECK_READ_WATCH( addr, size )
45 #define CHECK_WRITE_WATCH( addr, size )
46 #endif
48 #define TRACE_IO( str, p, r, ... ) if(io_rgn[(uint32_t)p]->trace_flag) \
49 TRACE( str " [%s.%s: %s]", __VA_ARGS__, \
50 MMIO_NAME_BYNUM((uint32_t)p), MMIO_REGID_BYNUM((uint32_t)p, r), \
51 MMIO_REGDESC_BYNUM((uint32_t)p, r) )
53 extern struct mem_region mem_rgn[];
54 extern struct mmio_region *P4_io[];
56 int32_t sh4_read_p4( uint32_t addr )
57 {
58 struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
59 if( !io ) {
60 ERROR( "Attempted read from unknown P4 region: %08X", addr );
61 return 0;
62 } else {
63 return io->io_read( addr&0xFFF );
64 }
65 }
67 void sh4_write_p4( uint32_t addr, int32_t val )
68 {
69 struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
70 if( !io ) {
71 if( (addr & 0xFC000000) == 0xE0000000 ) {
72 /* Store queue */
73 SH4_WRITE_STORE_QUEUE( addr, val );
74 } else {
75 ERROR( "Attempted write to unknown P4 region: %08X", addr );
76 }
77 } else {
78 io->io_write( addr&0xFFF, val );
79 }
80 }
82 int32_t sh4_read_phys_word( uint32_t addr )
83 {
84 char *page;
85 if( addr > 0xE0000000 ) /* P4 Area, handled specially */
86 return SIGNEXT16(sh4_read_p4( addr ));
88 if( (addr&0x1F800000) == 0x04000000 ) {
89 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
90 }
92 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
93 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
94 if( page == NULL ) {
95 ERROR( "Attempted word read to missing page: %08X",
96 addr );
97 return 0;
98 }
99 return SIGNEXT16(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
100 } else {
101 return SIGNEXT16(*(int16_t *)(page+(addr&0xFFF)));
102 }
103 }
105 int32_t sh4_read_long( uint32_t addr )
106 {
107 char *page;
109 CHECK_READ_WATCH(addr,4);
111 if( addr > 0xE0000000 ) /* P4 Area, handled specially */
112 return sh4_read_p4( addr );
114 if( (addr&0x1F800000) == 0x04000000 ) {
115 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
116 }
118 if( IS_MMU_ENABLED() ) {
119 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
120 sh4_stop();
121 return 0;
122 }
124 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
125 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
126 int32_t val;
127 if( page == NULL ) {
128 ERROR( "Attempted long read to missing page: %08X", addr );
129 return 0;
130 }
131 val = io_rgn[(uint32_t)page]->io_read(addr&0xFFF);
132 TRACE_IO( "Long read %08X <= %08X", page, (addr&0xFFF), val, addr );
133 return val;
134 } else {
135 return *(int32_t *)(page+(addr&0xFFF));
136 }
137 }
139 int32_t sh4_read_word( uint32_t addr )
140 {
141 char *page;
143 CHECK_READ_WATCH(addr,2);
145 if( addr > 0xE0000000 ) /* P4 Area, handled specially */
146 return SIGNEXT16(sh4_read_p4( addr ));
148 if( (addr&0x1F800000) == 0x04000000 ) {
149 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
150 }
152 if( IS_MMU_ENABLED() ) {
153 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
154 sh4_stop();
155 return 0;
156 }
158 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
159 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
160 int32_t val;
161 if( page == NULL ) {
162 ERROR( "Attempted word read to missing page: %08X", addr );
163 return 0;
164 }
165 val = SIGNEXT16(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
166 TRACE_IO( "Word read %04X <= %08X", page, (addr&0xFFF), val&0xFFFF, addr );
167 return val;
168 } else {
169 return SIGNEXT16(*(int16_t *)(page+(addr&0xFFF)));
170 }
171 }
173 int32_t sh4_read_byte( uint32_t addr )
174 {
175 char *page;
177 CHECK_READ_WATCH(addr,1);
179 if( addr > 0xE0000000 ) /* P4 Area, handled specially */
180 return SIGNEXT8(sh4_read_p4( addr ));
181 if( (addr&0x1F800000) == 0x04000000 ) {
182 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
183 }
185 if( IS_MMU_ENABLED() ) {
186 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
187 sh4_stop();
188 return 0;
189 }
191 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
192 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
193 int32_t val;
194 if( page == NULL ) {
195 ERROR( "Attempted byte read to missing page: %08X", addr );
196 return 0;
197 }
198 val = SIGNEXT8(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
199 TRACE_IO( "Byte read %02X <= %08X", page, (addr&0xFFF), val&0xFF, addr );
200 return val;
201 } else {
202 return SIGNEXT8(*(int8_t *)(page+(addr&0xFFF)));
203 }
204 }
206 void sh4_write_long( uint32_t addr, uint32_t val )
207 {
208 char *page;
210 CHECK_WRITE_WATCH(addr,4,val);
212 if( addr > 0xE0000000 ) {
213 sh4_write_p4( addr, val );
214 return;
215 }
216 if( (addr&0x1F800000) == 0x04000000 ) {
217 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
218 }
220 if( IS_MMU_ENABLED() ) {
221 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
222 sh4_stop();
223 return;
224 }
225 if( (addr&0x1FFFFFFF) < 0x200000 ) {
226 ERROR( "Attempted write to read-only memory: %08X => %08X", val, addr);
227 sh4_stop();
228 return;
229 }
230 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
231 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
232 if( page == NULL ) {
233 ERROR( "Long write to missing page: %08X => %08X", val, addr );
234 return;
235 }
236 TRACE_IO( "Long write %08X => %08X", page, (addr&0xFFF), val, addr );
237 io_rgn[(uint32_t)page]->io_write(addr&0xFFF, val);
238 } else {
239 *(uint32_t *)(page+(addr&0xFFF)) = val;
240 }
241 }
243 void sh4_write_word( uint32_t addr, uint32_t val )
244 {
245 char *page;
247 CHECK_WRITE_WATCH(addr,2,val);
249 if( addr > 0xE0000000 ) {
250 sh4_write_p4( addr, (int16_t)val );
251 return;
252 }
253 if( (addr&0x1F800000) == 0x04000000 ) {
254 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
255 }
256 if( IS_MMU_ENABLED() ) {
257 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
258 sh4_stop();
259 return;
260 }
261 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
262 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
263 if( page == NULL ) {
264 ERROR( "Attempted word write to missing page: %08X", addr );
265 return;
266 }
267 TRACE_IO( "Word write %04X => %08X", page, (addr&0xFFF), val&0xFFFF, addr );
268 io_rgn[(uint32_t)page]->io_write(addr&0xFFF, val);
269 } else {
270 *(uint16_t *)(page+(addr&0xFFF)) = val;
271 }
272 }
274 void sh4_write_byte( uint32_t addr, uint32_t val )
275 {
276 char *page;
278 CHECK_WRITE_WATCH(addr,1,val);
280 if( addr > 0xE0000000 ) {
281 sh4_write_p4( addr, (int8_t)val );
282 return;
283 }
284 if( (addr&0x1F800000) == 0x04000000 ) {
285 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
286 }
288 if( IS_MMU_ENABLED() ) {
289 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
290 sh4_stop();
291 return;
292 }
293 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
294 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
295 if( page == NULL ) {
296 ERROR( "Attempted byte write to missing page: %08X", addr );
297 return;
298 }
299 TRACE_IO( "Byte write %02X => %08X", page, (addr&0xFFF), val&0xFF, addr );
300 io_rgn[(uint32_t)page]->io_write( (addr&0xFFF), val);
301 } else {
302 *(uint8_t *)(page+(addr&0xFFF)) = val;
303 }
304 }
308 /* FIXME: Handle all the many special cases when the range doesn't fall cleanly
309 * into the same memory black
310 */
311 void mem_copy_from_sh4( char *dest, uint32_t srcaddr, size_t count ) {
312 char *src = mem_get_region(srcaddr);
313 memcpy( dest, src, count );
314 }
316 void mem_copy_to_sh4( uint32_t destaddr, char *src, size_t count ) {
317 char *dest = mem_get_region(destaddr);
318 memcpy( dest, src, count );
319 }
.