Search
lxdream.org :: lxdream/src/sh4/sh4mem.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4mem.c
changeset 929:fd8cb0c82f5f
prev927:17b6b9e245d8
next930:07e5b11419db
author nkeynes
date Sat Dec 20 03:01:40 2008 +0000 (12 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change First pass experiment using cached decoding.
file annotate diff log raw
1.1 --- a/src/sh4/sh4mem.c Mon Dec 15 10:44:56 2008 +0000
1.2 +++ b/src/sh4/sh4mem.c Sat Dec 20 03:01:40 2008 +0000
1.3 @@ -1,7 +1,6 @@
1.4 /**
1.5 * $Id$
1.6 - * sh4mem.c is responsible for the SH4's access to memory (including memory
1.7 - * mapped I/O), using the page maps created in mem.c
1.8 + * sh4mem.c is responsible for interfacing between the SH4's internal memory
1.9 *
1.10 * Copyright (c) 2005 Nathan Keynes.
1.11 *
1.12 @@ -28,375 +27,354 @@
1.13 #include "sh4/sh4mmio.h"
1.14 #include "sh4/xltcache.h"
1.15 #include "pvr2/pvr2.h"
1.16 -#include "asic.h"
1.17
1.18 -#define OC_BASE 0x1C000000
1.19 -#define OC_TOP 0x20000000
1.20 +/* System regions (probably should be defined elsewhere) */
1.21 +extern struct mem_region_fn mem_region_unmapped;
1.22 +extern struct mem_region_fn mem_region_sdram;
1.23 +extern struct mem_region_fn mem_region_vram32;
1.24 +extern struct mem_region_fn mem_region_vram64;
1.25 +extern struct mem_region_fn mem_region_audioram;
1.26 +extern struct mem_region_fn mem_region_flashram;
1.27 +extern struct mem_region_fn mem_region_bootrom;
1.28
1.29 -#define TRANSLATE_VIDEO_64BIT_ADDRESS(a) ( (((a)&0x00FFFFF8)>>1)|(((a)&0x00000004)<<20)|((a)&0x03)|0x05000000 )
1.30 +/* On-chip regions other than defined MMIO regions */
1.31 +extern struct mem_region_fn mem_region_storequeue;
1.32 +extern struct mem_region_fn mem_region_icache_addr;
1.33 +extern struct mem_region_fn mem_region_icache_data;
1.34 +extern struct mem_region_fn mem_region_ocache_addr;
1.35 +extern struct mem_region_fn mem_region_ocache_data;
1.36 +extern struct mem_region_fn mem_region_itlb_addr;
1.37 +extern struct mem_region_fn mem_region_itlb_data;
1.38 +extern struct mem_region_fn mem_region_utlb_addr;
1.39 +extern struct mem_region_fn mem_region_utlb_data;
1.40
1.41 -#ifdef ENABLE_WATCH
1.42 -#define CHECK_READ_WATCH( addr, size ) \
1.43 - if( mem_is_watched(addr,size,WATCH_READ) != NULL ) { \
1.44 - WARN( "Watch triggered at %08X by %d byte read", addr, size ); \
1.45 - sh4_core_exit(CORE_EXIT_HALT); \
1.46 - }
1.47 -#define CHECK_WRITE_WATCH( addr, size, val ) \
1.48 - if( mem_is_watched(addr,size,WATCH_WRITE) != NULL ) { \
1.49 - WARN( "Watch triggered at %08X by %d byte write <= %0*X", addr, size, size*2, val ); \
1.50 - sh4_core_exit(CORE_EXIT_HALT); \
1.51 - }
1.52 +extern struct mmio_region *P4_io[];
1.53 +
1.54 +/********************* The "unmapped" address space ********************/
1.55 +/* Always reads as 0, writes have no effect */
1.56 +static int32_t FASTCALL unmapped_read_long( sh4addr_t addr )
1.57 +{
1.58 + return 0;
1.59 +}
1.60 +static void FASTCALL unmapped_write_long( sh4addr_t addr, uint32_t val )
1.61 +{
1.62 +}
1.63 +static void FASTCALL unmapped_read_burst( unsigned char *dest, sh4addr_t addr )
1.64 +{
1.65 + memset( dest, 0, 32 );
1.66 +}
1.67 +static void FASTCALL unmapped_write_burst( sh4addr_t addr, unsigned char *src )
1.68 +{
1.69 +}
1.70 +
1.71 +struct mem_region_fn mem_region_unmapped = {
1.72 + unmapped_read_long, unmapped_write_long,
1.73 + unmapped_read_long, unmapped_write_long,
1.74 + unmapped_read_long, unmapped_write_long,
1.75 + unmapped_read_burst, unmapped_write_burst };
1.76 +
1.77 +/********************* Store-queue (long-write only?) ******************/
1.78 +static void FASTCALL p4_storequeue_write_long( sh4addr_t addr, uint32_t val )
1.79 +{
1.80 + sh4r.store_queue[(addr>>2)&0xF] = val;
1.81 +}
1.82 +static int32_t FASTCALL p4_storequeue_read_long( sh4addr_t addr )
1.83 +{
1.84 + return sh4r.store_queue[(addr>>2)&0xF];
1.85 +}
1.86 +struct mem_region_fn p4_region_storequeue = {
1.87 + p4_storequeue_read_long, p4_storequeue_write_long,
1.88 + p4_storequeue_read_long, p4_storequeue_write_long,
1.89 + p4_storequeue_read_long, p4_storequeue_write_long,
1.90 + unmapped_read_burst, unmapped_write_burst }; // No burst access.
1.91 +
1.92 +/********************* The main ram address space **********************/
1.93 +static int32_t FASTCALL ext_sdram_read_long( sh4addr_t addr )
1.94 +{
1.95 + return *((int32_t *)(sh4_main_ram + (addr&0x00FFFFFF)));
1.96 +}
1.97 +static int32_t FASTCALL ext_sdram_read_word( sh4addr_t addr )
1.98 +{
1.99 + return SIGNEXT16(*((int16_t *)(sh4_main_ram + (addr&0x00FFFFFF))));
1.100 +}
1.101 +static int32_t FASTCALL ext_sdram_read_byte( sh4addr_t addr )
1.102 +{
1.103 + return SIGNEXT8(*((int16_t *)(sh4_main_ram + (addr&0x00FFFFFF))));
1.104 +}
1.105 +static void FASTCALL ext_sdram_write_long( sh4addr_t addr, uint32_t val )
1.106 +{
1.107 + *(uint32_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = val;
1.108 + xlat_invalidate_long(addr);
1.109 +}
1.110 +static void FASTCALL ext_sdram_write_word( sh4addr_t addr, uint32_t val )
1.111 +{
1.112 + *(uint16_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = (uint16_t)val;
1.113 + xlat_invalidate_word(addr);
1.114 +}
1.115 +static void FASTCALL ext_sdram_write_byte( sh4addr_t addr, uint32_t val )
1.116 +{
1.117 + *(uint8_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = (uint8_t)val;
1.118 + xlat_invalidate_word(addr);
1.119 +}
1.120 +static void FASTCALL ext_sdram_read_burst( unsigned char *dest, sh4addr_t addr )
1.121 +{
1.122 + memcpy( dest, sh4_main_ram+(addr&0x00FFFFFF), 32 );
1.123 +}
1.124 +static void FASTCALL ext_sdram_write_burst( sh4addr_t addr, unsigned char *src )
1.125 +{
1.126 + memcpy( sh4_main_ram+(addr&0x00FFFFFF), src, 32 );
1.127 +}
1.128 +
1.129 +struct mem_region_fn mem_region_sdram = { ext_sdram_read_long, ext_sdram_write_long,
1.130 + ext_sdram_read_word, ext_sdram_write_word,
1.131 + ext_sdram_read_byte, ext_sdram_write_byte,
1.132 + ext_sdram_read_burst, ext_sdram_write_burst };
1.133 +
1.134 +
1.135 +/********************* The Boot ROM address space **********************/
1.136 +extern sh4ptr_t dc_boot_rom;
1.137 +extern sh4ptr_t dc_flash_ram;
1.138 +extern sh4ptr_t dc_audio_ram;
1.139 +static int32_t FASTCALL ext_bootrom_read_long( sh4addr_t addr )
1.140 +{
1.141 + return *((int32_t *)(dc_boot_rom + (addr&0x001FFFFF)));
1.142 +}
1.143 +static int32_t FASTCALL ext_bootrom_read_word( sh4addr_t addr )
1.144 +{
1.145 + return SIGNEXT16(*((int16_t *)(dc_boot_rom + (addr&0x001FFFFF))));
1.146 +}
1.147 +static int32_t FASTCALL ext_bootrom_read_byte( sh4addr_t addr )
1.148 +{
1.149 + return SIGNEXT8(*((int16_t *)(dc_boot_rom + (addr&0x001FFFFF))));
1.150 +}
1.151 +static void FASTCALL ext_bootrom_read_burst( unsigned char *dest, sh4addr_t addr )
1.152 +{
1.153 + memcpy( dest, sh4_main_ram+(addr&0x001FFFFF), 32 );
1.154 +}
1.155 +
1.156 +struct mem_region_fn mem_region_bootrom = {
1.157 + ext_bootrom_read_long, unmapped_write_long,
1.158 + ext_bootrom_read_word, unmapped_write_long,
1.159 + ext_bootrom_read_byte, unmapped_write_long,
1.160 + ext_bootrom_read_burst, unmapped_write_burst };
1.161 +
1.162 +/********************* The Audio RAM address space **********************/
1.163 +static int32_t FASTCALL ext_audioram_read_long( sh4addr_t addr )
1.164 +{
1.165 + return *((int32_t *)(dc_audio_ram + (addr&0x001FFFFF)));
1.166 +}
1.167 +static int32_t FASTCALL ext_audioram_read_word( sh4addr_t addr )
1.168 +{
1.169 + return SIGNEXT16(*((int16_t *)(dc_audio_ram + (addr&0x001FFFFF))));
1.170 +}
1.171 +static int32_t FASTCALL ext_audioram_read_byte( sh4addr_t addr )
1.172 +{
1.173 + return SIGNEXT8(*((int16_t *)(dc_audio_ram + (addr&0x001FFFFF))));
1.174 +}
1.175 +static void FASTCALL ext_audioram_write_long( sh4addr_t addr, uint32_t val )
1.176 +{
1.177 + *(uint32_t *)(dc_audio_ram + (addr&0x001FFFFF)) = val;
1.178 + asic_g2_write_word();
1.179 +}
1.180 +static void FASTCALL ext_audioram_write_word( sh4addr_t addr, uint32_t val )
1.181 +{
1.182 + *(uint16_t *)(dc_audio_ram + (addr&0x001FFFFF)) = (uint16_t)val;
1.183 + asic_g2_write_word();
1.184 +}
1.185 +static void FASTCALL ext_audioram_write_byte( sh4addr_t addr, uint32_t val )
1.186 +{
1.187 + *(uint8_t *)(dc_audio_ram + (addr&0x001FFFFF)) = (uint8_t)val;
1.188 + asic_g2_write_word();
1.189 +}
1.190 +static void FASTCALL ext_audioram_read_burst( unsigned char *dest, sh4addr_t addr )
1.191 +{
1.192 + memcpy( dest, dc_audio_ram+(addr&0x001FFFFF), 32 );
1.193 +}
1.194 +static void FASTCALL ext_audioram_write_burst( sh4addr_t addr, unsigned char *src )
1.195 +{
1.196 + memcpy( dc_audio_ram+(addr&0x001FFFFF), src, 32 );
1.197 +}
1.198 +
1.199 +struct mem_region_fn mem_region_audioram = { ext_audioram_read_long, ext_audioram_write_long,
1.200 + ext_audioram_read_word, ext_audioram_write_word,
1.201 + ext_audioram_read_byte, ext_audioram_write_byte,
1.202 + ext_audioram_read_burst, ext_audioram_write_burst };
1.203 +
1.204 +/********************* The Flash RAM address space **********************/
1.205 +static int32_t FASTCALL ext_flashram_read_long( sh4addr_t addr )
1.206 +{
1.207 + return *((int32_t *)(dc_flash_ram + (addr&0x0001FFFF)));
1.208 +}
1.209 +static int32_t FASTCALL ext_flashram_read_word( sh4addr_t addr )
1.210 +{
1.211 + return SIGNEXT16(*((int16_t *)(dc_flash_ram + (addr&0x0001FFFF))));
1.212 +}
1.213 +static int32_t FASTCALL ext_flashram_read_byte( sh4addr_t addr )
1.214 +{
1.215 + return SIGNEXT8(*((int16_t *)(dc_flash_ram + (addr&0x0001FFFF))));
1.216 +}
1.217 +static void FASTCALL ext_flashram_write_long( sh4addr_t addr, uint32_t val )
1.218 +{
1.219 + *(uint32_t *)(dc_flash_ram + (addr&0x0001FFFF)) = val;
1.220 + asic_g2_write_word();
1.221 +}
1.222 +static void FASTCALL ext_flashram_write_word( sh4addr_t addr, uint32_t val )
1.223 +{
1.224 + *(uint16_t *)(dc_flash_ram + (addr&0x0001FFFF)) = (uint16_t)val;
1.225 + asic_g2_write_word();
1.226 +}
1.227 +static void FASTCALL ext_flashram_write_byte( sh4addr_t addr, uint32_t val )
1.228 +{
1.229 + *(uint8_t *)(dc_flash_ram + (addr&0x0001FFFF)) = (uint8_t)val;
1.230 + asic_g2_write_word();
1.231 +}
1.232 +static void FASTCALL ext_flashram_read_burst( unsigned char *dest, sh4addr_t addr )
1.233 +{
1.234 + memcpy( dest, dc_flash_ram+(addr&0x0001FFFF), 32 );
1.235 +}
1.236 +static void FASTCALL ext_flashram_write_burst( sh4addr_t addr, unsigned char *src )
1.237 +{
1.238 + memcpy( dc_flash_ram+(addr&0x0001FFFF), src, 32 );
1.239 +}
1.240 +
1.241 +struct mem_region_fn mem_region_flashram = { ext_flashram_read_long, ext_flashram_write_long,
1.242 + ext_flashram_read_word, ext_flashram_write_word,
1.243 + ext_flashram_read_byte, ext_flashram_write_byte,
1.244 + ext_flashram_read_burst, ext_flashram_write_burst };
1.245 +
1.246 +/**************************************************************************/
1.247 +
1.248 +struct mem_region_fn p4_region_icache_addr = {
1.249 + mmu_icache_addr_read, mmu_icache_addr_write,
1.250 + mmu_icache_addr_read, mmu_icache_addr_write,
1.251 + mmu_icache_addr_read, mmu_icache_addr_write,
1.252 + unmapped_read_burst, unmapped_write_burst };
1.253 +struct mem_region_fn p4_region_icache_data = {
1.254 + mmu_icache_data_read, mmu_icache_data_write,
1.255 + mmu_icache_data_read, mmu_icache_data_write,
1.256 + mmu_icache_data_read, mmu_icache_data_write,
1.257 + unmapped_read_burst, unmapped_write_burst };
1.258 +struct mem_region_fn p4_region_ocache_addr = {
1.259 + mmu_ocache_addr_read, mmu_ocache_addr_write,
1.260 + mmu_ocache_addr_read, mmu_ocache_addr_write,
1.261 + mmu_ocache_addr_read, mmu_ocache_addr_write,
1.262 + unmapped_read_burst, unmapped_write_burst };
1.263 +struct mem_region_fn p4_region_ocache_data = {
1.264 + mmu_ocache_data_read, mmu_ocache_data_write,
1.265 + mmu_ocache_data_read, mmu_ocache_data_write,
1.266 + mmu_ocache_data_read, mmu_ocache_data_write,
1.267 + unmapped_read_burst, unmapped_write_burst };
1.268 +struct mem_region_fn p4_region_itlb_addr = {
1.269 + mmu_itlb_addr_read, mmu_itlb_addr_write,
1.270 + mmu_itlb_addr_read, mmu_itlb_addr_write,
1.271 + mmu_itlb_addr_read, mmu_itlb_addr_write,
1.272 + unmapped_read_burst, unmapped_write_burst };
1.273 +struct mem_region_fn p4_region_itlb_data = {
1.274 + mmu_itlb_data_read, mmu_itlb_data_write,
1.275 + mmu_itlb_data_read, mmu_itlb_data_write,
1.276 + mmu_itlb_data_read, mmu_itlb_data_write,
1.277 + unmapped_read_burst, unmapped_write_burst };
1.278 +struct mem_region_fn p4_region_utlb_addr = {
1.279 + mmu_utlb_addr_read, mmu_utlb_addr_write,
1.280 + mmu_utlb_addr_read, mmu_utlb_addr_write,
1.281 + mmu_utlb_addr_read, mmu_utlb_addr_write,
1.282 + unmapped_read_burst, unmapped_write_burst };
1.283 +struct mem_region_fn p4_region_utlb_data = {
1.284 + mmu_utlb_data_read, mmu_utlb_data_write,
1.285 + mmu_utlb_data_read, mmu_utlb_data_write,
1.286 + mmu_utlb_data_read, mmu_utlb_data_write,
1.287 + unmapped_read_burst, unmapped_write_burst };
1.288 +
1.289 +#ifdef HAVE_FRAME_ADDRESS
1.290 +#define RETURN_VIA(exc) do{ *(((void **)__builtin_frame_address(0))+1) = exc; return; } while(0)
1.291 #else
1.292 -#define CHECK_READ_WATCH( addr, size )
1.293 -#define CHECK_WRITE_WATCH( addr, size, val )
1.294 +#define RETURN_VIA(exc) return NULL
1.295 #endif
1.296
1.297 -#ifdef ENABLE_TRACE_IO
1.298 -#define TRACE_IO( str, p, r, ... ) if(io_rgn[(uint32_t)p]->trace_flag && !MMIO_NOTRACE_BYNUM((uint32_t)p,r)) \
1.299 - TRACE( str " [%s.%s: %s]", __VA_ARGS__, \
1.300 - MMIO_NAME_BYNUM((uint32_t)p), MMIO_REGID_BYNUM((uint32_t)p, r), \
1.301 - MMIO_REGDESC_BYNUM((uint32_t)p, r) )
1.302 -#define TRACE_P4IO( str, io, r, ... ) if(io->trace_flag && !MMIO_NOTRACE_IOBYNUM(io,r)) \
1.303 - TRACE( str " [%s.%s: %s]", __VA_ARGS__, \
1.304 - io->id, MMIO_REGID_IOBYNUM(io, r), \
1.305 - MMIO_REGDESC_IOBYNUM(io, r) )
1.306 -#else
1.307 -#define TRACE_IO( str, p, r, ... )
1.308 -#define TRACE_P4IO( str, io, r, ... )
1.309 -#endif
1.310 -
1.311 -extern struct mem_region mem_rgn[];
1.312 -extern struct mmio_region *P4_io[];
1.313 -
1.314 -int32_t FASTCALL sh4_read_p4( sh4addr_t addr )
1.315 +int decode_sdram = 0;
1.316 +mem_region_fn_t FASTCALL mem_decode_address( sh4addr_t addr )
1.317 {
1.318 - struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
1.319 - if( !io ) {
1.320 - switch( addr & 0x1F000000 ) {
1.321 - case 0x00000000: case 0x01000000: case 0x02000000: case 0x03000000:
1.322 - /* Store queue - readable? */
1.323 - return 0;
1.324 - break;
1.325 - case 0x10000000: return mmu_icache_addr_read( addr );
1.326 - case 0x11000000: return mmu_icache_data_read( addr );
1.327 - case 0x12000000: return mmu_itlb_addr_read( addr );
1.328 - case 0x13000000: return mmu_itlb_data_read( addr );
1.329 - case 0x14000000: return mmu_ocache_addr_read( addr );
1.330 - case 0x15000000: return mmu_ocache_data_read( addr );
1.331 - case 0x16000000: return mmu_utlb_addr_read( addr );
1.332 - case 0x17000000: return mmu_utlb_data_read( addr );
1.333 - default:
1.334 - WARN( "Attempted read from unknown or invalid P4 region: %08X", addr );
1.335 - return 0;
1.336 + sh4ptr_t page;
1.337 + switch( addr >> 26 ) { /* Area */
1.338 + case 0: /* Holly multiplexed */
1.339 + page = page_map[(addr&0x1FFFFFFF)>>12];
1.340 + if( ((uintptr_t)page) < MAX_IO_REGIONS ) {
1.341 + return &io_rgn[(uintptr_t)page]->fn;
1.342 + } else if( addr < 0x00200000 ) {
1.343 + return &mem_region_bootrom;
1.344 + } else if( addr < 0x00400000 ) {
1.345 + return &mem_region_flashram;
1.346 + } else if( addr >= 0x00800000 && addr < 0x00A00000 ) {
1.347 + return &mem_region_audioram;
1.348 }
1.349 - } else {
1.350 - int32_t val = io->io_read( addr&0xFFF );
1.351 - TRACE_P4IO( "Long read %08X <= %08X", io, (addr&0xFFF), val, addr );
1.352 - return val;
1.353 - }
1.354 + break;
1.355 + case 1: /* VRAM */
1.356 + switch( addr >> 24 ) {
1.357 + case 4: return &mem_region_vram64; /* 0x04xxxxxx */
1.358 + case 5: return &mem_region_vram32; /* 0x05xxxxxx */
1.359 + }
1.360 + break;
1.361 + case 2: /* Unmapped */
1.362 + break;
1.363 + case 3: /* Main sdram */
1.364 + decode_sdram++;
1.365 + return &mem_region_sdram;
1.366 + case 4: /* Holly burst-access only? */
1.367 + break;
1.368 + }
1.369 + return &mem_region_unmapped;
1.370 }
1.371
1.372 -void FASTCALL sh4_write_p4( sh4addr_t addr, int32_t val )
1.373 +int decode_count = 0;
1.374 +int p4_count = 0;
1.375 +int sq_count = 0;
1.376 +
1.377 +mem_region_fn_t FASTCALL sh7750_decode_address( sh4addr_t addr )
1.378 {
1.379 - struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
1.380 - if( !io ) {
1.381 - switch( addr & 0x1F000000 ) {
1.382 - case 0x00000000: case 0x01000000: case 0x02000000: case 0x03000000:
1.383 - /* Store queue */
1.384 - SH4_WRITE_STORE_QUEUE( addr, val );
1.385 - break;
1.386 - case 0x10000000: mmu_icache_addr_write( addr, val ); break;
1.387 - case 0x11000000: mmu_icache_data_write( addr, val ); break;
1.388 - case 0x12000000: mmu_itlb_addr_write( addr, val ); break;
1.389 - case 0x13000000: mmu_itlb_data_write( addr, val ); break;
1.390 - case 0x14000000: mmu_ocache_addr_write( addr, val ); break;
1.391 - case 0x15000000: mmu_ocache_data_write( addr, val ); break;
1.392 - case 0x16000000: mmu_utlb_addr_write( addr, val ); break;
1.393 - case 0x17000000: mmu_utlb_data_write( addr, val ); break;
1.394 - default:
1.395 - if( (addr & 0xFFFF0000 ) == 0xFF940000 ||
1.396 - (addr & 0xFFFF0000 ) == 0xFF900000 ) {
1.397 - // SDRAM configuration, ignore for now
1.398 - } else {
1.399 - WARN( "Attempted write to unknown P4 region: %08X", addr );
1.400 + decode_count++;
1.401 + sh4addr_t region = addr >> 29;
1.402 + switch( region ) {
1.403 + case 7: /* P4 E0000000-FFFFFFFF - On-chip I/O */
1.404 + if( addr < 0xE4000000 ) {
1.405 + sq_count++;
1.406 + return &p4_region_storequeue;
1.407 + } else if( addr < 0xFC000000 ) { /* Control register region */
1.408 + p4_count++;
1.409 + switch( addr & 0x1F000000 ) {
1.410 + case 0x10000000: return &p4_region_icache_addr;
1.411 + case 0x11000000: return &p4_region_icache_data;
1.412 + case 0x12000000: return &p4_region_itlb_addr;
1.413 + case 0x13000000: return &p4_region_itlb_data;
1.414 + case 0x14000000: return &p4_region_ocache_addr;
1.415 + case 0x15000000: return &p4_region_ocache_data;
1.416 + case 0x16000000: return &p4_region_utlb_addr;
1.417 + case 0x17000000: return &p4_region_utlb_data;
1.418 + default: return &mem_region_unmapped;
1.419 }
1.420 + } else {
1.421 + p4_count++;
1.422 + struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
1.423 + if( io != NULL ) {
1.424 + return &io->fn;
1.425 + }
1.426 + return &mem_region_unmapped;
1.427 }
1.428 - } else {
1.429 - TRACE_P4IO( "Long write %08X => %08X", io, (addr&0xFFF), val, addr );
1.430 - io->io_write( addr&0xFFF, val );
1.431 + break;
1.432 + case 6: /* P3 C0000000-DFFFFFFF - TLB on, Cache on */
1.433 + case 5: /* P2 A0000000-BFFFFFFF - TLB off, Cache off*/
1.434 + case 4: /* P1 80000000-9FFFFFFF - TLB off, Cache on */
1.435 + default: /* P0/U0 00000000-7FFFFFFF - TLB on, Cache on */
1.436 + return mem_decode_address( addr & 0x1FFFFFFF );
1.437 + /* TODO: Integrate TLB, Operand Cache lookups */
1.438 }
1.439 }
1.440
1.441 -int32_t sh4_read_phys_word( sh4addr_t addr )
1.442 +void FASTCALL sh7750_decode_address_copy( sh4addr_t addr, mem_region_fn_t result )
1.443 {
1.444 - sh4ptr_t page;
1.445 - if( addr >= 0xE0000000 ) /* P4 Area, handled specially */
1.446 - return SIGNEXT16(sh4_read_p4( addr ));
1.447 -
1.448 - if( (addr&0x1F800000) == 0x04000000 ) {
1.449 - addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
1.450 - }
1.451 -
1.452 - page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
1.453 - if( ((uintptr_t)page) < MAX_IO_REGIONS ) { /* IO Region */
1.454 - if( page == NULL ) {
1.455 - WARN( "Attempted word read to missing page: %08X",
1.456 - addr );
1.457 - return 0;
1.458 - }
1.459 - return SIGNEXT16(io_rgn[(uintptr_t)page]->io_read(addr&0xFFF));
1.460 - } else {
1.461 - return SIGNEXT16(*(int16_t *)(page+(addr&0xFFF)));
1.462 - }
1.463 + mem_region_fn_t region = sh7750_decode_address( addr );
1.464 + memcpy( result, region, sizeof(struct mem_region_fn) -8 );
1.465 }
1.466
1.467 -/**
1.468 - * Convenience function to read a quad-word (implemented as two long reads).
1.469 - */
1.470 -int64_t FASTCALL sh4_read_quad( sh4addr_t addr )
1.471 -{
1.472 - return ((int64_t)((uint32_t)sh4_read_long(addr))) |
1.473 - (((int64_t)((uint32_t)sh4_read_long(addr+4))) << 32);
1.474 -}
1.475 -
1.476 -int32_t FASTCALL sh4_read_long( sh4addr_t addr )
1.477 -{
1.478 - sh4ptr_t page;
1.479 -
1.480 - CHECK_READ_WATCH(addr,4);
1.481 -
1.482 - if( addr >= 0xE0000000 ) { /* P4 Area, handled specially */
1.483 - return ZEROEXT32(sh4_read_p4( addr ));
1.484 - } else if( (addr&0x1C000000) == 0x0C000000 ) {
1.485 - return ZEROEXT32(*(int32_t *)(sh4_main_ram + (addr&0x00FFFFFF)));
1.486 - } else if( (addr&0x1F800000) == 0x04000000 ) {
1.487 - addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
1.488 - pvr2_render_buffer_invalidate(addr, FALSE);
1.489 - } else if( (addr&0x1F800000) == 0x05000000 ) {
1.490 - pvr2_render_buffer_invalidate(addr, FALSE);
1.491 - }
1.492 -
1.493 - page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
1.494 - if( ((uintptr_t)page) < MAX_IO_REGIONS ) { /* IO Region */
1.495 - int32_t val;
1.496 - if( page == NULL ) {
1.497 - WARN( "Attempted long read to missing page: %08X", addr );
1.498 - return 0;
1.499 - }
1.500 - val = io_rgn[(uintptr_t)page]->io_read(addr&0xFFF);
1.501 - TRACE_IO( "Long read %08X <= %08X", page, (addr&0xFFF), val, addr );
1.502 - return ZEROEXT32(val);
1.503 - } else {
1.504 - return ZEROEXT32(*(int32_t *)(page+(addr&0xFFF)));
1.505 - }
1.506 -}
1.507 -
1.508 -int32_t FASTCALL sh4_read_word( sh4addr_t addr )
1.509 -{
1.510 - sh4ptr_t page;
1.511 -
1.512 - CHECK_READ_WATCH(addr,2);
1.513 -
1.514 - if( addr >= 0xE0000000 ) { /* P4 Area, handled specially */
1.515 - return ZEROEXT32(SIGNEXT16(sh4_read_p4( addr )));
1.516 - } else if( (addr&0x1C000000) == 0x0C000000 ) {
1.517 - return ZEROEXT32(SIGNEXT16(*(int16_t *)(sh4_main_ram + (addr&0x00FFFFFF))));
1.518 - } else if( (addr&0x1F800000) == 0x04000000 ) {
1.519 - addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
1.520 - pvr2_render_buffer_invalidate(addr, FALSE);
1.521 - } else if( (addr&0x1F800000) == 0x05000000 ) {
1.522 - pvr2_render_buffer_invalidate(addr, FALSE);
1.523 - }
1.524 -
1.525 - page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
1.526 - if( ((uintptr_t)page) < MAX_IO_REGIONS ) { /* IO Region */
1.527 - int32_t val;
1.528 - if( page == NULL ) {
1.529 - WARN( "Attempted word read to missing page: %08X", addr );
1.530 - return 0;
1.531 - }
1.532 - val = SIGNEXT16(io_rgn[(uintptr_t)page]->io_read(addr&0xFFF));
1.533 - TRACE_IO( "Word read %04X <= %08X", page, (addr&0xFFF), val&0xFFFF, addr );
1.534 - return ZEROEXT32(val);
1.535 - } else {
1.536 - return ZEROEXT32(SIGNEXT16(*(int16_t *)(page+(addr&0xFFF))));
1.537 - }
1.538 -}
1.539 -
1.540 -int32_t FASTCALL sh4_read_byte( sh4addr_t addr )
1.541 -{
1.542 - sh4ptr_t page;
1.543 -
1.544 - CHECK_READ_WATCH(addr,1);
1.545 -
1.546 - if( addr >= 0xE0000000 ) { /* P4 Area, handled specially */
1.547 - return ZEROEXT32(SIGNEXT8(sh4_read_p4( addr )));
1.548 - } else if( (addr&0x1C000000) == 0x0C000000 ) {
1.549 - return ZEROEXT32(SIGNEXT8(*(int8_t *)(sh4_main_ram + (addr&0x00FFFFFF))));
1.550 - } else if( (addr&0x1F800000) == 0x04000000 ) {
1.551 - addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
1.552 - pvr2_render_buffer_invalidate(addr, FALSE);
1.553 - } else if( (addr&0x1F800000) == 0x05000000 ) {
1.554 - pvr2_render_buffer_invalidate(addr, FALSE);
1.555 - }
1.556 -
1.557 -
1.558 - page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
1.559 - if( ((uintptr_t)page) < MAX_IO_REGIONS ) { /* IO Region */
1.560 - int32_t val;
1.561 - if( page == NULL ) {
1.562 - WARN( "Attempted byte read to missing page: %08X", addr );
1.563 - return 0;
1.564 - }
1.565 - val = SIGNEXT8(io_rgn[(uintptr_t)page]->io_read(addr&0xFFF));
1.566 - TRACE_IO( "Byte read %02X <= %08X", page, (addr&0xFFF), val&0xFF, addr );
1.567 - return ZEROEXT32(val);
1.568 - } else {
1.569 - return ZEROEXT32(SIGNEXT8(*(int8_t *)(page+(addr&0xFFF))));
1.570 - }
1.571 -}
1.572 -
1.573 -/**
1.574 - * Convenience function to write a quad-word (implemented as two long writes).
1.575 - */
1.576 -void FASTCALL sh4_write_quad( sh4addr_t addr, uint64_t val )
1.577 -{
1.578 - sh4_write_long( addr, (uint32_t)val );
1.579 - sh4_write_long( addr+4, (uint32_t)(val>>32) );
1.580 -}
1.581 -
1.582 -void FASTCALL sh4_write_long( sh4addr_t addr, uint32_t val )
1.583 -{
1.584 - sh4ptr_t page;
1.585 -
1.586 - CHECK_WRITE_WATCH(addr,4,val);
1.587 -
1.588 - if( addr >= 0xE0000000 ) {
1.589 - if( addr < 0xE4000000 ) { // Shortcut for the extremely common case
1.590 - SH4_WRITE_STORE_QUEUE( addr, val );
1.591 - } else {
1.592 - sh4_write_p4( addr, val );
1.593 - }
1.594 - return;
1.595 - } else if( (addr&0x1C000000) == 0x0C000000 ) {
1.596 - *(uint32_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = val;
1.597 - xlat_invalidate_long(addr);
1.598 - return;
1.599 - } else if( (addr&0x1F800000) == 0x04000000 ||
1.600 - (addr&0x1F800000) == 0x11000000 ) {
1.601 - texcache_invalidate_page(addr& 0x7FFFFF);
1.602 - addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
1.603 - pvr2_render_buffer_invalidate(addr, TRUE);
1.604 - } else if( (addr&0x1F800000) == 0x05000000 ) {
1.605 - pvr2_render_buffer_invalidate(addr, TRUE);
1.606 - }
1.607 -
1.608 - if( (addr&0x1FFFFFFF) < 0x200000 ) {
1.609 - WARN( "Attempted write to read-only memory: %08X => %08X", val, addr);
1.610 - sh4_stop();
1.611 - return;
1.612 - }
1.613 - if( (addr&0x1F800000) == 0x00800000 )
1.614 - asic_g2_write_word();
1.615 -
1.616 - page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
1.617 - if( ((uintptr_t)page) < MAX_IO_REGIONS ) { /* IO Region */
1.618 - if( page == NULL ) {
1.619 - if( (addr & 0x1F000000) >= 0x04000000 &&
1.620 - (addr & 0x1F000000) < 0x07000000 )
1.621 - return;
1.622 - WARN( "Long write to missing page: %08X => %08X", val, addr );
1.623 - return;
1.624 - }
1.625 - TRACE_IO( "Long write %08X => %08X", page, (addr&0xFFF), val, addr );
1.626 - io_rgn[(uintptr_t)page]->io_write(addr&0xFFF, val);
1.627 - } else {
1.628 - *(uint32_t *)(page+(addr&0xFFF)) = val;
1.629 - }
1.630 -}
1.631 -
1.632 -void FASTCALL sh4_write_word( sh4addr_t addr, uint32_t val )
1.633 -{
1.634 - sh4ptr_t page;
1.635 -
1.636 - CHECK_WRITE_WATCH(addr,2,val);
1.637 -
1.638 - if( addr >= 0xE0000000 ) {
1.639 - sh4_write_p4( addr, (int16_t)val );
1.640 - return;
1.641 - } else if( (addr&0x1C000000) == 0x0C000000 ) {
1.642 - *(uint16_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = val;
1.643 - xlat_invalidate_word(addr);
1.644 - return;
1.645 - } else if( (addr&0x1F800000) == 0x04000000 ||
1.646 - (addr&0x1F800000) == 0x11000000 ) {
1.647 - texcache_invalidate_page(addr& 0x7FFFFF);
1.648 - addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
1.649 - pvr2_render_buffer_invalidate(addr, TRUE);
1.650 - } else if( (addr&0x1F800000) == 0x05000000 ) {
1.651 - pvr2_render_buffer_invalidate(addr, TRUE);
1.652 - }
1.653 -
1.654 - if( (addr&0x1FFFFFFF) < 0x200000 ) {
1.655 - WARN( "Attempted write to read-only memory: %08X => %08X", val, addr);
1.656 - sh4_stop();
1.657 - return;
1.658 - }
1.659 - page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
1.660 - if( ((uintptr_t)page) < MAX_IO_REGIONS ) { /* IO Region */
1.661 - if( page == NULL ) {
1.662 - WARN( "Attempted word write to missing page: %08X", addr );
1.663 - return;
1.664 - }
1.665 - TRACE_IO( "Word write %04X => %08X", page, (addr&0xFFF), val&0xFFFF, addr );
1.666 - io_rgn[(uintptr_t)page]->io_write(addr&0xFFF, val);
1.667 - } else {
1.668 - *(uint16_t *)(page+(addr&0xFFF)) = val;
1.669 - }
1.670 -}
1.671 -
1.672 -void FASTCALL sh4_write_byte( sh4addr_t addr, uint32_t val )
1.673 -{
1.674 - sh4ptr_t page;
1.675 -
1.676 - CHECK_WRITE_WATCH(addr,1,val);
1.677 -
1.678 - if( addr >= 0xE0000000 ) {
1.679 - sh4_write_p4( addr, (int8_t)val );
1.680 - return;
1.681 - } else if( (addr&0x1C000000) == 0x0C000000 ) {
1.682 - *(uint8_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = val;
1.683 - xlat_invalidate_word(addr);
1.684 - return;
1.685 - } else if( (addr&0x1F800000) == 0x04000000 ||
1.686 - (addr&0x1F800000) == 0x11000000 ) {
1.687 - texcache_invalidate_page(addr& 0x7FFFFF);
1.688 - addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
1.689 - pvr2_render_buffer_invalidate(addr, TRUE);
1.690 - } else if( (addr&0x1F800000) == 0x05000000 ) {
1.691 - pvr2_render_buffer_invalidate(addr, TRUE);
1.692 - }
1.693 -
1.694 - if( (addr&0x1FFFFFFF) < 0x200000 ) {
1.695 - WARN( "Attempted write to read-only memory: %08X => %08X", val, addr);
1.696 - sh4_stop();
1.697 - return;
1.698 - }
1.699 - page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
1.700 - if( ((uintptr_t)page) < MAX_IO_REGIONS ) { /* IO Region */
1.701 - if( page == NULL ) {
1.702 - WARN( "Attempted byte write to missing page: %08X", addr );
1.703 - return;
1.704 - }
1.705 - TRACE_IO( "Byte write %02X => %08X", page, (addr&0xFFF), val&0xFF, addr );
1.706 - io_rgn[(uintptr_t)page]->io_write( (addr&0xFFF), val);
1.707 - } else {
1.708 - *(uint8_t *)(page+(addr&0xFFF)) = val;
1.709 - }
1.710 -}
1.711 -
1.712 -
1.713 -
1.714 /* FIXME: Handle all the many special cases when the range doesn't fall cleanly
1.715 * into the same memory block
1.716 */
1.717 @@ -432,3 +410,109 @@
1.718 }
1.719 }
1.720
1.721 +static uint32_t last_page = -1;
1.722 +static mem_region_fn_t last_region = NULL;
1.723 +static uint32_t hit_count = 0;
1.724 +static uint32_t miss_count = 0;
1.725 +static uint32_t rl_count = 0, rw_count = 0, rb_count = 0;
1.726 +static uint32_t wl_count = 0, ww_count = 0, wb_count = 0;
1.727 +
1.728 +/************** Compatibility methods ***************/
1.729 +
1.730 +int32_t FASTCALL sh4_read_long( sh4addr_t addr )
1.731 +{
1.732 + rl_count++;
1.733 + uint32_t page = (addr & 0xFFFFF000);
1.734 + if( page == last_page ) {
1.735 + hit_count++;
1.736 + return last_region->read_long(addr);
1.737 + } else {
1.738 + miss_count++;
1.739 + last_page = page;
1.740 + last_region = sh7750_decode_address(addr);
1.741 + return last_region->read_long(addr);
1.742 + }
1.743 +}
1.744 +
1.745 +int32_t FASTCALL sh4_read_word( sh4addr_t addr )
1.746 +{
1.747 + rw_count++;
1.748 + uint32_t page = (addr & 0xFFFFF000);
1.749 + if( page == last_page ) {
1.750 + hit_count++;
1.751 + return last_region->read_word(addr);
1.752 + } else {
1.753 + miss_count++;
1.754 + last_page = page;
1.755 + last_region = sh7750_decode_address(addr);
1.756 + return last_region->read_word(addr);
1.757 + }
1.758 +}
1.759 +
1.760 +int32_t FASTCALL sh4_read_byte( sh4addr_t addr )
1.761 +{
1.762 + rb_count++;
1.763 + uint32_t page = (addr & 0xFFFFF000);
1.764 + if( page == last_page ) {
1.765 + hit_count++;
1.766 + return last_region->read_byte(addr);
1.767 + } else {
1.768 + miss_count++;
1.769 + last_page = page;
1.770 + last_region = sh7750_decode_address(addr);
1.771 + return last_region->read_byte(addr);
1.772 + }
1.773 +}
1.774 +
1.775 +void FASTCALL sh4_write_long( sh4addr_t addr, uint32_t val )
1.776 +{
1.777 + wl_count++;
1.778 + uint32_t page = (addr & 0xFFFFF000);
1.779 + if( page == last_page ) {
1.780 + hit_count++;
1.781 + last_region->write_long(addr, val);
1.782 + } else {
1.783 + miss_count++;
1.784 + last_page = page;
1.785 + last_region = sh7750_decode_address(addr);
1.786 + last_region->write_long(addr,val);
1.787 + }
1.788 +}
1.789 +
1.790 +void FASTCALL sh4_write_word( sh4addr_t addr, uint32_t val )
1.791 +{
1.792 + ww_count++;
1.793 + uint32_t page = (addr & 0xFFFFF000);
1.794 + if( page == last_page ) {
1.795 + hit_count++;
1.796 + last_region->write_word(addr, val);
1.797 + } else {
1.798 + miss_count++;
1.799 + last_page = page;
1.800 + last_region = sh7750_decode_address(addr);
1.801 + last_region->write_word(addr,val);
1.802 + }
1.803 +}
1.804 +
1.805 +void FASTCALL sh4_write_byte( sh4addr_t addr, uint32_t val )
1.806 +{
1.807 + wb_count++;
1.808 + uint32_t page = (addr & 0xFFFFF000);
1.809 + if( page == last_page ) {
1.810 + hit_count++;
1.811 + last_region->write_byte(addr, val);
1.812 + } else {
1.813 + miss_count++;
1.814 + last_page = page;
1.815 + last_region = sh7750_decode_address(addr);
1.816 + last_region->write_byte(addr,val);
1.817 + }
1.818 +}
1.819 +
1.820 +void print_sh4mem_stats() {
1.821 + printf( "Decodes to p4: %d sq: %d\n", p4_count+sq_count, sq_count );
1.822 + printf( "Decodes to sdram: %d\n", decode_sdram );
1.823 + printf( "Decodes: %d Hits: %d Miss: %d\n", decode_count, hit_count, miss_count );
1.824 + printf( "Read long: %d word: %d byte: %d\n", rl_count, rw_count, rb_count );
1.825 + printf( "Write long: %d word: %d byte: %d\n", wl_count, ww_count, wb_count );
1.826 +}
1.827 \ No newline at end of file
.