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 Tue Dec 23 05:48:05 2008 +0000 (12 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change More refactoring and general cleanup. Most things should be working again now.
Split off cache and start real implementation, breaking save states in the process
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 }
.