Search
lxdream.org :: lxdream/src/sh4/sh4mem.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4mem.c
changeset 929:fd8cb0c82f5f
prev927:17b6b9e245d8
next930:07e5b11419db
author nkeynes
date Sat Dec 20 03:01:40 2008 +0000 (12 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change First pass experiment using cached decoding.
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@929
    53
/********************* The "unmapped" address space ********************/
nkeynes@929
    54
/* Always reads as 0, writes have no effect */
nkeynes@929
    55
static int32_t FASTCALL unmapped_read_long( sh4addr_t addr )
nkeynes@929
    56
{
nkeynes@929
    57
    return 0;
nkeynes@929
    58
}
nkeynes@929
    59
static void FASTCALL unmapped_write_long( sh4addr_t addr, uint32_t val )
nkeynes@929
    60
{
nkeynes@929
    61
}
nkeynes@929
    62
static void FASTCALL unmapped_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@929
    63
{
nkeynes@929
    64
    memset( dest, 0, 32 );
nkeynes@929
    65
}
nkeynes@929
    66
static void FASTCALL unmapped_write_burst( sh4addr_t addr, unsigned char *src )
nkeynes@929
    67
{
nkeynes@929
    68
}
nkeynes@929
    69
nkeynes@929
    70
struct mem_region_fn mem_region_unmapped = { 
nkeynes@929
    71
        unmapped_read_long, unmapped_write_long, 
nkeynes@929
    72
        unmapped_read_long, unmapped_write_long, 
nkeynes@929
    73
        unmapped_read_long, unmapped_write_long, 
nkeynes@929
    74
        unmapped_read_burst, unmapped_write_burst }; 
nkeynes@929
    75
nkeynes@929
    76
/********************* Store-queue (long-write only?) ******************/
nkeynes@929
    77
static void FASTCALL p4_storequeue_write_long( sh4addr_t addr, uint32_t val )
nkeynes@929
    78
{
nkeynes@929
    79
    sh4r.store_queue[(addr>>2)&0xF] = val;
nkeynes@929
    80
}
nkeynes@929
    81
static int32_t FASTCALL p4_storequeue_read_long( sh4addr_t addr )
nkeynes@929
    82
{
nkeynes@929
    83
    return sh4r.store_queue[(addr>>2)&0xF];
nkeynes@929
    84
}
nkeynes@929
    85
struct mem_region_fn p4_region_storequeue = { 
nkeynes@929
    86
        p4_storequeue_read_long, p4_storequeue_write_long,
nkeynes@929
    87
        p4_storequeue_read_long, p4_storequeue_write_long,
nkeynes@929
    88
        p4_storequeue_read_long, p4_storequeue_write_long,
nkeynes@929
    89
        unmapped_read_burst, unmapped_write_burst }; // No burst access.
nkeynes@929
    90
nkeynes@929
    91
/********************* The main ram address space **********************/
nkeynes@929
    92
static int32_t FASTCALL ext_sdram_read_long( sh4addr_t addr )
nkeynes@929
    93
{
nkeynes@929
    94
    return *((int32_t *)(sh4_main_ram + (addr&0x00FFFFFF)));
nkeynes@929
    95
}
nkeynes@929
    96
static int32_t FASTCALL ext_sdram_read_word( sh4addr_t addr )
nkeynes@929
    97
{
nkeynes@929
    98
    return SIGNEXT16(*((int16_t *)(sh4_main_ram + (addr&0x00FFFFFF))));
nkeynes@929
    99
}
nkeynes@929
   100
static int32_t FASTCALL ext_sdram_read_byte( sh4addr_t addr )
nkeynes@929
   101
{
nkeynes@929
   102
    return SIGNEXT8(*((int16_t *)(sh4_main_ram + (addr&0x00FFFFFF))));
nkeynes@929
   103
}
nkeynes@929
   104
static void FASTCALL ext_sdram_write_long( sh4addr_t addr, uint32_t val )
nkeynes@929
   105
{
nkeynes@929
   106
    *(uint32_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = val;
nkeynes@929
   107
    xlat_invalidate_long(addr);
nkeynes@929
   108
}
nkeynes@929
   109
static void FASTCALL ext_sdram_write_word( sh4addr_t addr, uint32_t val )
nkeynes@929
   110
{
nkeynes@929
   111
    *(uint16_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = (uint16_t)val;
nkeynes@929
   112
    xlat_invalidate_word(addr);
nkeynes@929
   113
}
nkeynes@929
   114
static void FASTCALL ext_sdram_write_byte( sh4addr_t addr, uint32_t val )
nkeynes@929
   115
{
nkeynes@929
   116
    *(uint8_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = (uint8_t)val;
nkeynes@929
   117
    xlat_invalidate_word(addr);
nkeynes@929
   118
}
nkeynes@929
   119
static void FASTCALL ext_sdram_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@929
   120
{
nkeynes@929
   121
    memcpy( dest, sh4_main_ram+(addr&0x00FFFFFF), 32 );
nkeynes@929
   122
}
nkeynes@929
   123
static void FASTCALL ext_sdram_write_burst( sh4addr_t addr, unsigned char *src )
nkeynes@929
   124
{
nkeynes@929
   125
    memcpy( sh4_main_ram+(addr&0x00FFFFFF), src, 32 );
nkeynes@929
   126
}
nkeynes@929
   127
nkeynes@929
   128
struct mem_region_fn mem_region_sdram = { ext_sdram_read_long, ext_sdram_write_long, 
nkeynes@929
   129
        ext_sdram_read_word, ext_sdram_write_word, 
nkeynes@929
   130
        ext_sdram_read_byte, ext_sdram_write_byte, 
nkeynes@929
   131
        ext_sdram_read_burst, ext_sdram_write_burst }; 
nkeynes@929
   132
nkeynes@929
   133
nkeynes@929
   134
/********************* The Boot ROM address space **********************/
nkeynes@929
   135
extern sh4ptr_t dc_boot_rom;
nkeynes@929
   136
extern sh4ptr_t dc_flash_ram;
nkeynes@929
   137
extern sh4ptr_t dc_audio_ram;
nkeynes@929
   138
static int32_t FASTCALL ext_bootrom_read_long( sh4addr_t addr )
nkeynes@929
   139
{
nkeynes@929
   140
    return *((int32_t *)(dc_boot_rom + (addr&0x001FFFFF)));
nkeynes@929
   141
}
nkeynes@929
   142
static int32_t FASTCALL ext_bootrom_read_word( sh4addr_t addr )
nkeynes@929
   143
{
nkeynes@929
   144
    return SIGNEXT16(*((int16_t *)(dc_boot_rom + (addr&0x001FFFFF))));
nkeynes@929
   145
}
nkeynes@929
   146
static int32_t FASTCALL ext_bootrom_read_byte( sh4addr_t addr )
nkeynes@929
   147
{
nkeynes@929
   148
    return SIGNEXT8(*((int16_t *)(dc_boot_rom + (addr&0x001FFFFF))));
nkeynes@929
   149
}
nkeynes@929
   150
static void FASTCALL ext_bootrom_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@929
   151
{
nkeynes@929
   152
    memcpy( dest, sh4_main_ram+(addr&0x001FFFFF), 32 );
nkeynes@929
   153
}
nkeynes@929
   154
nkeynes@929
   155
struct mem_region_fn mem_region_bootrom = { 
nkeynes@929
   156
        ext_bootrom_read_long, unmapped_write_long, 
nkeynes@929
   157
        ext_bootrom_read_word, unmapped_write_long, 
nkeynes@929
   158
        ext_bootrom_read_byte, unmapped_write_long, 
nkeynes@929
   159
        ext_bootrom_read_burst, unmapped_write_burst }; 
nkeynes@929
   160
nkeynes@929
   161
/********************* The Audio RAM address space **********************/
nkeynes@929
   162
static int32_t FASTCALL ext_audioram_read_long( sh4addr_t addr )
nkeynes@929
   163
{
nkeynes@929
   164
    return *((int32_t *)(dc_audio_ram + (addr&0x001FFFFF)));
nkeynes@929
   165
}
nkeynes@929
   166
static int32_t FASTCALL ext_audioram_read_word( sh4addr_t addr )
nkeynes@929
   167
{
nkeynes@929
   168
    return SIGNEXT16(*((int16_t *)(dc_audio_ram + (addr&0x001FFFFF))));
nkeynes@929
   169
}
nkeynes@929
   170
static int32_t FASTCALL ext_audioram_read_byte( sh4addr_t addr )
nkeynes@929
   171
{
nkeynes@929
   172
    return SIGNEXT8(*((int16_t *)(dc_audio_ram + (addr&0x001FFFFF))));
nkeynes@929
   173
}
nkeynes@929
   174
static void FASTCALL ext_audioram_write_long( sh4addr_t addr, uint32_t val )
nkeynes@929
   175
{
nkeynes@929
   176
    *(uint32_t *)(dc_audio_ram + (addr&0x001FFFFF)) = val;
nkeynes@929
   177
    asic_g2_write_word();
nkeynes@929
   178
}
nkeynes@929
   179
static void FASTCALL ext_audioram_write_word( sh4addr_t addr, uint32_t val )
nkeynes@929
   180
{
nkeynes@929
   181
    *(uint16_t *)(dc_audio_ram + (addr&0x001FFFFF)) = (uint16_t)val;
nkeynes@929
   182
    asic_g2_write_word();
nkeynes@929
   183
}
nkeynes@929
   184
static void FASTCALL ext_audioram_write_byte( sh4addr_t addr, uint32_t val )
nkeynes@929
   185
{
nkeynes@929
   186
    *(uint8_t *)(dc_audio_ram + (addr&0x001FFFFF)) = (uint8_t)val;
nkeynes@929
   187
    asic_g2_write_word();
nkeynes@929
   188
}
nkeynes@929
   189
static void FASTCALL ext_audioram_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@929
   190
{
nkeynes@929
   191
    memcpy( dest, dc_audio_ram+(addr&0x001FFFFF), 32 );
nkeynes@929
   192
}
nkeynes@929
   193
static void FASTCALL ext_audioram_write_burst( sh4addr_t addr, unsigned char *src )
nkeynes@929
   194
{
nkeynes@929
   195
    memcpy( dc_audio_ram+(addr&0x001FFFFF), src, 32 );
nkeynes@929
   196
}
nkeynes@929
   197
nkeynes@929
   198
struct mem_region_fn mem_region_audioram = { ext_audioram_read_long, ext_audioram_write_long, 
nkeynes@929
   199
        ext_audioram_read_word, ext_audioram_write_word, 
nkeynes@929
   200
        ext_audioram_read_byte, ext_audioram_write_byte, 
nkeynes@929
   201
        ext_audioram_read_burst, ext_audioram_write_burst }; 
nkeynes@929
   202
nkeynes@929
   203
/********************* The Flash RAM address space **********************/
nkeynes@929
   204
static int32_t FASTCALL ext_flashram_read_long( sh4addr_t addr )
nkeynes@929
   205
{
nkeynes@929
   206
    return *((int32_t *)(dc_flash_ram + (addr&0x0001FFFF)));
nkeynes@929
   207
}
nkeynes@929
   208
static int32_t FASTCALL ext_flashram_read_word( sh4addr_t addr )
nkeynes@929
   209
{
nkeynes@929
   210
    return SIGNEXT16(*((int16_t *)(dc_flash_ram + (addr&0x0001FFFF))));
nkeynes@929
   211
}
nkeynes@929
   212
static int32_t FASTCALL ext_flashram_read_byte( sh4addr_t addr )
nkeynes@929
   213
{
nkeynes@929
   214
    return SIGNEXT8(*((int16_t *)(dc_flash_ram + (addr&0x0001FFFF))));
nkeynes@929
   215
}
nkeynes@929
   216
static void FASTCALL ext_flashram_write_long( sh4addr_t addr, uint32_t val )
nkeynes@929
   217
{
nkeynes@929
   218
    *(uint32_t *)(dc_flash_ram + (addr&0x0001FFFF)) = val;
nkeynes@929
   219
    asic_g2_write_word();
nkeynes@929
   220
}
nkeynes@929
   221
static void FASTCALL ext_flashram_write_word( sh4addr_t addr, uint32_t val )
nkeynes@929
   222
{
nkeynes@929
   223
    *(uint16_t *)(dc_flash_ram + (addr&0x0001FFFF)) = (uint16_t)val;
nkeynes@929
   224
    asic_g2_write_word();
nkeynes@929
   225
}
nkeynes@929
   226
static void FASTCALL ext_flashram_write_byte( sh4addr_t addr, uint32_t val )
nkeynes@929
   227
{
nkeynes@929
   228
    *(uint8_t *)(dc_flash_ram + (addr&0x0001FFFF)) = (uint8_t)val;
nkeynes@929
   229
    asic_g2_write_word();
nkeynes@929
   230
}
nkeynes@929
   231
static void FASTCALL ext_flashram_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@929
   232
{
nkeynes@929
   233
    memcpy( dest, dc_flash_ram+(addr&0x0001FFFF), 32 );
nkeynes@929
   234
}
nkeynes@929
   235
static void FASTCALL ext_flashram_write_burst( sh4addr_t addr, unsigned char *src )
nkeynes@929
   236
{
nkeynes@929
   237
    memcpy( dc_flash_ram+(addr&0x0001FFFF), src, 32 );
nkeynes@929
   238
}
nkeynes@929
   239
nkeynes@929
   240
struct mem_region_fn mem_region_flashram = { ext_flashram_read_long, ext_flashram_write_long, 
nkeynes@929
   241
        ext_flashram_read_word, ext_flashram_write_word, 
nkeynes@929
   242
        ext_flashram_read_byte, ext_flashram_write_byte, 
nkeynes@929
   243
        ext_flashram_read_burst, ext_flashram_write_burst }; 
nkeynes@929
   244
nkeynes@929
   245
/**************************************************************************/
nkeynes@929
   246
nkeynes@929
   247
struct mem_region_fn p4_region_icache_addr = {
nkeynes@929
   248
        mmu_icache_addr_read, mmu_icache_addr_write,
nkeynes@929
   249
        mmu_icache_addr_read, mmu_icache_addr_write,
nkeynes@929
   250
        mmu_icache_addr_read, mmu_icache_addr_write,
nkeynes@929
   251
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   252
struct mem_region_fn p4_region_icache_data = {
nkeynes@929
   253
        mmu_icache_data_read, mmu_icache_data_write,
nkeynes@929
   254
        mmu_icache_data_read, mmu_icache_data_write,
nkeynes@929
   255
        mmu_icache_data_read, mmu_icache_data_write,
nkeynes@929
   256
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   257
struct mem_region_fn p4_region_ocache_addr = {
nkeynes@929
   258
        mmu_ocache_addr_read, mmu_ocache_addr_write,
nkeynes@929
   259
        mmu_ocache_addr_read, mmu_ocache_addr_write,
nkeynes@929
   260
        mmu_ocache_addr_read, mmu_ocache_addr_write,
nkeynes@929
   261
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   262
struct mem_region_fn p4_region_ocache_data = {
nkeynes@929
   263
        mmu_ocache_data_read, mmu_ocache_data_write,
nkeynes@929
   264
        mmu_ocache_data_read, mmu_ocache_data_write,
nkeynes@929
   265
        mmu_ocache_data_read, mmu_ocache_data_write,
nkeynes@929
   266
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   267
struct mem_region_fn p4_region_itlb_addr = {
nkeynes@929
   268
        mmu_itlb_addr_read, mmu_itlb_addr_write,
nkeynes@929
   269
        mmu_itlb_addr_read, mmu_itlb_addr_write,
nkeynes@929
   270
        mmu_itlb_addr_read, mmu_itlb_addr_write,
nkeynes@929
   271
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   272
struct mem_region_fn p4_region_itlb_data = {
nkeynes@929
   273
        mmu_itlb_data_read, mmu_itlb_data_write,
nkeynes@929
   274
        mmu_itlb_data_read, mmu_itlb_data_write,
nkeynes@929
   275
        mmu_itlb_data_read, mmu_itlb_data_write,
nkeynes@929
   276
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   277
struct mem_region_fn p4_region_utlb_addr = {
nkeynes@929
   278
        mmu_utlb_addr_read, mmu_utlb_addr_write,
nkeynes@929
   279
        mmu_utlb_addr_read, mmu_utlb_addr_write,
nkeynes@929
   280
        mmu_utlb_addr_read, mmu_utlb_addr_write,
nkeynes@929
   281
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   282
struct mem_region_fn p4_region_utlb_data = {
nkeynes@929
   283
        mmu_utlb_data_read, mmu_utlb_data_write,
nkeynes@929
   284
        mmu_utlb_data_read, mmu_utlb_data_write,
nkeynes@929
   285
        mmu_utlb_data_read, mmu_utlb_data_write,
nkeynes@929
   286
        unmapped_read_burst, unmapped_write_burst };
nkeynes@929
   287
nkeynes@929
   288
#ifdef HAVE_FRAME_ADDRESS
nkeynes@929
   289
#define RETURN_VIA(exc) do{ *(((void **)__builtin_frame_address(0))+1) = exc; return; } while(0)
nkeynes@10
   290
#else
nkeynes@929
   291
#define RETURN_VIA(exc) return NULL
nkeynes@10
   292
#endif
nkeynes@10
   293
nkeynes@929
   294
int decode_sdram = 0;
nkeynes@929
   295
mem_region_fn_t FASTCALL mem_decode_address( sh4addr_t addr )
nkeynes@10
   296
{
nkeynes@929
   297
    sh4ptr_t page;
nkeynes@929
   298
    switch( addr >> 26 ) { /* Area */
nkeynes@929
   299
    case 0: /* Holly multiplexed */
nkeynes@929
   300
        page = page_map[(addr&0x1FFFFFFF)>>12];
nkeynes@929
   301
        if( ((uintptr_t)page) < MAX_IO_REGIONS ) {
nkeynes@929
   302
            return &io_rgn[(uintptr_t)page]->fn;
nkeynes@929
   303
        } else if( addr < 0x00200000 ) {
nkeynes@929
   304
            return &mem_region_bootrom;
nkeynes@929
   305
        } else if( addr < 0x00400000 ) {
nkeynes@929
   306
            return &mem_region_flashram;
nkeynes@929
   307
        } else if( addr >= 0x00800000 && addr < 0x00A00000 ) {
nkeynes@929
   308
            return &mem_region_audioram;
nkeynes@282
   309
        }
nkeynes@929
   310
        break;
nkeynes@929
   311
    case 1: /* VRAM */
nkeynes@929
   312
        switch( addr >> 24 ) {
nkeynes@929
   313
        case 4: return &mem_region_vram64; /* 0x04xxxxxx */
nkeynes@929
   314
        case 5: return &mem_region_vram32; /* 0x05xxxxxx */ 
nkeynes@929
   315
        }    
nkeynes@929
   316
        break;
nkeynes@929
   317
    case 2: /* Unmapped */
nkeynes@929
   318
        break;
nkeynes@929
   319
    case 3: /* Main sdram */
nkeynes@929
   320
        decode_sdram++;
nkeynes@929
   321
        return &mem_region_sdram;
nkeynes@929
   322
    case 4: /* Holly burst-access only? */
nkeynes@929
   323
        break;
nkeynes@929
   324
    }
nkeynes@929
   325
    return &mem_region_unmapped;
nkeynes@10
   326
}
nkeynes@10
   327
nkeynes@929
   328
int decode_count = 0;
nkeynes@929
   329
int p4_count = 0;
nkeynes@929
   330
int sq_count = 0;
nkeynes@929
   331
nkeynes@929
   332
mem_region_fn_t FASTCALL sh7750_decode_address( sh4addr_t addr )
nkeynes@10
   333
{
nkeynes@929
   334
    decode_count++;
nkeynes@929
   335
    sh4addr_t region = addr >> 29;
nkeynes@929
   336
    switch( region ) {
nkeynes@929
   337
    case 7: /* P4 E0000000-FFFFFFFF - On-chip I/O */
nkeynes@929
   338
        if( addr < 0xE4000000 ) {
nkeynes@929
   339
            sq_count++;
nkeynes@929
   340
            return &p4_region_storequeue;
nkeynes@929
   341
        } else if( addr < 0xFC000000 ) { /* Control register region */
nkeynes@929
   342
            p4_count++;
nkeynes@929
   343
            switch( addr & 0x1F000000 ) {
nkeynes@929
   344
            case 0x10000000: return &p4_region_icache_addr;
nkeynes@929
   345
            case 0x11000000: return &p4_region_icache_data;
nkeynes@929
   346
            case 0x12000000: return &p4_region_itlb_addr;
nkeynes@929
   347
            case 0x13000000: return &p4_region_itlb_data;
nkeynes@929
   348
            case 0x14000000: return &p4_region_ocache_addr;
nkeynes@929
   349
            case 0x15000000: return &p4_region_ocache_data;
nkeynes@929
   350
            case 0x16000000: return &p4_region_utlb_addr;
nkeynes@929
   351
            case 0x17000000: return &p4_region_utlb_data;
nkeynes@929
   352
            default: return &mem_region_unmapped;
nkeynes@828
   353
            }
nkeynes@929
   354
        } else {
nkeynes@929
   355
            p4_count++;
nkeynes@929
   356
            struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
nkeynes@929
   357
            if( io != NULL ) {
nkeynes@929
   358
                return &io->fn;
nkeynes@929
   359
            }
nkeynes@929
   360
            return &mem_region_unmapped;
nkeynes@10
   361
        }
nkeynes@929
   362
        break;
nkeynes@929
   363
    case 6: /* P3 C0000000-DFFFFFFF - TLB on, Cache on */
nkeynes@929
   364
    case 5: /* P2 A0000000-BFFFFFFF - TLB off, Cache off*/
nkeynes@929
   365
    case 4: /* P1 80000000-9FFFFFFF - TLB off, Cache on */
nkeynes@929
   366
    default: /* P0/U0 00000000-7FFFFFFF - TLB on, Cache on */
nkeynes@929
   367
        return mem_decode_address( addr & 0x1FFFFFFF ); 
nkeynes@929
   368
        /* TODO: Integrate TLB, Operand Cache lookups */
nkeynes@10
   369
    }
nkeynes@10
   370
}
nkeynes@10
   371
nkeynes@929
   372
void FASTCALL sh7750_decode_address_copy( sh4addr_t addr, mem_region_fn_t result )
nkeynes@10
   373
{
nkeynes@929
   374
    mem_region_fn_t region = sh7750_decode_address( addr );
nkeynes@929
   375
    memcpy( result, region, sizeof(struct mem_region_fn) -8 );
nkeynes@10
   376
}
nkeynes@10
   377
nkeynes@10
   378
/* FIXME: Handle all the many special cases when the range doesn't fall cleanly
nkeynes@400
   379
 * into the same memory block
nkeynes@10
   380
 */
nkeynes@912
   381
void mem_copy_from_sh4( sh4ptr_t dest, sh4addr_t srcaddr, size_t count ) {
nkeynes@103
   382
    if( srcaddr >= 0x04000000 && srcaddr < 0x05000000 ) {
nkeynes@736
   383
        pvr2_vram64_read( dest, srcaddr, count );
nkeynes@103
   384
    } else {
nkeynes@736
   385
        sh4ptr_t src = mem_get_region(srcaddr);
nkeynes@736
   386
        if( src == NULL ) {
nkeynes@736
   387
            WARN( "Attempted block read from unknown address %08X", srcaddr );
nkeynes@736
   388
        } else {
nkeynes@736
   389
            memcpy( dest, src, count );
nkeynes@736
   390
        }
nkeynes@103
   391
    }
nkeynes@10
   392
}
nkeynes@10
   393
nkeynes@912
   394
void mem_copy_to_sh4( sh4addr_t destaddr, sh4ptr_t src, size_t count ) {
nkeynes@325
   395
    if( destaddr >= 0x10000000 && destaddr < 0x14000000 ) {
nkeynes@736
   396
        pvr2_dma_write( destaddr, src, count );
nkeynes@736
   397
        return;
nkeynes@325
   398
    } else if( (destaddr & 0x1F800000) == 0x05000000 ) {
nkeynes@736
   399
        pvr2_render_buffer_invalidate( destaddr, TRUE );
nkeynes@325
   400
    } else if( (destaddr & 0x1F800000) == 0x04000000 ) {
nkeynes@736
   401
        pvr2_vram64_write( destaddr, src, count );
nkeynes@736
   402
        return;
nkeynes@325
   403
    }
nkeynes@502
   404
    sh4ptr_t dest = mem_get_region(destaddr);
nkeynes@325
   405
    if( dest == NULL )
nkeynes@736
   406
        WARN( "Attempted block write to unknown address %08X", destaddr );
nkeynes@325
   407
    else {
nkeynes@736
   408
        xlat_invalidate_block( destaddr, count );
nkeynes@736
   409
        memcpy( dest, src, count );
nkeynes@90
   410
    }
nkeynes@10
   411
}
nkeynes@369
   412
nkeynes@929
   413
static uint32_t last_page = -1;
nkeynes@929
   414
static mem_region_fn_t last_region = NULL; 
nkeynes@929
   415
static uint32_t hit_count = 0;
nkeynes@929
   416
static uint32_t miss_count = 0;
nkeynes@929
   417
static uint32_t rl_count = 0, rw_count = 0, rb_count = 0;
nkeynes@929
   418
static uint32_t wl_count = 0, ww_count = 0, wb_count = 0;
nkeynes@929
   419
nkeynes@929
   420
/************** Compatibility methods ***************/
nkeynes@929
   421
nkeynes@929
   422
int32_t FASTCALL sh4_read_long( sh4addr_t addr )
nkeynes@929
   423
{
nkeynes@929
   424
    rl_count++;
nkeynes@929
   425
    uint32_t page = (addr & 0xFFFFF000);
nkeynes@929
   426
    if( page == last_page ) {
nkeynes@929
   427
        hit_count++;
nkeynes@929
   428
        return last_region->read_long(addr);
nkeynes@929
   429
    } else {
nkeynes@929
   430
        miss_count++;
nkeynes@929
   431
        last_page = page;
nkeynes@929
   432
        last_region = sh7750_decode_address(addr);
nkeynes@929
   433
        return last_region->read_long(addr);
nkeynes@929
   434
    }
nkeynes@929
   435
}
nkeynes@929
   436
nkeynes@929
   437
int32_t FASTCALL sh4_read_word( sh4addr_t addr )
nkeynes@929
   438
{
nkeynes@929
   439
    rw_count++;
nkeynes@929
   440
    uint32_t page = (addr & 0xFFFFF000);
nkeynes@929
   441
    if( page == last_page ) {
nkeynes@929
   442
        hit_count++;
nkeynes@929
   443
        return last_region->read_word(addr);
nkeynes@929
   444
    } else {
nkeynes@929
   445
        miss_count++;
nkeynes@929
   446
        last_page = page;
nkeynes@929
   447
        last_region = sh7750_decode_address(addr);
nkeynes@929
   448
        return last_region->read_word(addr);
nkeynes@929
   449
    }
nkeynes@929
   450
}
nkeynes@929
   451
nkeynes@929
   452
int32_t FASTCALL sh4_read_byte( sh4addr_t addr )
nkeynes@929
   453
{
nkeynes@929
   454
    rb_count++;
nkeynes@929
   455
    uint32_t page = (addr & 0xFFFFF000);
nkeynes@929
   456
    if( page == last_page ) {
nkeynes@929
   457
        hit_count++;
nkeynes@929
   458
        return last_region->read_byte(addr);
nkeynes@929
   459
    } else {
nkeynes@929
   460
        miss_count++;
nkeynes@929
   461
        last_page = page;
nkeynes@929
   462
        last_region = sh7750_decode_address(addr);
nkeynes@929
   463
        return last_region->read_byte(addr);
nkeynes@929
   464
    }    
nkeynes@929
   465
}
nkeynes@929
   466
nkeynes@929
   467
void FASTCALL sh4_write_long( sh4addr_t addr, uint32_t val )
nkeynes@929
   468
{
nkeynes@929
   469
    wl_count++;
nkeynes@929
   470
    uint32_t page = (addr & 0xFFFFF000);
nkeynes@929
   471
    if( page == last_page ) {
nkeynes@929
   472
        hit_count++;
nkeynes@929
   473
        last_region->write_long(addr, val);
nkeynes@929
   474
    } else {
nkeynes@929
   475
        miss_count++;
nkeynes@929
   476
        last_page = page;
nkeynes@929
   477
        last_region = sh7750_decode_address(addr);
nkeynes@929
   478
        last_region->write_long(addr,val);
nkeynes@929
   479
    }
nkeynes@929
   480
}
nkeynes@929
   481
nkeynes@929
   482
void FASTCALL sh4_write_word( sh4addr_t addr, uint32_t val )
nkeynes@929
   483
{
nkeynes@929
   484
    ww_count++;
nkeynes@929
   485
    uint32_t page = (addr & 0xFFFFF000);
nkeynes@929
   486
    if( page == last_page ) {
nkeynes@929
   487
        hit_count++;
nkeynes@929
   488
        last_region->write_word(addr, val);
nkeynes@929
   489
    } else {
nkeynes@929
   490
        miss_count++;
nkeynes@929
   491
        last_page = page;
nkeynes@929
   492
        last_region = sh7750_decode_address(addr);
nkeynes@929
   493
        last_region->write_word(addr,val);
nkeynes@929
   494
    }
nkeynes@929
   495
}
nkeynes@929
   496
nkeynes@929
   497
void FASTCALL sh4_write_byte( sh4addr_t addr, uint32_t val )
nkeynes@929
   498
{
nkeynes@929
   499
    wb_count++;
nkeynes@929
   500
    uint32_t page = (addr & 0xFFFFF000);
nkeynes@929
   501
    if( page == last_page ) {
nkeynes@929
   502
        hit_count++;
nkeynes@929
   503
        last_region->write_byte(addr, val);
nkeynes@929
   504
    } else {
nkeynes@929
   505
        miss_count++;
nkeynes@929
   506
        last_page = page;
nkeynes@929
   507
        last_region = sh7750_decode_address(addr);
nkeynes@929
   508
        last_region->write_byte(addr,val);
nkeynes@929
   509
    }
nkeynes@929
   510
}
nkeynes@929
   511
nkeynes@929
   512
void print_sh4mem_stats() {
nkeynes@929
   513
    printf( "Decodes to p4: %d sq: %d\n", p4_count+sq_count, sq_count );
nkeynes@929
   514
    printf( "Decodes to sdram: %d\n", decode_sdram );
nkeynes@929
   515
    printf( "Decodes: %d Hits: %d Miss: %d\n", decode_count, hit_count, miss_count );
nkeynes@929
   516
    printf( "Read long:  %d word: %d byte: %d\n", rl_count, rw_count, rb_count );
nkeynes@929
   517
    printf( "Write long: %d word: %d byte: %d\n", wl_count, ww_count, wb_count );
nkeynes@929
   518
}
.