Search
lxdream.org :: lxdream/src/sh4/sh4mem.c
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.
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 mem_region_storequeue;
    42 extern struct mem_region_fn mem_region_icache_addr;
    43 extern struct mem_region_fn mem_region_icache_data;
    44 extern struct mem_region_fn mem_region_ocache_addr;
    45 extern struct mem_region_fn mem_region_ocache_data;
    46 extern struct mem_region_fn mem_region_itlb_addr;
    47 extern struct mem_region_fn mem_region_itlb_data;
    48 extern struct mem_region_fn mem_region_utlb_addr;
    49 extern struct mem_region_fn mem_region_utlb_data;
    51 extern struct mmio_region *P4_io[];
    53 /********************* The "unmapped" address space ********************/
    54 /* Always reads as 0, writes have no effect */
    55 static int32_t FASTCALL unmapped_read_long( sh4addr_t addr )
    56 {
    57     return 0;
    58 }
    59 static void FASTCALL unmapped_write_long( sh4addr_t addr, uint32_t val )
    60 {
    61 }
    62 static void FASTCALL unmapped_read_burst( unsigned char *dest, sh4addr_t addr )
    63 {
    64     memset( dest, 0, 32 );
    65 }
    66 static void FASTCALL unmapped_write_burst( sh4addr_t addr, unsigned char *src )
    67 {
    68 }
    70 struct mem_region_fn mem_region_unmapped = { 
    71         unmapped_read_long, unmapped_write_long, 
    72         unmapped_read_long, unmapped_write_long, 
    73         unmapped_read_long, unmapped_write_long, 
    74         unmapped_read_burst, unmapped_write_burst }; 
    76 /********************* Store-queue (long-write only?) ******************/
    77 static void FASTCALL p4_storequeue_write_long( sh4addr_t addr, uint32_t val )
    78 {
    79     sh4r.store_queue[(addr>>2)&0xF] = val;
    80 }
    81 static int32_t FASTCALL p4_storequeue_read_long( sh4addr_t addr )
    82 {
    83     return sh4r.store_queue[(addr>>2)&0xF];
    84 }
    85 struct mem_region_fn p4_region_storequeue = { 
    86         p4_storequeue_read_long, p4_storequeue_write_long,
    87         p4_storequeue_read_long, p4_storequeue_write_long,
    88         p4_storequeue_read_long, p4_storequeue_write_long,
    89         unmapped_read_burst, unmapped_write_burst }; // No burst access.
    91 /********************* The main ram address space **********************/
    92 static int32_t FASTCALL ext_sdram_read_long( sh4addr_t addr )
    93 {
    94     return *((int32_t *)(sh4_main_ram + (addr&0x00FFFFFF)));
    95 }
    96 static int32_t FASTCALL ext_sdram_read_word( sh4addr_t addr )
    97 {
    98     return SIGNEXT16(*((int16_t *)(sh4_main_ram + (addr&0x00FFFFFF))));
    99 }
   100 static int32_t FASTCALL ext_sdram_read_byte( sh4addr_t addr )
   101 {
   102     return SIGNEXT8(*((int16_t *)(sh4_main_ram + (addr&0x00FFFFFF))));
   103 }
   104 static void FASTCALL ext_sdram_write_long( sh4addr_t addr, uint32_t val )
   105 {
   106     *(uint32_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = val;
   107     xlat_invalidate_long(addr);
   108 }
   109 static void FASTCALL ext_sdram_write_word( sh4addr_t addr, uint32_t val )
   110 {
   111     *(uint16_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = (uint16_t)val;
   112     xlat_invalidate_word(addr);
   113 }
   114 static void FASTCALL ext_sdram_write_byte( sh4addr_t addr, uint32_t val )
   115 {
   116     *(uint8_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = (uint8_t)val;
   117     xlat_invalidate_word(addr);
   118 }
   119 static void FASTCALL ext_sdram_read_burst( unsigned char *dest, sh4addr_t addr )
   120 {
   121     memcpy( dest, sh4_main_ram+(addr&0x00FFFFFF), 32 );
   122 }
   123 static void FASTCALL ext_sdram_write_burst( sh4addr_t addr, unsigned char *src )
   124 {
   125     memcpy( sh4_main_ram+(addr&0x00FFFFFF), src, 32 );
   126 }
   128 struct mem_region_fn mem_region_sdram = { ext_sdram_read_long, ext_sdram_write_long, 
   129         ext_sdram_read_word, ext_sdram_write_word, 
   130         ext_sdram_read_byte, ext_sdram_write_byte, 
   131         ext_sdram_read_burst, ext_sdram_write_burst }; 
   134 /********************* The Boot ROM address space **********************/
   135 extern sh4ptr_t dc_boot_rom;
   136 extern sh4ptr_t dc_flash_ram;
   137 extern sh4ptr_t dc_audio_ram;
   138 static int32_t FASTCALL ext_bootrom_read_long( sh4addr_t addr )
   139 {
   140     return *((int32_t *)(dc_boot_rom + (addr&0x001FFFFF)));
   141 }
   142 static int32_t FASTCALL ext_bootrom_read_word( sh4addr_t addr )
   143 {
   144     return SIGNEXT16(*((int16_t *)(dc_boot_rom + (addr&0x001FFFFF))));
   145 }
   146 static int32_t FASTCALL ext_bootrom_read_byte( sh4addr_t addr )
   147 {
   148     return SIGNEXT8(*((int16_t *)(dc_boot_rom + (addr&0x001FFFFF))));
   149 }
   150 static void FASTCALL ext_bootrom_read_burst( unsigned char *dest, sh4addr_t addr )
   151 {
   152     memcpy( dest, sh4_main_ram+(addr&0x001FFFFF), 32 );
   153 }
   155 struct mem_region_fn mem_region_bootrom = { 
   156         ext_bootrom_read_long, unmapped_write_long, 
   157         ext_bootrom_read_word, unmapped_write_long, 
   158         ext_bootrom_read_byte, unmapped_write_long, 
   159         ext_bootrom_read_burst, unmapped_write_burst }; 
   161 /********************* The Audio RAM address space **********************/
   162 static int32_t FASTCALL ext_audioram_read_long( sh4addr_t addr )
   163 {
   164     return *((int32_t *)(dc_audio_ram + (addr&0x001FFFFF)));
   165 }
   166 static int32_t FASTCALL ext_audioram_read_word( sh4addr_t addr )
   167 {
   168     return SIGNEXT16(*((int16_t *)(dc_audio_ram + (addr&0x001FFFFF))));
   169 }
   170 static int32_t FASTCALL ext_audioram_read_byte( sh4addr_t addr )
   171 {
   172     return SIGNEXT8(*((int16_t *)(dc_audio_ram + (addr&0x001FFFFF))));
   173 }
   174 static void FASTCALL ext_audioram_write_long( sh4addr_t addr, uint32_t val )
   175 {
   176     *(uint32_t *)(dc_audio_ram + (addr&0x001FFFFF)) = val;
   177     asic_g2_write_word();
   178 }
   179 static void FASTCALL ext_audioram_write_word( sh4addr_t addr, uint32_t val )
   180 {
   181     *(uint16_t *)(dc_audio_ram + (addr&0x001FFFFF)) = (uint16_t)val;
   182     asic_g2_write_word();
   183 }
   184 static void FASTCALL ext_audioram_write_byte( sh4addr_t addr, uint32_t val )
   185 {
   186     *(uint8_t *)(dc_audio_ram + (addr&0x001FFFFF)) = (uint8_t)val;
   187     asic_g2_write_word();
   188 }
   189 static void FASTCALL ext_audioram_read_burst( unsigned char *dest, sh4addr_t addr )
   190 {
   191     memcpy( dest, dc_audio_ram+(addr&0x001FFFFF), 32 );
   192 }
   193 static void FASTCALL ext_audioram_write_burst( sh4addr_t addr, unsigned char *src )
   194 {
   195     memcpy( dc_audio_ram+(addr&0x001FFFFF), src, 32 );
   196 }
   198 struct mem_region_fn mem_region_audioram = { ext_audioram_read_long, ext_audioram_write_long, 
   199         ext_audioram_read_word, ext_audioram_write_word, 
   200         ext_audioram_read_byte, ext_audioram_write_byte, 
   201         ext_audioram_read_burst, ext_audioram_write_burst }; 
   203 /********************* The Flash RAM address space **********************/
   204 static int32_t FASTCALL ext_flashram_read_long( sh4addr_t addr )
   205 {
   206     return *((int32_t *)(dc_flash_ram + (addr&0x0001FFFF)));
   207 }
   208 static int32_t FASTCALL ext_flashram_read_word( sh4addr_t addr )
   209 {
   210     return SIGNEXT16(*((int16_t *)(dc_flash_ram + (addr&0x0001FFFF))));
   211 }
   212 static int32_t FASTCALL ext_flashram_read_byte( sh4addr_t addr )
   213 {
   214     return SIGNEXT8(*((int16_t *)(dc_flash_ram + (addr&0x0001FFFF))));
   215 }
   216 static void FASTCALL ext_flashram_write_long( sh4addr_t addr, uint32_t val )
   217 {
   218     *(uint32_t *)(dc_flash_ram + (addr&0x0001FFFF)) = val;
   219     asic_g2_write_word();
   220 }
   221 static void FASTCALL ext_flashram_write_word( sh4addr_t addr, uint32_t val )
   222 {
   223     *(uint16_t *)(dc_flash_ram + (addr&0x0001FFFF)) = (uint16_t)val;
   224     asic_g2_write_word();
   225 }
   226 static void FASTCALL ext_flashram_write_byte( sh4addr_t addr, uint32_t val )
   227 {
   228     *(uint8_t *)(dc_flash_ram + (addr&0x0001FFFF)) = (uint8_t)val;
   229     asic_g2_write_word();
   230 }
   231 static void FASTCALL ext_flashram_read_burst( unsigned char *dest, sh4addr_t addr )
   232 {
   233     memcpy( dest, dc_flash_ram+(addr&0x0001FFFF), 32 );
   234 }
   235 static void FASTCALL ext_flashram_write_burst( sh4addr_t addr, unsigned char *src )
   236 {
   237     memcpy( dc_flash_ram+(addr&0x0001FFFF), src, 32 );
   238 }
   240 struct mem_region_fn mem_region_flashram = { ext_flashram_read_long, ext_flashram_write_long, 
   241         ext_flashram_read_word, ext_flashram_write_word, 
   242         ext_flashram_read_byte, ext_flashram_write_byte, 
   243         ext_flashram_read_burst, ext_flashram_write_burst }; 
   245 /**************************************************************************/
   247 struct mem_region_fn p4_region_icache_addr = {
   248         mmu_icache_addr_read, mmu_icache_addr_write,
   249         mmu_icache_addr_read, mmu_icache_addr_write,
   250         mmu_icache_addr_read, mmu_icache_addr_write,
   251         unmapped_read_burst, unmapped_write_burst };
   252 struct mem_region_fn p4_region_icache_data = {
   253         mmu_icache_data_read, mmu_icache_data_write,
   254         mmu_icache_data_read, mmu_icache_data_write,
   255         mmu_icache_data_read, mmu_icache_data_write,
   256         unmapped_read_burst, unmapped_write_burst };
   257 struct mem_region_fn p4_region_ocache_addr = {
   258         mmu_ocache_addr_read, mmu_ocache_addr_write,
   259         mmu_ocache_addr_read, mmu_ocache_addr_write,
   260         mmu_ocache_addr_read, mmu_ocache_addr_write,
   261         unmapped_read_burst, unmapped_write_burst };
   262 struct mem_region_fn p4_region_ocache_data = {
   263         mmu_ocache_data_read, mmu_ocache_data_write,
   264         mmu_ocache_data_read, mmu_ocache_data_write,
   265         mmu_ocache_data_read, mmu_ocache_data_write,
   266         unmapped_read_burst, unmapped_write_burst };
   267 struct mem_region_fn p4_region_itlb_addr = {
   268         mmu_itlb_addr_read, mmu_itlb_addr_write,
   269         mmu_itlb_addr_read, mmu_itlb_addr_write,
   270         mmu_itlb_addr_read, mmu_itlb_addr_write,
   271         unmapped_read_burst, unmapped_write_burst };
   272 struct mem_region_fn p4_region_itlb_data = {
   273         mmu_itlb_data_read, mmu_itlb_data_write,
   274         mmu_itlb_data_read, mmu_itlb_data_write,
   275         mmu_itlb_data_read, mmu_itlb_data_write,
   276         unmapped_read_burst, unmapped_write_burst };
   277 struct mem_region_fn p4_region_utlb_addr = {
   278         mmu_utlb_addr_read, mmu_utlb_addr_write,
   279         mmu_utlb_addr_read, mmu_utlb_addr_write,
   280         mmu_utlb_addr_read, mmu_utlb_addr_write,
   281         unmapped_read_burst, unmapped_write_burst };
   282 struct mem_region_fn p4_region_utlb_data = {
   283         mmu_utlb_data_read, mmu_utlb_data_write,
   284         mmu_utlb_data_read, mmu_utlb_data_write,
   285         mmu_utlb_data_read, mmu_utlb_data_write,
   286         unmapped_read_burst, unmapped_write_burst };
   288 #ifdef HAVE_FRAME_ADDRESS
   289 #define RETURN_VIA(exc) do{ *(((void **)__builtin_frame_address(0))+1) = exc; return; } while(0)
   290 #else
   291 #define RETURN_VIA(exc) return NULL
   292 #endif
   294 int decode_sdram = 0;
   295 mem_region_fn_t FASTCALL mem_decode_address( sh4addr_t addr )
   296 {
   297     sh4ptr_t page;
   298     switch( addr >> 26 ) { /* Area */
   299     case 0: /* Holly multiplexed */
   300         page = page_map[(addr&0x1FFFFFFF)>>12];
   301         if( ((uintptr_t)page) < MAX_IO_REGIONS ) {
   302             return &io_rgn[(uintptr_t)page]->fn;
   303         } else if( addr < 0x00200000 ) {
   304             return &mem_region_bootrom;
   305         } else if( addr < 0x00400000 ) {
   306             return &mem_region_flashram;
   307         } else if( addr >= 0x00800000 && addr < 0x00A00000 ) {
   308             return &mem_region_audioram;
   309         }
   310         break;
   311     case 1: /* VRAM */
   312         switch( addr >> 24 ) {
   313         case 4: return &mem_region_vram64; /* 0x04xxxxxx */
   314         case 5: return &mem_region_vram32; /* 0x05xxxxxx */ 
   315         }    
   316         break;
   317     case 2: /* Unmapped */
   318         break;
   319     case 3: /* Main sdram */
   320         decode_sdram++;
   321         return &mem_region_sdram;
   322     case 4: /* Holly burst-access only? */
   323         break;
   324     }
   325     return &mem_region_unmapped;
   326 }
   328 int decode_count = 0;
   329 int p4_count = 0;
   330 int sq_count = 0;
   332 mem_region_fn_t FASTCALL sh7750_decode_address( sh4addr_t addr )
   333 {
   334     decode_count++;
   335     sh4addr_t region = addr >> 29;
   336     switch( region ) {
   337     case 7: /* P4 E0000000-FFFFFFFF - On-chip I/O */
   338         if( addr < 0xE4000000 ) {
   339             sq_count++;
   340             return &p4_region_storequeue;
   341         } else if( addr < 0xFC000000 ) { /* Control register region */
   342             p4_count++;
   343             switch( addr & 0x1F000000 ) {
   344             case 0x10000000: return &p4_region_icache_addr;
   345             case 0x11000000: return &p4_region_icache_data;
   346             case 0x12000000: return &p4_region_itlb_addr;
   347             case 0x13000000: return &p4_region_itlb_data;
   348             case 0x14000000: return &p4_region_ocache_addr;
   349             case 0x15000000: return &p4_region_ocache_data;
   350             case 0x16000000: return &p4_region_utlb_addr;
   351             case 0x17000000: return &p4_region_utlb_data;
   352             default: return &mem_region_unmapped;
   353             }
   354         } else {
   355             p4_count++;
   356             struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
   357             if( io != NULL ) {
   358                 return &io->fn;
   359             }
   360             return &mem_region_unmapped;
   361         }
   362         break;
   363     case 6: /* P3 C0000000-DFFFFFFF - TLB on, Cache on */
   364     case 5: /* P2 A0000000-BFFFFFFF - TLB off, Cache off*/
   365     case 4: /* P1 80000000-9FFFFFFF - TLB off, Cache on */
   366     default: /* P0/U0 00000000-7FFFFFFF - TLB on, Cache on */
   367         return mem_decode_address( addr & 0x1FFFFFFF ); 
   368         /* TODO: Integrate TLB, Operand Cache lookups */
   369     }
   370 }
   372 void FASTCALL sh7750_decode_address_copy( sh4addr_t addr, mem_region_fn_t result )
   373 {
   374     mem_region_fn_t region = sh7750_decode_address( addr );
   375     memcpy( result, region, sizeof(struct mem_region_fn) -8 );
   376 }
   378 /* FIXME: Handle all the many special cases when the range doesn't fall cleanly
   379  * into the same memory block
   380  */
   381 void mem_copy_from_sh4( sh4ptr_t dest, sh4addr_t srcaddr, size_t count ) {
   382     if( srcaddr >= 0x04000000 && srcaddr < 0x05000000 ) {
   383         pvr2_vram64_read( dest, srcaddr, count );
   384     } else {
   385         sh4ptr_t src = mem_get_region(srcaddr);
   386         if( src == NULL ) {
   387             WARN( "Attempted block read from unknown address %08X", srcaddr );
   388         } else {
   389             memcpy( dest, src, count );
   390         }
   391     }
   392 }
   394 void mem_copy_to_sh4( sh4addr_t destaddr, sh4ptr_t src, size_t count ) {
   395     if( destaddr >= 0x10000000 && destaddr < 0x14000000 ) {
   396         pvr2_dma_write( destaddr, src, count );
   397         return;
   398     } else if( (destaddr & 0x1F800000) == 0x05000000 ) {
   399         pvr2_render_buffer_invalidate( destaddr, TRUE );
   400     } else if( (destaddr & 0x1F800000) == 0x04000000 ) {
   401         pvr2_vram64_write( destaddr, src, count );
   402         return;
   403     }
   404     sh4ptr_t dest = mem_get_region(destaddr);
   405     if( dest == NULL )
   406         WARN( "Attempted block write to unknown address %08X", destaddr );
   407     else {
   408         xlat_invalidate_block( destaddr, count );
   409         memcpy( dest, src, count );
   410     }
   411 }
   413 static uint32_t last_page = -1;
   414 static mem_region_fn_t last_region = NULL; 
   415 static uint32_t hit_count = 0;
   416 static uint32_t miss_count = 0;
   417 static uint32_t rl_count = 0, rw_count = 0, rb_count = 0;
   418 static uint32_t wl_count = 0, ww_count = 0, wb_count = 0;
   420 /************** Compatibility methods ***************/
   422 int32_t FASTCALL sh4_read_long( sh4addr_t addr )
   423 {
   424     rl_count++;
   425     uint32_t page = (addr & 0xFFFFF000);
   426     if( page == last_page ) {
   427         hit_count++;
   428         return last_region->read_long(addr);
   429     } else {
   430         miss_count++;
   431         last_page = page;
   432         last_region = sh7750_decode_address(addr);
   433         return last_region->read_long(addr);
   434     }
   435 }
   437 int32_t FASTCALL sh4_read_word( sh4addr_t addr )
   438 {
   439     rw_count++;
   440     uint32_t page = (addr & 0xFFFFF000);
   441     if( page == last_page ) {
   442         hit_count++;
   443         return last_region->read_word(addr);
   444     } else {
   445         miss_count++;
   446         last_page = page;
   447         last_region = sh7750_decode_address(addr);
   448         return last_region->read_word(addr);
   449     }
   450 }
   452 int32_t FASTCALL sh4_read_byte( sh4addr_t addr )
   453 {
   454     rb_count++;
   455     uint32_t page = (addr & 0xFFFFF000);
   456     if( page == last_page ) {
   457         hit_count++;
   458         return last_region->read_byte(addr);
   459     } else {
   460         miss_count++;
   461         last_page = page;
   462         last_region = sh7750_decode_address(addr);
   463         return last_region->read_byte(addr);
   464     }    
   465 }
   467 void FASTCALL sh4_write_long( sh4addr_t addr, uint32_t val )
   468 {
   469     wl_count++;
   470     uint32_t page = (addr & 0xFFFFF000);
   471     if( page == last_page ) {
   472         hit_count++;
   473         last_region->write_long(addr, val);
   474     } else {
   475         miss_count++;
   476         last_page = page;
   477         last_region = sh7750_decode_address(addr);
   478         last_region->write_long(addr,val);
   479     }
   480 }
   482 void FASTCALL sh4_write_word( sh4addr_t addr, uint32_t val )
   483 {
   484     ww_count++;
   485     uint32_t page = (addr & 0xFFFFF000);
   486     if( page == last_page ) {
   487         hit_count++;
   488         last_region->write_word(addr, val);
   489     } else {
   490         miss_count++;
   491         last_page = page;
   492         last_region = sh7750_decode_address(addr);
   493         last_region->write_word(addr,val);
   494     }
   495 }
   497 void FASTCALL sh4_write_byte( sh4addr_t addr, uint32_t val )
   498 {
   499     wb_count++;
   500     uint32_t page = (addr & 0xFFFFF000);
   501     if( page == last_page ) {
   502         hit_count++;
   503         last_region->write_byte(addr, val);
   504     } else {
   505         miss_count++;
   506         last_page = page;
   507         last_region = sh7750_decode_address(addr);
   508         last_region->write_byte(addr,val);
   509     }
   510 }
   512 void print_sh4mem_stats() {
   513     printf( "Decodes to p4: %d sq: %d\n", p4_count+sq_count, sq_count );
   514     printf( "Decodes to sdram: %d\n", decode_sdram );
   515     printf( "Decodes: %d Hits: %d Miss: %d\n", decode_count, hit_count, miss_count );
   516     printf( "Read long:  %d word: %d byte: %d\n", rl_count, rw_count, rb_count );
   517     printf( "Write long: %d word: %d byte: %d\n", wl_count, ww_count, wb_count );
.