Search
lxdream.org :: lxdream/src/sh4/sh4mem.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4mem.c
changeset 930:07e5b11419db
prev929:fd8cb0c82f5f
next931:430048ea8b71
author nkeynes
date Mon Dec 22 09:51:11 2008 +0000 (12 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change Remove pointer cache and add full address-space map. Much better
file annotate diff log raw
nkeynes@10
     1
/**
nkeynes@586
     2
 * $Id$
nkeynes@929
     3
 * sh4mem.c is responsible for interfacing between the SH4's internal memory
nkeynes@10
     4
 *
nkeynes@10
     5
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@10
     6
 *
nkeynes@10
     7
 * This program is free software; you can redistribute it and/or modify
nkeynes@10
     8
 * it under the terms of the GNU General Public License as published by
nkeynes@10
     9
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@10
    10
 * (at your option) any later version.
nkeynes@10
    11
 *
nkeynes@10
    12
 * This program is distributed in the hope that it will be useful,
nkeynes@10
    13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@10
    14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@10
    15
 * GNU General Public License for more details.
nkeynes@10
    16
 */
nkeynes@10
    17
nkeynes@35
    18
#define MODULE sh4_module
nkeynes@35
    19
nkeynes@10
    20
#include <string.h>
nkeynes@10
    21
#include <zlib.h>
nkeynes@10
    22
#include "dream.h"
nkeynes@10
    23
#include "mem.h"
nkeynes@10
    24
#include "mmio.h"
nkeynes@10
    25
#include "dreamcast.h"
nkeynes@422
    26
#include "sh4/sh4core.h"
nkeynes@422
    27
#include "sh4/sh4mmio.h"
nkeynes@422
    28
#include "sh4/xltcache.h"
nkeynes@100
    29
#include "pvr2/pvr2.h"
nkeynes@10
    30
nkeynes@929
    31
/* System regions (probably should be defined elsewhere) */
nkeynes@929
    32
extern struct mem_region_fn mem_region_unmapped;
nkeynes@929
    33
extern struct mem_region_fn mem_region_sdram;
nkeynes@929
    34
extern struct mem_region_fn mem_region_vram32;
nkeynes@929
    35
extern struct mem_region_fn mem_region_vram64;
nkeynes@929
    36
extern struct mem_region_fn mem_region_audioram;
nkeynes@929
    37
extern struct mem_region_fn mem_region_flashram;
nkeynes@929
    38
extern struct mem_region_fn mem_region_bootrom;
nkeynes@10
    39
nkeynes@929
    40
/* On-chip regions other than defined MMIO regions */
nkeynes@929
    41
extern struct mem_region_fn mem_region_storequeue;
nkeynes@929
    42
extern struct mem_region_fn mem_region_icache_addr;
nkeynes@929
    43
extern struct mem_region_fn mem_region_icache_data;
nkeynes@929
    44
extern struct mem_region_fn mem_region_ocache_addr;
nkeynes@929
    45
extern struct mem_region_fn mem_region_ocache_data;
nkeynes@929
    46
extern struct mem_region_fn mem_region_itlb_addr;
nkeynes@929
    47
extern struct mem_region_fn mem_region_itlb_data;
nkeynes@929
    48
extern struct mem_region_fn mem_region_utlb_addr;
nkeynes@929
    49
extern struct mem_region_fn mem_region_utlb_data;
nkeynes@10
    50
nkeynes@929
    51
extern struct mmio_region *P4_io[];
nkeynes@929
    52
nkeynes@930
    53
mem_region_fn_t *sh4_address_space;
nkeynes@930
    54
nkeynes@929
    55
/********************* The "unmapped" address space ********************/
nkeynes@929
    56
/* Always reads as 0, writes have no effect */
nkeynes@929
    57
static int32_t FASTCALL unmapped_read_long( sh4addr_t addr )
nkeynes@929
    58
{
nkeynes@929
    59
    return 0;
nkeynes@929
    60
}
nkeynes@929
    61
static void FASTCALL unmapped_write_long( sh4addr_t addr, uint32_t val )
nkeynes@929
    62
{
nkeynes@929
    63
}
nkeynes@929
    64
static void FASTCALL unmapped_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@929
    65
{
nkeynes@929
    66
    memset( dest, 0, 32 );
nkeynes@929
    67
}
nkeynes@929
    68
static void FASTCALL unmapped_write_burst( sh4addr_t addr, unsigned char *src )
nkeynes@929
    69
{
nkeynes@929
    70
}
nkeynes@929
    71
nkeynes@929
    72
struct mem_region_fn mem_region_unmapped = { 
nkeynes@929
    73
        unmapped_read_long, unmapped_write_long, 
nkeynes@929
    74
        unmapped_read_long, unmapped_write_long, 
nkeynes@929
    75
        unmapped_read_long, unmapped_write_long, 
nkeynes@929
    76
        unmapped_read_burst, unmapped_write_burst }; 
nkeynes@929
    77
nkeynes@929
    78
/********************* Store-queue (long-write only?) ******************/
nkeynes@929
    79
static void FASTCALL p4_storequeue_write_long( sh4addr_t addr, uint32_t val )
nkeynes@929
    80
{
nkeynes@929
    81
    sh4r.store_queue[(addr>>2)&0xF] = val;
nkeynes@929
    82
}
nkeynes@929
    83
static int32_t FASTCALL p4_storequeue_read_long( sh4addr_t addr )
nkeynes@929
    84
{
nkeynes@929
    85
    return sh4r.store_queue[(addr>>2)&0xF];
nkeynes@929
    86
}
nkeynes@929
    87
struct mem_region_fn p4_region_storequeue = { 
nkeynes@929
    88
        p4_storequeue_read_long, p4_storequeue_write_long,
nkeynes@929
    89
        p4_storequeue_read_long, p4_storequeue_write_long,
nkeynes@929
    90
        p4_storequeue_read_long, p4_storequeue_write_long,
nkeynes@929
    91
        unmapped_read_burst, unmapped_write_burst }; // No burst access.
nkeynes@929
    92
nkeynes@929
    93
/********************* The main ram address space **********************/
nkeynes@929
    94
static int32_t FASTCALL ext_sdram_read_long( sh4addr_t addr )
nkeynes@929
    95
{
nkeynes@929
    96
    return *((int32_t *)(sh4_main_ram + (addr&0x00FFFFFF)));
nkeynes@929
    97
}
nkeynes@929
    98
static int32_t FASTCALL ext_sdram_read_word( sh4addr_t addr )
nkeynes@929
    99
{
nkeynes@929
   100
    return SIGNEXT16(*((int16_t *)(sh4_main_ram + (addr&0x00FFFFFF))));
nkeynes@929
   101
}
nkeynes@929
   102
static int32_t FASTCALL ext_sdram_read_byte( sh4addr_t addr )
nkeynes@929
   103
{
nkeynes@929
   104
    return SIGNEXT8(*((int16_t *)(sh4_main_ram + (addr&0x00FFFFFF))));
nkeynes@929
   105
}
nkeynes@929
   106
static void FASTCALL ext_sdram_write_long( sh4addr_t addr, uint32_t val )
nkeynes@929
   107
{
nkeynes@929
   108
    *(uint32_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = val;
nkeynes@929
   109
    xlat_invalidate_long(addr);
nkeynes@929
   110
}
nkeynes@929
   111
static void FASTCALL ext_sdram_write_word( sh4addr_t addr, uint32_t val )
nkeynes@929
   112
{
nkeynes@929
   113
    *(uint16_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = (uint16_t)val;
nkeynes@929
   114
    xlat_invalidate_word(addr);
nkeynes@929
   115
}
nkeynes@929
   116
static void FASTCALL ext_sdram_write_byte( sh4addr_t addr, uint32_t val )
nkeynes@929
   117
{
nkeynes@929
   118
    *(uint8_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = (uint8_t)val;
nkeynes@929
   119
    xlat_invalidate_word(addr);
nkeynes@929
   120
}
nkeynes@929
   121
static void FASTCALL ext_sdram_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@929
   122
{
nkeynes@929
   123
    memcpy( dest, sh4_main_ram+(addr&0x00FFFFFF), 32 );
nkeynes@929
   124
}
nkeynes@929
   125
static void FASTCALL ext_sdram_write_burst( sh4addr_t addr, unsigned char *src )
nkeynes@929
   126
{
nkeynes@929
   127
    memcpy( sh4_main_ram+(addr&0x00FFFFFF), src, 32 );
nkeynes@929
   128
}
nkeynes@929
   129
nkeynes@929
   130
struct mem_region_fn mem_region_sdram = { ext_sdram_read_long, ext_sdram_write_long, 
nkeynes@929
   131
        ext_sdram_read_word, ext_sdram_write_word, 
nkeynes@929
   132
        ext_sdram_read_byte, ext_sdram_write_byte, 
nkeynes@929
   133
        ext_sdram_read_burst, ext_sdram_write_burst }; 
nkeynes@929
   134
nkeynes@929
   135
nkeynes@929
   136
/********************* The Boot ROM address space **********************/
nkeynes@929
   137
extern sh4ptr_t dc_boot_rom;
nkeynes@929
   138
extern sh4ptr_t dc_flash_ram;
nkeynes@929
   139
extern sh4ptr_t dc_audio_ram;
nkeynes@929
   140
static int32_t FASTCALL ext_bootrom_read_long( sh4addr_t addr )
nkeynes@929
   141
{
nkeynes@929
   142
    return *((int32_t *)(dc_boot_rom + (addr&0x001FFFFF)));
nkeynes@929
   143
}
nkeynes@929
   144
static int32_t FASTCALL ext_bootrom_read_word( sh4addr_t addr )
nkeynes@929
   145
{
nkeynes@929
   146
    return SIGNEXT16(*((int16_t *)(dc_boot_rom + (addr&0x001FFFFF))));
nkeynes@929
   147
}
nkeynes@929
   148
static int32_t FASTCALL ext_bootrom_read_byte( sh4addr_t addr )
nkeynes@929
   149
{
nkeynes@929
   150
    return SIGNEXT8(*((int16_t *)(dc_boot_rom + (addr&0x001FFFFF))));
nkeynes@929
   151
}
nkeynes@929
   152
static void FASTCALL ext_bootrom_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@929
   153
{
nkeynes@929
   154
    memcpy( dest, sh4_main_ram+(addr&0x001FFFFF), 32 );
nkeynes@929
   155
}
nkeynes@929
   156
nkeynes@929
   157
struct mem_region_fn mem_region_bootrom = { 
nkeynes@929
   158
        ext_bootrom_read_long, unmapped_write_long, 
nkeynes@929
   159
        ext_bootrom_read_word, unmapped_write_long, 
nkeynes@929
   160
        ext_bootrom_read_byte, unmapped_write_long, 
nkeynes@929
   161
        ext_bootrom_read_burst, unmapped_write_burst }; 
nkeynes@929
   162
nkeynes@929
   163
/********************* The Audio RAM address space **********************/
nkeynes@929
   164
static int32_t FASTCALL ext_audioram_read_long( sh4addr_t addr )
nkeynes@929
   165
{
nkeynes@929
   166
    return *((int32_t *)(dc_audio_ram + (addr&0x001FFFFF)));
nkeynes@929
   167
}
nkeynes@929
   168
static int32_t FASTCALL ext_audioram_read_word( sh4addr_t addr )
nkeynes@929
   169
{
nkeynes@929
   170
    return SIGNEXT16(*((int16_t *)(dc_audio_ram + (addr&0x001FFFFF))));
nkeynes@929
   171
}
nkeynes@929
   172
static int32_t FASTCALL ext_audioram_read_byte( sh4addr_t addr )
nkeynes@929
   173
{
nkeynes@929
   174
    return SIGNEXT8(*((int16_t *)(dc_audio_ram + (addr&0x001FFFFF))));
nkeynes@929
   175
}
nkeynes@929
   176
static void FASTCALL ext_audioram_write_long( sh4addr_t addr, uint32_t val )
nkeynes@929
   177
{
nkeynes@929
   178
    *(uint32_t *)(dc_audio_ram + (addr&0x001FFFFF)) = val;
nkeynes@929
   179
    asic_g2_write_word();
nkeynes@929
   180
}
nkeynes@929
   181
static void FASTCALL ext_audioram_write_word( sh4addr_t addr, uint32_t val )
nkeynes@929
   182
{
nkeynes@929
   183
    *(uint16_t *)(dc_audio_ram + (addr&0x001FFFFF)) = (uint16_t)val;
nkeynes@929
   184
    asic_g2_write_word();
nkeynes@929
   185
}
nkeynes@929
   186
static void FASTCALL ext_audioram_write_byte( sh4addr_t addr, uint32_t val )
nkeynes@929
   187
{
nkeynes@929
   188
    *(uint8_t *)(dc_audio_ram + (addr&0x001FFFFF)) = (uint8_t)val;
nkeynes@929
   189
    asic_g2_write_word();
nkeynes@929
   190
}
nkeynes@929
   191
static void FASTCALL ext_audioram_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@929
   192
{
nkeynes@929
   193
    memcpy( dest, dc_audio_ram+(addr&0x001FFFFF), 32 );
nkeynes@929
   194
}
nkeynes@929
   195
static void FASTCALL ext_audioram_write_burst( sh4addr_t addr, unsigned char *src )
nkeynes@929
   196
{
nkeynes@929
   197
    memcpy( dc_audio_ram+(addr&0x001FFFFF), src, 32 );
nkeynes@929
   198
}
nkeynes@929
   199
nkeynes@929
   200
struct mem_region_fn mem_region_audioram = { ext_audioram_read_long, ext_audioram_write_long, 
nkeynes@929
   201
        ext_audioram_read_word, ext_audioram_write_word, 
nkeynes@929
   202
        ext_audioram_read_byte, ext_audioram_write_byte, 
nkeynes@929
   203
        ext_audioram_read_burst, ext_audioram_write_burst }; 
nkeynes@929
   204
nkeynes@929
   205
/********************* The Flash RAM address space **********************/
nkeynes@929
   206
static int32_t FASTCALL ext_flashram_read_long( sh4addr_t addr )
nkeynes@929
   207
{
nkeynes@929
   208
    return *((int32_t *)(dc_flash_ram + (addr&0x0001FFFF)));
nkeynes@929
   209
}
nkeynes@929
   210
static int32_t FASTCALL ext_flashram_read_word( sh4addr_t addr )
nkeynes@929
   211
{
nkeynes@929
   212
    return SIGNEXT16(*((int16_t *)(dc_flash_ram + (addr&0x0001FFFF))));
nkeynes@929
   213
}
nkeynes@929
   214
static int32_t FASTCALL ext_flashram_read_byte( sh4addr_t addr )
nkeynes@929
   215
{
nkeynes@929
   216
    return SIGNEXT8(*((int16_t *)(dc_flash_ram + (addr&0x0001FFFF))));
nkeynes@929
   217
}
nkeynes@929
   218
static void FASTCALL ext_flashram_write_long( sh4addr_t addr, uint32_t val )
nkeynes@929
   219
{
nkeynes@929
   220
    *(uint32_t *)(dc_flash_ram + (addr&0x0001FFFF)) = val;
nkeynes@929
   221
    asic_g2_write_word();
nkeynes@929
   222
}
nkeynes@929
   223
static void FASTCALL ext_flashram_write_word( sh4addr_t addr, uint32_t val )
nkeynes@929
   224
{
nkeynes@929
   225
    *(uint16_t *)(dc_flash_ram + (addr&0x0001FFFF)) = (uint16_t)val;
nkeynes@929
   226
    asic_g2_write_word();
nkeynes@929
   227
}
nkeynes@929
   228
static void FASTCALL ext_flashram_write_byte( sh4addr_t addr, uint32_t val )
nkeynes@929
   229
{
nkeynes@929
   230
    *(uint8_t *)(dc_flash_ram + (addr&0x0001FFFF)) = (uint8_t)val;
nkeynes@929
   231
    asic_g2_write_word();
nkeynes@929
   232
}
nkeynes@929
   233
static void FASTCALL ext_flashram_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@929
   234
{
nkeynes@929
   235
    memcpy( dest, dc_flash_ram+(addr&0x0001FFFF), 32 );
nkeynes@929
   236
}
nkeynes@929
   237
static void FASTCALL ext_flashram_write_burst( sh4addr_t addr, unsigned char *src )
nkeynes@929
   238
{
nkeynes@929
   239
    memcpy( dc_flash_ram+(addr&0x0001FFFF), src, 32 );
nkeynes@929
   240
}
nkeynes@929
   241
nkeynes@929
   242
struct mem_region_fn mem_region_flashram = { ext_flashram_read_long, ext_flashram_write_long, 
nkeynes@929
   243
        ext_flashram_read_word, ext_flashram_write_word, 
nkeynes@929
   244
        ext_flashram_read_byte, ext_flashram_write_byte, 
nkeynes@929
   245
        ext_flashram_read_burst, ext_flashram_write_burst }; 
nkeynes@929
   246
nkeynes@929
   247
/**************************************************************************/
nkeynes@929
   248
nkeynes@929
   249
struct mem_region_fn p4_region_icache_addr = {
nkeynes@929
   250
        mmu_icache_addr_read, mmu_icache_addr_write,
nkeynes@929
   251
        mmu_icache_addr_read, mmu_icache_addr_write,
nkeynes@929
   252
        mmu_icache_addr_read, mmu_icache_addr_write,
nkeynes@929
   253
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   254
struct mem_region_fn p4_region_icache_data = {
nkeynes@929
   255
        mmu_icache_data_read, mmu_icache_data_write,
nkeynes@929
   256
        mmu_icache_data_read, mmu_icache_data_write,
nkeynes@929
   257
        mmu_icache_data_read, mmu_icache_data_write,
nkeynes@929
   258
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   259
struct mem_region_fn p4_region_ocache_addr = {
nkeynes@929
   260
        mmu_ocache_addr_read, mmu_ocache_addr_write,
nkeynes@929
   261
        mmu_ocache_addr_read, mmu_ocache_addr_write,
nkeynes@929
   262
        mmu_ocache_addr_read, mmu_ocache_addr_write,
nkeynes@929
   263
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   264
struct mem_region_fn p4_region_ocache_data = {
nkeynes@929
   265
        mmu_ocache_data_read, mmu_ocache_data_write,
nkeynes@929
   266
        mmu_ocache_data_read, mmu_ocache_data_write,
nkeynes@929
   267
        mmu_ocache_data_read, mmu_ocache_data_write,
nkeynes@929
   268
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   269
struct mem_region_fn p4_region_itlb_addr = {
nkeynes@929
   270
        mmu_itlb_addr_read, mmu_itlb_addr_write,
nkeynes@929
   271
        mmu_itlb_addr_read, mmu_itlb_addr_write,
nkeynes@929
   272
        mmu_itlb_addr_read, mmu_itlb_addr_write,
nkeynes@929
   273
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   274
struct mem_region_fn p4_region_itlb_data = {
nkeynes@929
   275
        mmu_itlb_data_read, mmu_itlb_data_write,
nkeynes@929
   276
        mmu_itlb_data_read, mmu_itlb_data_write,
nkeynes@929
   277
        mmu_itlb_data_read, mmu_itlb_data_write,
nkeynes@929
   278
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   279
struct mem_region_fn p4_region_utlb_addr = {
nkeynes@929
   280
        mmu_utlb_addr_read, mmu_utlb_addr_write,
nkeynes@929
   281
        mmu_utlb_addr_read, mmu_utlb_addr_write,
nkeynes@929
   282
        mmu_utlb_addr_read, mmu_utlb_addr_write,
nkeynes@929
   283
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   284
struct mem_region_fn p4_region_utlb_data = {
nkeynes@929
   285
        mmu_utlb_data_read, mmu_utlb_data_write,
nkeynes@929
   286
        mmu_utlb_data_read, mmu_utlb_data_write,
nkeynes@929
   287
        mmu_utlb_data_read, mmu_utlb_data_write,
nkeynes@929
   288
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   289
nkeynes@929
   290
#ifdef HAVE_FRAME_ADDRESS
nkeynes@929
   291
#define RETURN_VIA(exc) do{ *(((void **)__builtin_frame_address(0))+1) = exc; return; } while(0)
nkeynes@10
   292
#else
nkeynes@929
   293
#define RETURN_VIA(exc) return NULL
nkeynes@10
   294
#endif
nkeynes@10
   295
nkeynes@929
   296
int decode_sdram = 0;
nkeynes@929
   297
mem_region_fn_t FASTCALL mem_decode_address( sh4addr_t addr )
nkeynes@10
   298
{
nkeynes@929
   299
    sh4ptr_t page;
nkeynes@929
   300
    switch( addr >> 26 ) { /* Area */
nkeynes@929
   301
    case 0: /* Holly multiplexed */
nkeynes@929
   302
        page = page_map[(addr&0x1FFFFFFF)>>12];
nkeynes@929
   303
        if( ((uintptr_t)page) < MAX_IO_REGIONS ) {
nkeynes@929
   304
            return &io_rgn[(uintptr_t)page]->fn;
nkeynes@929
   305
        } else if( addr < 0x00200000 ) {
nkeynes@929
   306
            return &mem_region_bootrom;
nkeynes@929
   307
        } else if( addr < 0x00400000 ) {
nkeynes@929
   308
            return &mem_region_flashram;
nkeynes@929
   309
        } else if( addr >= 0x00800000 && addr < 0x00A00000 ) {
nkeynes@929
   310
            return &mem_region_audioram;
nkeynes@282
   311
        }
nkeynes@929
   312
        break;
nkeynes@929
   313
    case 1: /* VRAM */
nkeynes@929
   314
        switch( addr >> 24 ) {
nkeynes@929
   315
        case 4: return &mem_region_vram64; /* 0x04xxxxxx */
nkeynes@929
   316
        case 5: return &mem_region_vram32; /* 0x05xxxxxx */ 
nkeynes@929
   317
        }    
nkeynes@929
   318
        break;
nkeynes@929
   319
    case 2: /* Unmapped */
nkeynes@929
   320
        break;
nkeynes@929
   321
    case 3: /* Main sdram */
nkeynes@929
   322
        decode_sdram++;
nkeynes@929
   323
        return &mem_region_sdram;
nkeynes@929
   324
    case 4: /* Holly burst-access only? */
nkeynes@929
   325
        break;
nkeynes@929
   326
    }
nkeynes@929
   327
    return &mem_region_unmapped;
nkeynes@10
   328
}
nkeynes@10
   329
nkeynes@929
   330
int decode_count = 0;
nkeynes@929
   331
int p4_count = 0;
nkeynes@929
   332
int sq_count = 0;
nkeynes@929
   333
nkeynes@929
   334
mem_region_fn_t FASTCALL sh7750_decode_address( sh4addr_t addr )
nkeynes@10
   335
{
nkeynes@929
   336
    decode_count++;
nkeynes@929
   337
    sh4addr_t region = addr >> 29;
nkeynes@929
   338
    switch( region ) {
nkeynes@929
   339
    case 7: /* P4 E0000000-FFFFFFFF - On-chip I/O */
nkeynes@929
   340
        if( addr < 0xE4000000 ) {
nkeynes@929
   341
            sq_count++;
nkeynes@929
   342
            return &p4_region_storequeue;
nkeynes@929
   343
        } else if( addr < 0xFC000000 ) { /* Control register region */
nkeynes@929
   344
            p4_count++;
nkeynes@929
   345
            switch( addr & 0x1F000000 ) {
nkeynes@929
   346
            case 0x10000000: return &p4_region_icache_addr;
nkeynes@929
   347
            case 0x11000000: return &p4_region_icache_data;
nkeynes@929
   348
            case 0x12000000: return &p4_region_itlb_addr;
nkeynes@929
   349
            case 0x13000000: return &p4_region_itlb_data;
nkeynes@929
   350
            case 0x14000000: return &p4_region_ocache_addr;
nkeynes@929
   351
            case 0x15000000: return &p4_region_ocache_data;
nkeynes@929
   352
            case 0x16000000: return &p4_region_utlb_addr;
nkeynes@929
   353
            case 0x17000000: return &p4_region_utlb_data;
nkeynes@929
   354
            default: return &mem_region_unmapped;
nkeynes@828
   355
            }
nkeynes@929
   356
        } else {
nkeynes@929
   357
            p4_count++;
nkeynes@929
   358
            struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
nkeynes@929
   359
            if( io != NULL ) {
nkeynes@929
   360
                return &io->fn;
nkeynes@929
   361
            }
nkeynes@929
   362
            return &mem_region_unmapped;
nkeynes@10
   363
        }
nkeynes@929
   364
        break;
nkeynes@929
   365
    case 6: /* P3 C0000000-DFFFFFFF - TLB on, Cache on */
nkeynes@929
   366
    case 5: /* P2 A0000000-BFFFFFFF - TLB off, Cache off*/
nkeynes@929
   367
    case 4: /* P1 80000000-9FFFFFFF - TLB off, Cache on */
nkeynes@929
   368
    default: /* P0/U0 00000000-7FFFFFFF - TLB on, Cache on */
nkeynes@929
   369
        return mem_decode_address( addr & 0x1FFFFFFF ); 
nkeynes@929
   370
        /* TODO: Integrate TLB, Operand Cache lookups */
nkeynes@10
   371
    }
nkeynes@10
   372
}
nkeynes@10
   373
nkeynes@929
   374
void FASTCALL sh7750_decode_address_copy( sh4addr_t addr, mem_region_fn_t result )
nkeynes@10
   375
{
nkeynes@929
   376
    mem_region_fn_t region = sh7750_decode_address( addr );
nkeynes@929
   377
    memcpy( result, region, sizeof(struct mem_region_fn) -8 );
nkeynes@10
   378
}
nkeynes@10
   379
nkeynes@10
   380
/* FIXME: Handle all the many special cases when the range doesn't fall cleanly
nkeynes@400
   381
 * into the same memory block
nkeynes@10
   382
 */
nkeynes@912
   383
void mem_copy_from_sh4( sh4ptr_t dest, sh4addr_t srcaddr, size_t count ) {
nkeynes@103
   384
    if( srcaddr >= 0x04000000 && srcaddr < 0x05000000 ) {
nkeynes@736
   385
        pvr2_vram64_read( dest, srcaddr, count );
nkeynes@103
   386
    } else {
nkeynes@736
   387
        sh4ptr_t src = mem_get_region(srcaddr);
nkeynes@736
   388
        if( src == NULL ) {
nkeynes@736
   389
            WARN( "Attempted block read from unknown address %08X", srcaddr );
nkeynes@736
   390
        } else {
nkeynes@736
   391
            memcpy( dest, src, count );
nkeynes@736
   392
        }
nkeynes@103
   393
    }
nkeynes@10
   394
}
nkeynes@10
   395
nkeynes@912
   396
void mem_copy_to_sh4( sh4addr_t destaddr, sh4ptr_t src, size_t count ) {
nkeynes@325
   397
    if( destaddr >= 0x10000000 && destaddr < 0x14000000 ) {
nkeynes@736
   398
        pvr2_dma_write( destaddr, src, count );
nkeynes@736
   399
        return;
nkeynes@325
   400
    } else if( (destaddr & 0x1F800000) == 0x05000000 ) {
nkeynes@736
   401
        pvr2_render_buffer_invalidate( destaddr, TRUE );
nkeynes@325
   402
    } else if( (destaddr & 0x1F800000) == 0x04000000 ) {
nkeynes@736
   403
        pvr2_vram64_write( destaddr, src, count );
nkeynes@736
   404
        return;
nkeynes@325
   405
    }
nkeynes@502
   406
    sh4ptr_t dest = mem_get_region(destaddr);
nkeynes@325
   407
    if( dest == NULL )
nkeynes@736
   408
        WARN( "Attempted block write to unknown address %08X", destaddr );
nkeynes@325
   409
    else {
nkeynes@736
   410
        xlat_invalidate_block( destaddr, count );
nkeynes@736
   411
        memcpy( dest, src, count );
nkeynes@90
   412
    }
nkeynes@10
   413
}
nkeynes@369
   414
nkeynes@929
   415
static uint32_t last_page = -1;
nkeynes@929
   416
static mem_region_fn_t last_region = NULL; 
nkeynes@929
   417
static uint32_t hit_count = 0;
nkeynes@929
   418
static uint32_t miss_count = 0;
nkeynes@929
   419
static uint32_t rl_count = 0, rw_count = 0, rb_count = 0;
nkeynes@929
   420
static uint32_t wl_count = 0, ww_count = 0, wb_count = 0;
nkeynes@929
   421
nkeynes@929
   422
/************** Compatibility methods ***************/
nkeynes@929
   423
nkeynes@929
   424
int32_t FASTCALL sh4_read_long( sh4addr_t addr )
nkeynes@929
   425
{
nkeynes@929
   426
    rl_count++;
nkeynes@930
   427
    return sh4_address_space[addr>>12]->read_long(addr);
nkeynes@929
   428
}
nkeynes@929
   429
nkeynes@929
   430
int32_t FASTCALL sh4_read_word( sh4addr_t addr )
nkeynes@929
   431
{
nkeynes@929
   432
    rw_count++;
nkeynes@930
   433
    return sh4_address_space[addr>>12]->read_word(addr);
nkeynes@929
   434
}
nkeynes@929
   435
nkeynes@929
   436
int32_t FASTCALL sh4_read_byte( sh4addr_t addr )
nkeynes@929
   437
{
nkeynes@929
   438
    rb_count++;
nkeynes@930
   439
    return sh4_address_space[addr>>12]->read_byte(addr);
nkeynes@929
   440
}
nkeynes@929
   441
nkeynes@929
   442
void FASTCALL sh4_write_long( sh4addr_t addr, uint32_t val )
nkeynes@929
   443
{
nkeynes@929
   444
    wl_count++;
nkeynes@930
   445
    sh4_address_space[addr>>12]->write_long(addr, val);
nkeynes@929
   446
}
nkeynes@929
   447
nkeynes@929
   448
void FASTCALL sh4_write_word( sh4addr_t addr, uint32_t val )
nkeynes@929
   449
{
nkeynes@929
   450
    ww_count++;
nkeynes@930
   451
    sh4_address_space[addr>>12]->write_word(addr,val);
nkeynes@929
   452
}
nkeynes@929
   453
nkeynes@929
   454
void FASTCALL sh4_write_byte( sh4addr_t addr, uint32_t val )
nkeynes@929
   455
{
nkeynes@929
   456
    wb_count++;
nkeynes@930
   457
    sh4_address_space[addr>>12]->write_byte(addr, val);
nkeynes@930
   458
}
nkeynes@930
   459
nkeynes@930
   460
extern mem_region_fn_t *ext_address_space;
nkeynes@930
   461
nkeynes@930
   462
static void sh4_register_mem_region( uint32_t start, uint32_t end, mem_region_fn_t fn )
nkeynes@930
   463
{
nkeynes@930
   464
    int count = (end - start) >> 12;
nkeynes@930
   465
    mem_region_fn_t *ptr = &sh4_address_space[start>>12];
nkeynes@930
   466
    while( count-- > 0 ) {
nkeynes@930
   467
        *ptr++ = fn;
nkeynes@929
   468
    }
nkeynes@929
   469
}
nkeynes@930
   470
    
nkeynes@929
   471
nkeynes@930
   472
void sh4_mem_init()
nkeynes@930
   473
{
nkeynes@930
   474
    int i;
nkeynes@930
   475
    mem_region_fn_t *ptr;
nkeynes@930
   476
    sh4_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 256 );
nkeynes@930
   477
    for( i=0, ptr = sh4_address_space; i<7; i++, ptr += LXDREAM_PAGE_TABLE_ENTRIES ) {
nkeynes@930
   478
        memcpy( ptr, ext_address_space, sizeof(mem_region_fn_t) * LXDREAM_PAGE_TABLE_ENTRIES );
nkeynes@930
   479
    }
nkeynes@930
   480
    
nkeynes@930
   481
    /* Setup main P4 regions */
nkeynes@930
   482
    sh4_register_mem_region( 0xE0000000, 0xE4000000, &p4_region_storequeue );
nkeynes@930
   483
    sh4_register_mem_region( 0xE4000000, 0xF0000000, &mem_region_unmapped );
nkeynes@930
   484
    sh4_register_mem_region( 0xF0000000, 0xF1000000, &p4_region_icache_addr );
nkeynes@930
   485
    sh4_register_mem_region( 0xF1000000, 0xF2000000, &p4_region_icache_data );
nkeynes@930
   486
    sh4_register_mem_region( 0xF2000000, 0xF3000000, &p4_region_itlb_addr );
nkeynes@930
   487
    sh4_register_mem_region( 0xF3000000, 0xF4000000, &p4_region_itlb_data );
nkeynes@930
   488
    sh4_register_mem_region( 0xF4000000, 0xF5000000, &p4_region_ocache_addr );
nkeynes@930
   489
    sh4_register_mem_region( 0xF5000000, 0xF6000000, &p4_region_ocache_data );
nkeynes@930
   490
    sh4_register_mem_region( 0xF6000000, 0xF7000000, &p4_region_utlb_addr );
nkeynes@930
   491
    sh4_register_mem_region( 0xF7000000, 0xF8000000, &p4_region_utlb_data );
nkeynes@930
   492
    sh4_register_mem_region( 0xF8000000, 0x00000000, &mem_region_unmapped );
nkeynes@930
   493
    
nkeynes@930
   494
    /* Setup P4 control region */
nkeynes@930
   495
    sh4_register_mem_region( 0xFF000000, 0xFF001000, &mmio_region_MMU.fn );
nkeynes@930
   496
    sh4_register_mem_region( 0xFF100000, 0xFF101000, &mmio_region_PMM.fn );
nkeynes@930
   497
    sh4_register_mem_region( 0xFF200000, 0xFF201000, &mmio_region_UBC.fn );
nkeynes@930
   498
    sh4_register_mem_region( 0xFF800000, 0xFF801000, &mmio_region_BSC.fn );
nkeynes@930
   499
    sh4_register_mem_region( 0xFF900000, 0xFFA00000, &mem_region_unmapped ); // SDMR2 + SDMR3
nkeynes@930
   500
    sh4_register_mem_region( 0xFFA00000, 0xFFA01000, &mmio_region_DMAC.fn );
nkeynes@930
   501
    sh4_register_mem_region( 0xFFC00000, 0xFFC01000, &mmio_region_CPG.fn );
nkeynes@930
   502
    sh4_register_mem_region( 0xFFC80000, 0xFFC81000, &mmio_region_RTC.fn );
nkeynes@930
   503
    sh4_register_mem_region( 0xFFD00000, 0xFFD01000, &mmio_region_INTC.fn );
nkeynes@930
   504
    sh4_register_mem_region( 0xFFD80000, 0xFFD81000, &mmio_region_TMU.fn );
nkeynes@930
   505
    sh4_register_mem_region( 0xFFE00000, 0xFFE01000, &mmio_region_SCI.fn );
nkeynes@930
   506
    sh4_register_mem_region( 0xFFE80000, 0xFFE81000, &mmio_region_SCIF.fn );
nkeynes@930
   507
    sh4_register_mem_region( 0xFFF00000, 0xFFF01000, &mem_region_unmapped ); // H-UDI    
nkeynes@930
   508
}
nkeynes@930
   509
                           
nkeynes@929
   510
void print_sh4mem_stats() {
nkeynes@929
   511
    printf( "Decodes to p4: %d sq: %d\n", p4_count+sq_count, sq_count );
nkeynes@929
   512
    printf( "Decodes to sdram: %d\n", decode_sdram );
nkeynes@929
   513
    printf( "Decodes: %d Hits: %d Miss: %d\n", decode_count, hit_count, miss_count );
nkeynes@929
   514
    printf( "Read long:  %d word: %d byte: %d\n", rl_count, rw_count, rb_count );
nkeynes@929
   515
    printf( "Write long: %d word: %d byte: %d\n", wl_count, ww_count, wb_count );
nkeynes@929
   516
}
.