Search
lxdream.org :: lxdream/src/sh4/sh4mem.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4mem.c
changeset 934:3acd3b3ee6d1
prev933:880c37bb1909
next939:6f2302afeb89
author nkeynes
date Sat Dec 27 02:59:35 2008 +0000 (15 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change Replace fpscr_mask/fpscr flags in xlat_cache_block with a single xlat_sh4_mode,
which tracks the field of the same name in sh4r - actually a little faster this way.
Now depends on SR.MD, FPSCR.PR and FPSCR.SZ (although it doesn't benefit from the SR
flag yet).

Also fixed the failure to check the flags in the common case (code address returned
by previous block) which took away the performance benefits, but oh well.
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 *)(dc_main_ram + (addr&0x00FFFFFF)));
    55 }
    56 static int32_t FASTCALL ext_sdram_read_word( sh4addr_t addr )
    57 {
    58     return SIGNEXT16(*((int16_t *)(dc_main_ram + (addr&0x00FFFFFF))));
    59 }
    60 static int32_t FASTCALL ext_sdram_read_byte( sh4addr_t addr )
    61 {
    62     return SIGNEXT8(*((int16_t *)(dc_main_ram + (addr&0x00FFFFFF))));
    63 }
    64 static void FASTCALL ext_sdram_write_long( sh4addr_t addr, uint32_t val )
    65 {
    66     *(uint32_t *)(dc_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 *)(dc_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 *)(dc_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, dc_main_ram+(addr&0x00FFFFFF), 32 );
    82 }
    83 static void FASTCALL ext_sdram_write_burst( sh4addr_t addr, unsigned char *src )
    84 {
    85     memcpy( dc_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 /***************************** P4 Regions ************************************/
    96 /* Store-queue (long-write only?) */
    97 static void FASTCALL p4_storequeue_write_long( sh4addr_t addr, uint32_t val )
    98 {
    99     sh4r.store_queue[(addr>>2)&0xF] = val;
   100 }
   101 static int32_t FASTCALL p4_storequeue_read_long( sh4addr_t addr )
   102 {
   103     return sh4r.store_queue[(addr>>2)&0xF];
   104 }
   106 struct mem_region_fn p4_region_storequeue = { 
   107         p4_storequeue_read_long, p4_storequeue_write_long,
   108         p4_storequeue_read_long, p4_storequeue_write_long,
   109         p4_storequeue_read_long, p4_storequeue_write_long,
   110         unmapped_read_burst, unmapped_write_burst }; // No burst access.
   112 /* TLB access */
   113 struct mem_region_fn p4_region_itlb_addr = {
   114         mmu_itlb_addr_read, mmu_itlb_addr_write,
   115         mmu_itlb_addr_read, mmu_itlb_addr_write,
   116         mmu_itlb_addr_read, mmu_itlb_addr_write,
   117         unmapped_read_burst, unmapped_write_burst };
   118 struct mem_region_fn p4_region_itlb_data = {
   119         mmu_itlb_data_read, mmu_itlb_data_write,
   120         mmu_itlb_data_read, mmu_itlb_data_write,
   121         mmu_itlb_data_read, mmu_itlb_data_write,
   122         unmapped_read_burst, unmapped_write_burst };
   123 struct mem_region_fn p4_region_utlb_addr = {
   124         mmu_utlb_addr_read, mmu_utlb_addr_write,
   125         mmu_utlb_addr_read, mmu_utlb_addr_write,
   126         mmu_utlb_addr_read, mmu_utlb_addr_write,
   127         unmapped_read_burst, unmapped_write_burst };
   128 struct mem_region_fn p4_region_utlb_data = {
   129         mmu_utlb_data_read, mmu_utlb_data_write,
   130         mmu_utlb_data_read, mmu_utlb_data_write,
   131         mmu_utlb_data_read, mmu_utlb_data_write,
   132         unmapped_read_burst, unmapped_write_burst };
   134 /********************** Initialization *************************/
   136 mem_region_fn_t *sh4_address_space;
   138 static void sh4_register_mem_region( uint32_t start, uint32_t end, mem_region_fn_t fn )
   139 {
   140     int count = (end - start) >> 12;
   141     mem_region_fn_t *ptr = &sh4_address_space[start>>12];
   142     while( count-- > 0 ) {
   143         *ptr++ = fn;
   144     }
   145 }
   147 static gboolean sh4_ext_page_remapped( sh4addr_t page, mem_region_fn_t fn, void *user_data )
   148 {
   149     int i;
   150     for( i=0; i<= 0xC0000000; i+= 0x20000000 ) {
   151         sh4_address_space[(page|i)>>12] = fn;
   152     }
   153 }
   156 void sh4_mem_init()
   157 {
   158     int i;
   159     mem_region_fn_t *ptr;
   160     sh4_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 256 );
   161     for( i=0, ptr = sh4_address_space; i<7; i++, ptr += LXDREAM_PAGE_TABLE_ENTRIES ) {
   162         memcpy( ptr, ext_address_space, sizeof(mem_region_fn_t) * LXDREAM_PAGE_TABLE_ENTRIES );
   163     }
   165     /* Setup main P4 regions */
   166     sh4_register_mem_region( 0xE0000000, 0xE4000000, &p4_region_storequeue );
   167     sh4_register_mem_region( 0xE4000000, 0xF0000000, &mem_region_unmapped );
   168     sh4_register_mem_region( 0xF0000000, 0xF1000000, &p4_region_icache_addr );
   169     sh4_register_mem_region( 0xF1000000, 0xF2000000, &p4_region_icache_data );
   170     sh4_register_mem_region( 0xF2000000, 0xF3000000, &p4_region_itlb_addr );
   171     sh4_register_mem_region( 0xF3000000, 0xF4000000, &p4_region_itlb_data );
   172     sh4_register_mem_region( 0xF4000000, 0xF5000000, &p4_region_ocache_addr );
   173     sh4_register_mem_region( 0xF5000000, 0xF6000000, &p4_region_ocache_data );
   174     sh4_register_mem_region( 0xF6000000, 0xF7000000, &p4_region_utlb_addr );
   175     sh4_register_mem_region( 0xF7000000, 0xF8000000, &p4_region_utlb_data );
   176     sh4_register_mem_region( 0xF8000000, 0x00000000, &mem_region_unmapped );
   178     /* Setup P4 control region */
   179     sh4_register_mem_region( 0xFF000000, 0xFF001000, &mmio_region_MMU.fn );
   180     sh4_register_mem_region( 0xFF100000, 0xFF101000, &mmio_region_PMM.fn );
   181     sh4_register_mem_region( 0xFF200000, 0xFF201000, &mmio_region_UBC.fn );
   182     sh4_register_mem_region( 0xFF800000, 0xFF801000, &mmio_region_BSC.fn );
   183     sh4_register_mem_region( 0xFF900000, 0xFFA00000, &mem_region_unmapped ); // SDMR2 + SDMR3
   184     sh4_register_mem_region( 0xFFA00000, 0xFFA01000, &mmio_region_DMAC.fn );
   185     sh4_register_mem_region( 0xFFC00000, 0xFFC01000, &mmio_region_CPG.fn );
   186     sh4_register_mem_region( 0xFFC80000, 0xFFC81000, &mmio_region_RTC.fn );
   187     sh4_register_mem_region( 0xFFD00000, 0xFFD01000, &mmio_region_INTC.fn );
   188     sh4_register_mem_region( 0xFFD80000, 0xFFD81000, &mmio_region_TMU.fn );
   189     sh4_register_mem_region( 0xFFE00000, 0xFFE01000, &mmio_region_SCI.fn );
   190     sh4_register_mem_region( 0xFFE80000, 0xFFE81000, &mmio_region_SCIF.fn );
   191     sh4_register_mem_region( 0xFFF00000, 0xFFF01000, &mem_region_unmapped ); // H-UDI
   193     register_mem_page_remapped_hook( sh4_ext_page_remapped, NULL );
   194 }
   196 /************** Access methods ***************/
   197 #ifdef HAVE_FRAME_ADDRESS
   198 #define RETURN_VIA(exc) do{ *(((void **)__builtin_frame_address(0))+1) = exc; return; } while(0)
   199 #else
   200 #define RETURN_VIA(exc) return NULL
   201 #endif
   204 int32_t FASTCALL sh4_read_long( sh4addr_t addr )
   205 {
   206     return sh4_address_space[addr>>12]->read_long(addr);
   207 }
   209 int32_t FASTCALL sh4_read_word( sh4addr_t addr )
   210 {
   211     return sh4_address_space[addr>>12]->read_word(addr);
   212 }
   214 int32_t FASTCALL sh4_read_byte( sh4addr_t addr )
   215 {
   216     return sh4_address_space[addr>>12]->read_byte(addr);
   217 }
   219 void FASTCALL sh4_write_long( sh4addr_t addr, uint32_t val )
   220 {
   221     sh4_address_space[addr>>12]->write_long(addr, val);
   222 }
   224 void FASTCALL sh4_write_word( sh4addr_t addr, uint32_t val )
   225 {
   226     sh4_address_space[addr>>12]->write_word(addr,val);
   227 }
   229 void FASTCALL sh4_write_byte( sh4addr_t addr, uint32_t val )
   230 {
   231     sh4_address_space[addr>>12]->write_byte(addr, val);
   232 }
   234 /* FIXME: Handle all the many special cases when the range doesn't fall cleanly
   235  * into the same memory block
   236  */
   237 void mem_copy_from_sh4( sh4ptr_t dest, sh4addr_t srcaddr, size_t count ) {
   238     if( srcaddr >= 0x04000000 && srcaddr < 0x05000000 ) {
   239         pvr2_vram64_read( dest, srcaddr, count );
   240     } else {
   241         sh4ptr_t src = mem_get_region(srcaddr);
   242         if( src == NULL ) {
   243             WARN( "Attempted block read from unknown address %08X", srcaddr );
   244         } else {
   245             memcpy( dest, src, count );
   246         }
   247     }
   248 }
   250 void mem_copy_to_sh4( sh4addr_t destaddr, sh4ptr_t src, size_t count ) {
   251     if( destaddr >= 0x10000000 && destaddr < 0x14000000 ) {
   252         pvr2_dma_write( destaddr, src, count );
   253         return;
   254     } else if( (destaddr & 0x1F800000) == 0x05000000 ) {
   255         pvr2_render_buffer_invalidate( destaddr, TRUE );
   256     } else if( (destaddr & 0x1F800000) == 0x04000000 ) {
   257         pvr2_vram64_write( destaddr, src, count );
   258         return;
   259     }
   260     sh4ptr_t dest = mem_get_region(destaddr);
   261     if( dest == NULL )
   262         WARN( "Attempted block write to unknown address %08X", destaddr );
   263     else {
   264         xlat_invalidate_block( destaddr, count );
   265         memcpy( dest, src, count );
   266     }
   267 }
.