filename | src/sh4/sh4mem.c |
changeset | 35:21a4be098304 |
prev | 10:c898b37506e0 |
next | 38:9ccc7ac66a9d |
author | nkeynes |
date | Mon Dec 26 03:54:55 2005 +0000 (15 years ago) |
permissions | -rw-r--r-- |
last change | Remove modules.h - move definitions into dream.h Add source string to output list (taken from module name) ARM Work in progress |
view | annotate | diff | log | raw |
1 /**
2 * $Id: sh4mem.c,v 1.2 2005-12-26 03:54:55 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 #define MODULE sh4_module
21 #include <string.h>
22 #include <zlib.h>
23 #include "dream.h"
24 #include "mem.h"
25 #include "mmio.h"
26 #include "sh4mmio.h"
27 #include "dreamcast.h"
29 #define OC_BASE 0x1C000000
30 #define OC_TOP 0x20000000
32 #define TRANSLATE_VIDEO_64BIT_ADDRESS(a) ( (((a)&0x00FFFFF8)>>1)|(((a)&0x00000004)<<20)|((a)&0x03)|0x05000000 );
34 #ifdef ENABLE_WATCH
35 #define CHECK_READ_WATCH( addr, size ) \
36 if( mem_is_watched(addr,size,WATCH_READ) != NULL ) { \
37 WARN( "Watch triggered at %08X by %d byte read", addr, size ); \
38 dreamcast_stop(); \
39 }
40 #define CHECK_WRITE_WATCH( addr, size, val ) \
41 if( mem_is_watched(addr,size,WATCH_WRITE) != NULL ) { \
42 WARN( "Watch triggered at %08X by %d byte write <= %0*X", addr, size, size*2, val ); \
43 dreamcast_stop(); \
44 }
45 #else
46 #define CHECK_READ_WATCH( addr, size )
47 #define CHECK_WRITE_WATCH( addr, size )
48 #endif
50 #define TRACE_IO( str, p, r, ... ) if(io_rgn[(uint32_t)p]->trace_flag) \
51 TRACE( str " [%s.%s: %s]", __VA_ARGS__, \
52 MMIO_NAME_BYNUM((uint32_t)p), MMIO_REGID_BYNUM((uint32_t)p, r), \
53 MMIO_REGDESC_BYNUM((uint32_t)p, r) )
55 extern struct mem_region mem_rgn[];
56 extern struct mmio_region *P4_io[];
58 int32_t sh4_read_p4( uint32_t addr )
59 {
60 struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
61 if( !io ) {
62 ERROR( "Attempted read from unknown P4 region: %08X", addr );
63 return 0;
64 } else {
65 return io->io_read( addr&0xFFF );
66 }
67 }
69 void sh4_write_p4( uint32_t addr, int32_t val )
70 {
71 struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
72 if( !io ) {
73 if( (addr & 0xFC000000) == 0xE0000000 ) {
74 /* Store queue */
75 SH4_WRITE_STORE_QUEUE( addr, val );
76 } else {
77 ERROR( "Attempted write to unknown P4 region: %08X", addr );
78 }
79 } else {
80 io->io_write( addr&0xFFF, val );
81 }
82 }
84 int32_t sh4_read_phys_word( uint32_t addr )
85 {
86 char *page;
87 if( addr > 0xE0000000 ) /* P4 Area, handled specially */
88 return SIGNEXT16(sh4_read_p4( addr ));
90 if( (addr&0x1F800000) == 0x04000000 ) {
91 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
92 }
94 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
95 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
96 if( page == NULL ) {
97 ERROR( "Attempted word read to missing page: %08X",
98 addr );
99 return 0;
100 }
101 return SIGNEXT16(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
102 } else {
103 return SIGNEXT16(*(int16_t *)(page+(addr&0xFFF)));
104 }
105 }
107 int32_t sh4_read_long( uint32_t addr )
108 {
109 char *page;
111 CHECK_READ_WATCH(addr,4);
113 if( addr > 0xE0000000 ) /* P4 Area, handled specially */
114 return sh4_read_p4( addr );
116 if( (addr&0x1F800000) == 0x04000000 ) {
117 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
118 }
120 if( IS_MMU_ENABLED() ) {
121 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
122 sh4_stop();
123 return 0;
124 }
126 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
127 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
128 int32_t val;
129 if( page == NULL ) {
130 ERROR( "Attempted long read to missing page: %08X", addr );
131 return 0;
132 }
133 val = io_rgn[(uint32_t)page]->io_read(addr&0xFFF);
134 TRACE_IO( "Long read %08X <= %08X", page, (addr&0xFFF), val, addr );
135 return val;
136 } else {
137 return *(int32_t *)(page+(addr&0xFFF));
138 }
139 }
141 int32_t sh4_read_word( uint32_t addr )
142 {
143 char *page;
145 CHECK_READ_WATCH(addr,2);
147 if( addr > 0xE0000000 ) /* P4 Area, handled specially */
148 return SIGNEXT16(sh4_read_p4( addr ));
150 if( (addr&0x1F800000) == 0x04000000 ) {
151 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
152 }
154 if( IS_MMU_ENABLED() ) {
155 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
156 sh4_stop();
157 return 0;
158 }
160 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
161 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
162 int32_t val;
163 if( page == NULL ) {
164 ERROR( "Attempted word read to missing page: %08X", addr );
165 return 0;
166 }
167 val = SIGNEXT16(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
168 TRACE_IO( "Word read %04X <= %08X", page, (addr&0xFFF), val&0xFFFF, addr );
169 return val;
170 } else {
171 return SIGNEXT16(*(int16_t *)(page+(addr&0xFFF)));
172 }
173 }
175 int32_t sh4_read_byte( uint32_t addr )
176 {
177 char *page;
179 CHECK_READ_WATCH(addr,1);
181 if( addr > 0xE0000000 ) /* P4 Area, handled specially */
182 return SIGNEXT8(sh4_read_p4( addr ));
183 if( (addr&0x1F800000) == 0x04000000 ) {
184 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
185 }
187 if( IS_MMU_ENABLED() ) {
188 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
189 sh4_stop();
190 return 0;
191 }
193 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
194 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
195 int32_t val;
196 if( page == NULL ) {
197 ERROR( "Attempted byte read to missing page: %08X", addr );
198 return 0;
199 }
200 val = SIGNEXT8(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
201 TRACE_IO( "Byte read %02X <= %08X", page, (addr&0xFFF), val&0xFF, addr );
202 return val;
203 } else {
204 return SIGNEXT8(*(int8_t *)(page+(addr&0xFFF)));
205 }
206 }
208 void sh4_write_long( uint32_t addr, uint32_t val )
209 {
210 char *page;
212 CHECK_WRITE_WATCH(addr,4,val);
214 if( addr > 0xE0000000 ) {
215 sh4_write_p4( addr, val );
216 return;
217 }
218 if( (addr&0x1F800000) == 0x04000000 ) {
219 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
220 }
222 if( IS_MMU_ENABLED() ) {
223 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
224 sh4_stop();
225 return;
226 }
227 if( (addr&0x1FFFFFFF) < 0x200000 ) {
228 ERROR( "Attempted write to read-only memory: %08X => %08X", val, addr);
229 sh4_stop();
230 return;
231 }
232 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
233 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
234 if( page == NULL ) {
235 ERROR( "Long write to missing page: %08X => %08X", val, addr );
236 return;
237 }
238 TRACE_IO( "Long write %08X => %08X", page, (addr&0xFFF), val, addr );
239 io_rgn[(uint32_t)page]->io_write(addr&0xFFF, val);
240 } else {
241 *(uint32_t *)(page+(addr&0xFFF)) = val;
242 }
243 }
245 void sh4_write_word( uint32_t addr, uint32_t val )
246 {
247 char *page;
249 CHECK_WRITE_WATCH(addr,2,val);
251 if( addr > 0xE0000000 ) {
252 sh4_write_p4( addr, (int16_t)val );
253 return;
254 }
255 if( (addr&0x1F800000) == 0x04000000 ) {
256 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
257 }
258 if( IS_MMU_ENABLED() ) {
259 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
260 sh4_stop();
261 return;
262 }
263 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
264 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
265 if( page == NULL ) {
266 ERROR( "Attempted word write to missing page: %08X", addr );
267 return;
268 }
269 TRACE_IO( "Word write %04X => %08X", page, (addr&0xFFF), val&0xFFFF, addr );
270 io_rgn[(uint32_t)page]->io_write(addr&0xFFF, val);
271 } else {
272 *(uint16_t *)(page+(addr&0xFFF)) = val;
273 }
274 }
276 void sh4_write_byte( uint32_t addr, uint32_t val )
277 {
278 char *page;
280 CHECK_WRITE_WATCH(addr,1,val);
282 if( addr > 0xE0000000 ) {
283 sh4_write_p4( addr, (int8_t)val );
284 return;
285 }
286 if( (addr&0x1F800000) == 0x04000000 ) {
287 addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
288 }
290 if( IS_MMU_ENABLED() ) {
291 ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
292 sh4_stop();
293 return;
294 }
295 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
296 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
297 if( page == NULL ) {
298 ERROR( "Attempted byte write to missing page: %08X", addr );
299 return;
300 }
301 TRACE_IO( "Byte write %02X => %08X", page, (addr&0xFFF), val&0xFF, addr );
302 io_rgn[(uint32_t)page]->io_write( (addr&0xFFF), val);
303 } else {
304 *(uint8_t *)(page+(addr&0xFFF)) = val;
305 }
306 }
310 /* FIXME: Handle all the many special cases when the range doesn't fall cleanly
311 * into the same memory black
312 */
313 void mem_copy_from_sh4( char *dest, uint32_t srcaddr, size_t count ) {
314 char *src = mem_get_region(srcaddr);
315 memcpy( dest, src, count );
316 }
318 void mem_copy_to_sh4( uint32_t destaddr, char *src, size_t count ) {
319 char *dest = mem_get_region(destaddr);
320 memcpy( dest, src, count );
321 }
.