Search
lxdream.org :: lxdream/src/sh4/sh4mem.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4mem.c
changeset 931:430048ea8b71
prev930:07e5b11419db
next933:880c37bb1909
author nkeynes
date Wed Dec 24 06:05:42 2008 +0000 (15 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change Fix save-states (don't attempt to load/save non-existent regions)
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 /********************* 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 /* Cache access */
   182 struct mem_region_fn p4_region_icache_addr = {
   183         mmu_icache_addr_read, mmu_icache_addr_write,
   184         mmu_icache_addr_read, mmu_icache_addr_write,
   185         mmu_icache_addr_read, mmu_icache_addr_write,
   186         unmapped_read_burst, unmapped_write_burst };
   187 struct mem_region_fn p4_region_icache_data = {
   188         mmu_icache_data_read, mmu_icache_data_write,
   189         mmu_icache_data_read, mmu_icache_data_write,
   190         mmu_icache_data_read, mmu_icache_data_write,
   191         unmapped_read_burst, unmapped_write_burst };
   192 struct mem_region_fn p4_region_ocache_addr = {
   193         mmu_ocache_addr_read, mmu_ocache_addr_write,
   194         mmu_ocache_addr_read, mmu_ocache_addr_write,
   195         mmu_ocache_addr_read, mmu_ocache_addr_write,
   196         unmapped_read_burst, unmapped_write_burst };
   197 struct mem_region_fn p4_region_ocache_data = {
   198         mmu_ocache_data_read, mmu_ocache_data_write,
   199         mmu_ocache_data_read, mmu_ocache_data_write,
   200         mmu_ocache_data_read, mmu_ocache_data_write,
   201         unmapped_read_burst, unmapped_write_burst };
   203 /* TLB access */
   204 struct mem_region_fn p4_region_itlb_addr = {
   205         mmu_itlb_addr_read, mmu_itlb_addr_write,
   206         mmu_itlb_addr_read, mmu_itlb_addr_write,
   207         mmu_itlb_addr_read, mmu_itlb_addr_write,
   208         unmapped_read_burst, unmapped_write_burst };
   209 struct mem_region_fn p4_region_itlb_data = {
   210         mmu_itlb_data_read, mmu_itlb_data_write,
   211         mmu_itlb_data_read, mmu_itlb_data_write,
   212         mmu_itlb_data_read, mmu_itlb_data_write,
   213         unmapped_read_burst, unmapped_write_burst };
   214 struct mem_region_fn p4_region_utlb_addr = {
   215         mmu_utlb_addr_read, mmu_utlb_addr_write,
   216         mmu_utlb_addr_read, mmu_utlb_addr_write,
   217         mmu_utlb_addr_read, mmu_utlb_addr_write,
   218         unmapped_read_burst, unmapped_write_burst };
   219 struct mem_region_fn p4_region_utlb_data = {
   220         mmu_utlb_data_read, mmu_utlb_data_write,
   221         mmu_utlb_data_read, mmu_utlb_data_write,
   222         mmu_utlb_data_read, mmu_utlb_data_write,
   223         unmapped_read_burst, unmapped_write_burst };
   225 /********************** Initialization *************************/
   227 mem_region_fn_t *sh4_address_space;
   229 static void sh4_register_mem_region( uint32_t start, uint32_t end, mem_region_fn_t fn )
   230 {
   231     int count = (end - start) >> 12;
   232     mem_region_fn_t *ptr = &sh4_address_space[start>>12];
   233     while( count-- > 0 ) {
   234         *ptr++ = fn;
   235     }
   236 }
   238 static gboolean sh4_ext_page_remapped( sh4addr_t page, mem_region_fn_t fn, void *user_data )
   239 {
   240     int i;
   241     for( i=0; i<= 0xC0000000; i+= 0x20000000 ) {
   242         sh4_address_space[(page|i)>>12] = fn;
   243     }
   244 }
   247 void sh4_mem_init()
   248 {
   249     int i;
   250     mem_region_fn_t *ptr;
   251     sh4_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 256 );
   252     for( i=0, ptr = sh4_address_space; i<7; i++, ptr += LXDREAM_PAGE_TABLE_ENTRIES ) {
   253         memcpy( ptr, ext_address_space, sizeof(mem_region_fn_t) * LXDREAM_PAGE_TABLE_ENTRIES );
   254     }
   256     /* Setup main P4 regions */
   257     sh4_register_mem_region( 0xE0000000, 0xE4000000, &p4_region_storequeue );
   258     sh4_register_mem_region( 0xE4000000, 0xF0000000, &mem_region_unmapped );
   259     sh4_register_mem_region( 0xF0000000, 0xF1000000, &p4_region_icache_addr );
   260     sh4_register_mem_region( 0xF1000000, 0xF2000000, &p4_region_icache_data );
   261     sh4_register_mem_region( 0xF2000000, 0xF3000000, &p4_region_itlb_addr );
   262     sh4_register_mem_region( 0xF3000000, 0xF4000000, &p4_region_itlb_data );
   263     sh4_register_mem_region( 0xF4000000, 0xF5000000, &p4_region_ocache_addr );
   264     sh4_register_mem_region( 0xF5000000, 0xF6000000, &p4_region_ocache_data );
   265     sh4_register_mem_region( 0xF6000000, 0xF7000000, &p4_region_utlb_addr );
   266     sh4_register_mem_region( 0xF7000000, 0xF8000000, &p4_region_utlb_data );
   267     sh4_register_mem_region( 0xF8000000, 0x00000000, &mem_region_unmapped );
   269     /* Setup P4 control region */
   270     sh4_register_mem_region( 0xFF000000, 0xFF001000, &mmio_region_MMU.fn );
   271     sh4_register_mem_region( 0xFF100000, 0xFF101000, &mmio_region_PMM.fn );
   272     sh4_register_mem_region( 0xFF200000, 0xFF201000, &mmio_region_UBC.fn );
   273     sh4_register_mem_region( 0xFF800000, 0xFF801000, &mmio_region_BSC.fn );
   274     sh4_register_mem_region( 0xFF900000, 0xFFA00000, &mem_region_unmapped ); // SDMR2 + SDMR3
   275     sh4_register_mem_region( 0xFFA00000, 0xFFA01000, &mmio_region_DMAC.fn );
   276     sh4_register_mem_region( 0xFFC00000, 0xFFC01000, &mmio_region_CPG.fn );
   277     sh4_register_mem_region( 0xFFC80000, 0xFFC81000, &mmio_region_RTC.fn );
   278     sh4_register_mem_region( 0xFFD00000, 0xFFD01000, &mmio_region_INTC.fn );
   279     sh4_register_mem_region( 0xFFD80000, 0xFFD81000, &mmio_region_TMU.fn );
   280     sh4_register_mem_region( 0xFFE00000, 0xFFE01000, &mmio_region_SCI.fn );
   281     sh4_register_mem_region( 0xFFE80000, 0xFFE81000, &mmio_region_SCIF.fn );
   282     sh4_register_mem_region( 0xFFF00000, 0xFFF01000, &mem_region_unmapped ); // H-UDI
   284     register_mem_page_remapped_hook( sh4_ext_page_remapped, NULL );
   285 }
   287 /************** Access methods ***************/
   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
   295 int32_t FASTCALL sh4_read_long( sh4addr_t addr )
   296 {
   297     return sh4_address_space[addr>>12]->read_long(addr);
   298 }
   300 int32_t FASTCALL sh4_read_word( sh4addr_t addr )
   301 {
   302     return sh4_address_space[addr>>12]->read_word(addr);
   303 }
   305 int32_t FASTCALL sh4_read_byte( sh4addr_t addr )
   306 {
   307     return sh4_address_space[addr>>12]->read_byte(addr);
   308 }
   310 void FASTCALL sh4_write_long( sh4addr_t addr, uint32_t val )
   311 {
   312     sh4_address_space[addr>>12]->write_long(addr, val);
   313 }
   315 void FASTCALL sh4_write_word( sh4addr_t addr, uint32_t val )
   316 {
   317     sh4_address_space[addr>>12]->write_word(addr,val);
   318 }
   320 void FASTCALL sh4_write_byte( sh4addr_t addr, uint32_t val )
   321 {
   322     sh4_address_space[addr>>12]->write_byte(addr, val);
   323 }
   325 /* FIXME: Handle all the many special cases when the range doesn't fall cleanly
   326  * into the same memory block
   327  */
   328 void mem_copy_from_sh4( sh4ptr_t dest, sh4addr_t srcaddr, size_t count ) {
   329     if( srcaddr >= 0x04000000 && srcaddr < 0x05000000 ) {
   330         pvr2_vram64_read( dest, srcaddr, count );
   331     } else {
   332         sh4ptr_t src = mem_get_region(srcaddr);
   333         if( src == NULL ) {
   334             WARN( "Attempted block read from unknown address %08X", srcaddr );
   335         } else {
   336             memcpy( dest, src, count );
   337         }
   338     }
   339 }
   341 void mem_copy_to_sh4( sh4addr_t destaddr, sh4ptr_t src, size_t count ) {
   342     if( destaddr >= 0x10000000 && destaddr < 0x14000000 ) {
   343         pvr2_dma_write( destaddr, src, count );
   344         return;
   345     } else if( (destaddr & 0x1F800000) == 0x05000000 ) {
   346         pvr2_render_buffer_invalidate( destaddr, TRUE );
   347     } else if( (destaddr & 0x1F800000) == 0x04000000 ) {
   348         pvr2_vram64_write( destaddr, src, count );
   349         return;
   350     }
   351     sh4ptr_t dest = mem_get_region(destaddr);
   352     if( dest == NULL )
   353         WARN( "Attempted block write to unknown address %08X", destaddr );
   354     else {
   355         xlat_invalidate_block( destaddr, count );
   356         memcpy( dest, src, count );
   357     }
   358 }
.