filename | src/sh4/sh4mem.c |
changeset | 934:3acd3b3ee6d1 |
prev | 933:880c37bb1909 |
next | 939:6f2302afeb89 |
author | nkeynes |
date | Sat Dec 27 02:59:35 2008 +0000 (15 years ago) |
branch | lxdream-mem |
permissions | -rw-r--r-- |
last change | Replace fpscr_mask/fpscr flags in xlat_cache_block with a single xlat_sh4_mode, which tracks the field of the same name in sh4r - actually a little faster this way. Now depends on SR.MD, FPSCR.PR and FPSCR.SZ (although it doesn't benefit from the SR flag yet). Also fixed the failure to check the flags in the common case (code address returned by previous block) which took away the performance benefits, but oh well. |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 * sh4mem.c is responsible for interfacing between the SH4's internal memory
4 *
5 * Copyright (c) 2005 Nathan Keynes.
6 *
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.
11 *
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.
16 */
18 #define MODULE sh4_module
20 #include <string.h>
21 #include <zlib.h>
22 #include "dream.h"
23 #include "mem.h"
24 #include "mmio.h"
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 )
53 {
54 return *((int32_t *)(dc_main_ram + (addr&0x00FFFFFF)));
55 }
56 static int32_t FASTCALL ext_sdram_read_word( sh4addr_t addr )
57 {
58 return SIGNEXT16(*((int16_t *)(dc_main_ram + (addr&0x00FFFFFF))));
59 }
60 static int32_t FASTCALL ext_sdram_read_byte( sh4addr_t addr )
61 {
62 return SIGNEXT8(*((int16_t *)(dc_main_ram + (addr&0x00FFFFFF))));
63 }
64 static void FASTCALL ext_sdram_write_long( sh4addr_t addr, uint32_t val )
65 {
66 *(uint32_t *)(dc_main_ram + (addr&0x00FFFFFF)) = val;
67 xlat_invalidate_long(addr);
68 }
69 static void FASTCALL ext_sdram_write_word( sh4addr_t addr, uint32_t val )
70 {
71 *(uint16_t *)(dc_main_ram + (addr&0x00FFFFFF)) = (uint16_t)val;
72 xlat_invalidate_word(addr);
73 }
74 static void FASTCALL ext_sdram_write_byte( sh4addr_t addr, uint32_t val )
75 {
76 *(uint8_t *)(dc_main_ram + (addr&0x00FFFFFF)) = (uint8_t)val;
77 xlat_invalidate_word(addr);
78 }
79 static void FASTCALL ext_sdram_read_burst( unsigned char *dest, sh4addr_t addr )
80 {
81 memcpy( dest, dc_main_ram+(addr&0x00FFFFFF), 32 );
82 }
83 static void FASTCALL ext_sdram_write_burst( sh4addr_t addr, unsigned char *src )
84 {
85 memcpy( dc_main_ram+(addr&0x00FFFFFF), src, 32 );
86 }
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 )
98 {
99 sh4r.store_queue[(addr>>2)&0xF] = val;
100 }
101 static int32_t FASTCALL p4_storequeue_read_long( sh4addr_t addr )
102 {
103 return sh4r.store_queue[(addr>>2)&0xF];
104 }
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.
112 /* TLB 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 )
139 {
140 int count = (end - start) >> 12;
141 mem_region_fn_t *ptr = &sh4_address_space[start>>12];
142 while( count-- > 0 ) {
143 *ptr++ = fn;
144 }
145 }
147 static gboolean sh4_ext_page_remapped( sh4addr_t page, mem_region_fn_t fn, void *user_data )
148 {
149 int i;
150 for( i=0; i<= 0xC0000000; i+= 0x20000000 ) {
151 sh4_address_space[(page|i)>>12] = fn;
152 }
153 }
156 void sh4_mem_init()
157 {
158 int i;
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 );
163 }
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 );
194 }
196 /************** Access methods ***************/
197 #ifdef HAVE_FRAME_ADDRESS
198 #define RETURN_VIA(exc) do{ *(((void **)__builtin_frame_address(0))+1) = exc; return; } while(0)
199 #else
200 #define RETURN_VIA(exc) return NULL
201 #endif
204 int32_t FASTCALL sh4_read_long( sh4addr_t addr )
205 {
206 return sh4_address_space[addr>>12]->read_long(addr);
207 }
209 int32_t FASTCALL sh4_read_word( sh4addr_t addr )
210 {
211 return sh4_address_space[addr>>12]->read_word(addr);
212 }
214 int32_t FASTCALL sh4_read_byte( sh4addr_t addr )
215 {
216 return sh4_address_space[addr>>12]->read_byte(addr);
217 }
219 void FASTCALL sh4_write_long( sh4addr_t addr, uint32_t val )
220 {
221 sh4_address_space[addr>>12]->write_long(addr, val);
222 }
224 void FASTCALL sh4_write_word( sh4addr_t addr, uint32_t val )
225 {
226 sh4_address_space[addr>>12]->write_word(addr,val);
227 }
229 void FASTCALL sh4_write_byte( sh4addr_t addr, uint32_t val )
230 {
231 sh4_address_space[addr>>12]->write_byte(addr, val);
232 }
234 /* FIXME: Handle all the many special cases when the range doesn't fall cleanly
235 * into the same memory block
236 */
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 );
240 } else {
241 sh4ptr_t src = mem_get_region(srcaddr);
242 if( src == NULL ) {
243 WARN( "Attempted block read from unknown address %08X", srcaddr );
244 } else {
245 memcpy( dest, src, count );
246 }
247 }
248 }
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 );
253 return;
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 );
258 return;
259 }
260 sh4ptr_t dest = mem_get_region(destaddr);
261 if( dest == NULL )
262 WARN( "Attempted block write to unknown address %08X", destaddr );
263 else {
264 xlat_invalidate_block( destaddr, count );
265 memcpy( dest, src, count );
266 }
267 }
.