Search
lxdream.org :: lxdream/src/sh4/sh4mem.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4mem.c
changeset 933:880c37bb1909
prev931:430048ea8b71
next934:3acd3b3ee6d1
author nkeynes
date Wed Dec 24 06:06:23 2008 +0000 (12 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change Start putting cache together
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 *)(sh4_main_ram + (addr&0x00FFFFFF)));
    55 }
    56 static int32_t FASTCALL ext_sdram_read_word( sh4addr_t addr )
    57 {
    58     return SIGNEXT16(*((int16_t *)(sh4_main_ram + (addr&0x00FFFFFF))));
    59 }
    60 static int32_t FASTCALL ext_sdram_read_byte( sh4addr_t addr )
    61 {
    62     return SIGNEXT8(*((int16_t *)(sh4_main_ram + (addr&0x00FFFFFF))));
    63 }
    64 static void FASTCALL ext_sdram_write_long( sh4addr_t addr, uint32_t val )
    65 {
    66     *(uint32_t *)(sh4_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 *)(sh4_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 *)(sh4_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, sh4_main_ram+(addr&0x00FFFFFF), 32 );
    82 }
    83 static void FASTCALL ext_sdram_write_burst( sh4addr_t addr, unsigned char *src )
    84 {
    85     memcpy( sh4_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 /********************* The Boot ROM address space **********************/
    95 extern sh4ptr_t dc_boot_rom;
    96 extern sh4ptr_t dc_flash_ram;
    97 extern sh4ptr_t dc_audio_ram;
    98 static int32_t FASTCALL ext_bootrom_read_long( sh4addr_t addr )
    99 {
   100     return *((int32_t *)(dc_boot_rom + (addr&0x001FFFFF)));
   101 }
   102 static int32_t FASTCALL ext_bootrom_read_word( sh4addr_t addr )
   103 {
   104     return SIGNEXT16(*((int16_t *)(dc_boot_rom + (addr&0x001FFFFF))));
   105 }
   106 static int32_t FASTCALL ext_bootrom_read_byte( sh4addr_t addr )
   107 {
   108     return SIGNEXT8(*((int16_t *)(dc_boot_rom + (addr&0x001FFFFF))));
   109 }
   110 static void FASTCALL ext_bootrom_read_burst( unsigned char *dest, sh4addr_t addr )
   111 {
   112     memcpy( dest, sh4_main_ram+(addr&0x001FFFFF), 32 );
   113 }
   115 struct mem_region_fn mem_region_bootrom = { 
   116         ext_bootrom_read_long, unmapped_write_long, 
   117         ext_bootrom_read_word, unmapped_write_long, 
   118         ext_bootrom_read_byte, unmapped_write_long, 
   119         ext_bootrom_read_burst, unmapped_write_burst }; 
   121 /********************* The Flash RAM address space **********************/
   122 static int32_t FASTCALL ext_flashram_read_long( sh4addr_t addr )
   123 {
   124     return *((int32_t *)(dc_flash_ram + (addr&0x0001FFFF)));
   125 }
   126 static int32_t FASTCALL ext_flashram_read_word( sh4addr_t addr )
   127 {
   128     return SIGNEXT16(*((int16_t *)(dc_flash_ram + (addr&0x0001FFFF))));
   129 }
   130 static int32_t FASTCALL ext_flashram_read_byte( sh4addr_t addr )
   131 {
   132     return SIGNEXT8(*((int16_t *)(dc_flash_ram + (addr&0x0001FFFF))));
   133 }
   134 static void FASTCALL ext_flashram_write_long( sh4addr_t addr, uint32_t val )
   135 {
   136     *(uint32_t *)(dc_flash_ram + (addr&0x0001FFFF)) = val;
   137     asic_g2_write_word();
   138 }
   139 static void FASTCALL ext_flashram_write_word( sh4addr_t addr, uint32_t val )
   140 {
   141     *(uint16_t *)(dc_flash_ram + (addr&0x0001FFFF)) = (uint16_t)val;
   142     asic_g2_write_word();
   143 }
   144 static void FASTCALL ext_flashram_write_byte( sh4addr_t addr, uint32_t val )
   145 {
   146     *(uint8_t *)(dc_flash_ram + (addr&0x0001FFFF)) = (uint8_t)val;
   147     asic_g2_write_word();
   148 }
   149 static void FASTCALL ext_flashram_read_burst( unsigned char *dest, sh4addr_t addr )
   150 {
   151     memcpy( dest, dc_flash_ram+(addr&0x0001FFFF), 32 );
   152 }
   153 static void FASTCALL ext_flashram_write_burst( sh4addr_t addr, unsigned char *src )
   154 {
   155     memcpy( dc_flash_ram+(addr&0x0001FFFF), src, 32 );
   156 }
   158 struct mem_region_fn mem_region_flashram = { ext_flashram_read_long, ext_flashram_write_long, 
   159         ext_flashram_read_word, ext_flashram_write_word, 
   160         ext_flashram_read_byte, ext_flashram_write_byte, 
   161         ext_flashram_read_burst, ext_flashram_write_burst }; 
   163 /***************************** P4 Regions ************************************/
   165 /* Store-queue (long-write only?) */
   166 static void FASTCALL p4_storequeue_write_long( sh4addr_t addr, uint32_t val )
   167 {
   168     sh4r.store_queue[(addr>>2)&0xF] = val;
   169 }
   170 static int32_t FASTCALL p4_storequeue_read_long( sh4addr_t addr )
   171 {
   172     return sh4r.store_queue[(addr>>2)&0xF];
   173 }
   175 struct mem_region_fn p4_region_storequeue = { 
   176         p4_storequeue_read_long, p4_storequeue_write_long,
   177         p4_storequeue_read_long, p4_storequeue_write_long,
   178         p4_storequeue_read_long, p4_storequeue_write_long,
   179         unmapped_read_burst, unmapped_write_burst }; // No burst access.
   181 /* TLB access */
   182 struct mem_region_fn p4_region_itlb_addr = {
   183         mmu_itlb_addr_read, mmu_itlb_addr_write,
   184         mmu_itlb_addr_read, mmu_itlb_addr_write,
   185         mmu_itlb_addr_read, mmu_itlb_addr_write,
   186         unmapped_read_burst, unmapped_write_burst };
   187 struct mem_region_fn p4_region_itlb_data = {
   188         mmu_itlb_data_read, mmu_itlb_data_write,
   189         mmu_itlb_data_read, mmu_itlb_data_write,
   190         mmu_itlb_data_read, mmu_itlb_data_write,
   191         unmapped_read_burst, unmapped_write_burst };
   192 struct mem_region_fn p4_region_utlb_addr = {
   193         mmu_utlb_addr_read, mmu_utlb_addr_write,
   194         mmu_utlb_addr_read, mmu_utlb_addr_write,
   195         mmu_utlb_addr_read, mmu_utlb_addr_write,
   196         unmapped_read_burst, unmapped_write_burst };
   197 struct mem_region_fn p4_region_utlb_data = {
   198         mmu_utlb_data_read, mmu_utlb_data_write,
   199         mmu_utlb_data_read, mmu_utlb_data_write,
   200         mmu_utlb_data_read, mmu_utlb_data_write,
   201         unmapped_read_burst, unmapped_write_burst };
   203 /********************** Initialization *************************/
   205 mem_region_fn_t *sh4_address_space;
   207 static void sh4_register_mem_region( uint32_t start, uint32_t end, mem_region_fn_t fn )
   208 {
   209     int count = (end - start) >> 12;
   210     mem_region_fn_t *ptr = &sh4_address_space[start>>12];
   211     while( count-- > 0 ) {
   212         *ptr++ = fn;
   213     }
   214 }
   216 static gboolean sh4_ext_page_remapped( sh4addr_t page, mem_region_fn_t fn, void *user_data )
   217 {
   218     int i;
   219     for( i=0; i<= 0xC0000000; i+= 0x20000000 ) {
   220         sh4_address_space[(page|i)>>12] = fn;
   221     }
   222 }
   225 void sh4_mem_init()
   226 {
   227     int i;
   228     mem_region_fn_t *ptr;
   229     sh4_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 256 );
   230     for( i=0, ptr = sh4_address_space; i<7; i++, ptr += LXDREAM_PAGE_TABLE_ENTRIES ) {
   231         memcpy( ptr, ext_address_space, sizeof(mem_region_fn_t) * LXDREAM_PAGE_TABLE_ENTRIES );
   232     }
   234     /* Setup main P4 regions */
   235     sh4_register_mem_region( 0xE0000000, 0xE4000000, &p4_region_storequeue );
   236     sh4_register_mem_region( 0xE4000000, 0xF0000000, &mem_region_unmapped );
   237     sh4_register_mem_region( 0xF0000000, 0xF1000000, &p4_region_icache_addr );
   238     sh4_register_mem_region( 0xF1000000, 0xF2000000, &p4_region_icache_data );
   239     sh4_register_mem_region( 0xF2000000, 0xF3000000, &p4_region_itlb_addr );
   240     sh4_register_mem_region( 0xF3000000, 0xF4000000, &p4_region_itlb_data );
   241     sh4_register_mem_region( 0xF4000000, 0xF5000000, &p4_region_ocache_addr );
   242     sh4_register_mem_region( 0xF5000000, 0xF6000000, &p4_region_ocache_data );
   243     sh4_register_mem_region( 0xF6000000, 0xF7000000, &p4_region_utlb_addr );
   244     sh4_register_mem_region( 0xF7000000, 0xF8000000, &p4_region_utlb_data );
   245     sh4_register_mem_region( 0xF8000000, 0x00000000, &mem_region_unmapped );
   247     /* Setup P4 control region */
   248     sh4_register_mem_region( 0xFF000000, 0xFF001000, &mmio_region_MMU.fn );
   249     sh4_register_mem_region( 0xFF100000, 0xFF101000, &mmio_region_PMM.fn );
   250     sh4_register_mem_region( 0xFF200000, 0xFF201000, &mmio_region_UBC.fn );
   251     sh4_register_mem_region( 0xFF800000, 0xFF801000, &mmio_region_BSC.fn );
   252     sh4_register_mem_region( 0xFF900000, 0xFFA00000, &mem_region_unmapped ); // SDMR2 + SDMR3
   253     sh4_register_mem_region( 0xFFA00000, 0xFFA01000, &mmio_region_DMAC.fn );
   254     sh4_register_mem_region( 0xFFC00000, 0xFFC01000, &mmio_region_CPG.fn );
   255     sh4_register_mem_region( 0xFFC80000, 0xFFC81000, &mmio_region_RTC.fn );
   256     sh4_register_mem_region( 0xFFD00000, 0xFFD01000, &mmio_region_INTC.fn );
   257     sh4_register_mem_region( 0xFFD80000, 0xFFD81000, &mmio_region_TMU.fn );
   258     sh4_register_mem_region( 0xFFE00000, 0xFFE01000, &mmio_region_SCI.fn );
   259     sh4_register_mem_region( 0xFFE80000, 0xFFE81000, &mmio_region_SCIF.fn );
   260     sh4_register_mem_region( 0xFFF00000, 0xFFF01000, &mem_region_unmapped ); // H-UDI
   262     register_mem_page_remapped_hook( sh4_ext_page_remapped, NULL );
   263 }
   265 /************** Access methods ***************/
   266 #ifdef HAVE_FRAME_ADDRESS
   267 #define RETURN_VIA(exc) do{ *(((void **)__builtin_frame_address(0))+1) = exc; return; } while(0)
   268 #else
   269 #define RETURN_VIA(exc) return NULL
   270 #endif
   273 int32_t FASTCALL sh4_read_long( sh4addr_t addr )
   274 {
   275     return sh4_address_space[addr>>12]->read_long(addr);
   276 }
   278 int32_t FASTCALL sh4_read_word( sh4addr_t addr )
   279 {
   280     return sh4_address_space[addr>>12]->read_word(addr);
   281 }
   283 int32_t FASTCALL sh4_read_byte( sh4addr_t addr )
   284 {
   285     return sh4_address_space[addr>>12]->read_byte(addr);
   286 }
   288 void FASTCALL sh4_write_long( sh4addr_t addr, uint32_t val )
   289 {
   290     sh4_address_space[addr>>12]->write_long(addr, val);
   291 }
   293 void FASTCALL sh4_write_word( sh4addr_t addr, uint32_t val )
   294 {
   295     sh4_address_space[addr>>12]->write_word(addr,val);
   296 }
   298 void FASTCALL sh4_write_byte( sh4addr_t addr, uint32_t val )
   299 {
   300     sh4_address_space[addr>>12]->write_byte(addr, val);
   301 }
   303 /* FIXME: Handle all the many special cases when the range doesn't fall cleanly
   304  * into the same memory block
   305  */
   306 void mem_copy_from_sh4( sh4ptr_t dest, sh4addr_t srcaddr, size_t count ) {
   307     if( srcaddr >= 0x04000000 && srcaddr < 0x05000000 ) {
   308         pvr2_vram64_read( dest, srcaddr, count );
   309     } else {
   310         sh4ptr_t src = mem_get_region(srcaddr);
   311         if( src == NULL ) {
   312             WARN( "Attempted block read from unknown address %08X", srcaddr );
   313         } else {
   314             memcpy( dest, src, count );
   315         }
   316     }
   317 }
   319 void mem_copy_to_sh4( sh4addr_t destaddr, sh4ptr_t src, size_t count ) {
   320     if( destaddr >= 0x10000000 && destaddr < 0x14000000 ) {
   321         pvr2_dma_write( destaddr, src, count );
   322         return;
   323     } else if( (destaddr & 0x1F800000) == 0x05000000 ) {
   324         pvr2_render_buffer_invalidate( destaddr, TRUE );
   325     } else if( (destaddr & 0x1F800000) == 0x04000000 ) {
   326         pvr2_vram64_write( destaddr, src, count );
   327         return;
   328     }
   329     sh4ptr_t dest = mem_get_region(destaddr);
   330     if( dest == NULL )
   331         WARN( "Attempted block write to unknown address %08X", destaddr );
   332     else {
   333         xlat_invalidate_block( destaddr, count );
   334         memcpy( dest, src, count );
   335     }
   336 }
.