Search
lxdream.org :: lxdream/src/sh4/cache.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/cache.c
changeset 931:430048ea8b71
next933:880c37bb1909
author nkeynes
date Tue Dec 23 05:48:05 2008 +0000 (13 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
file annotate diff log raw
nkeynes@931
     1
/**
nkeynes@931
     2
 * $Id$
nkeynes@931
     3
 * Implements the on-chip operand cache and instruction caches
nkeynes@931
     4
 *
nkeynes@931
     5
 * Copyright (c) 2008 Nathan Keynes.
nkeynes@931
     6
 *
nkeynes@931
     7
 * This program is free software; you can redistribute it and/or modify
nkeynes@931
     8
 * it under the terms of the GNU General Public License as published by
nkeynes@931
     9
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@931
    10
 * (at your option) any later version.
nkeynes@931
    11
 *
nkeynes@931
    12
 * This program is distributed in the hope that it will be useful,
nkeynes@931
    13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@931
    14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@931
    15
 * GNU General Public License for more details.
nkeynes@931
    16
 */
nkeynes@931
    17
nkeynes@931
    18
#define MODULE sh4_module
nkeynes@931
    19
nkeynes@931
    20
#include <string.h>
nkeynes@931
    21
#include "dream.h"
nkeynes@931
    22
#include "mem.h"
nkeynes@931
    23
#include "mmio.h"
nkeynes@931
    24
#include "sh4/sh4core.h"
nkeynes@931
    25
#include "sh4/sh4mmio.h"
nkeynes@931
    26
#include "sh4/xltcache.h"
nkeynes@931
    27
nkeynes@931
    28
#define OCRAM_START (0x7C000000>>LXDREAM_PAGE_BITS)
nkeynes@931
    29
#define OCRAM_MID   (0x7E000000>>LXDREAM_PAGE_BITS)
nkeynes@931
    30
#define OCRAM_END   (0x80000000>>LXDREAM_PAGE_BITS)
nkeynes@931
    31
nkeynes@931
    32
#define CACHE_VALID 1
nkeynes@931
    33
#define CACHE_DIRTY 2
nkeynes@931
    34
nkeynes@931
    35
#define ICACHE_ENTRY_COUNT 256
nkeynes@931
    36
#define OCACHE_ENTRY_COUNT 512
nkeynes@931
    37
nkeynes@931
    38
struct cache_line {
nkeynes@931
    39
    uint32_t key;  // Fast address match - bits 5..28 for valid entry, -1 for invalid entry
nkeynes@931
    40
    uint32_t tag;  // tag + flags value from the address field
nkeynes@931
    41
};    
nkeynes@931
    42
nkeynes@931
    43
nkeynes@931
    44
static struct cache_line ccn_icache[ICACHE_ENTRY_COUNT];
nkeynes@931
    45
static struct cache_line ccn_ocache[OCACHE_ENTRY_COUNT];
nkeynes@931
    46
static unsigned char ccn_icache_data[ICACHE_ENTRY_COUNT*32];
nkeynes@931
    47
static unsigned char ccn_ocache_data[OCACHE_ENTRY_COUNT*32];
nkeynes@931
    48
nkeynes@931
    49
nkeynes@931
    50
/*********************** General module requirements ********************/
nkeynes@931
    51
nkeynes@931
    52
void CCN_save_state( FILE *f )
nkeynes@931
    53
{
nkeynes@931
    54
    fwrite( &ccn_icache, sizeof(ccn_icache), 1, f );
nkeynes@931
    55
    fwrite( &ccn_icache_data, sizeof(ccn_icache_data), 1, f );
nkeynes@931
    56
    fwrite( &ccn_ocache, sizeof(ccn_ocache), 1, f);
nkeynes@931
    57
    fwrite( &ccn_ocache_data, sizeof(ccn_ocache_data), 1, f);
nkeynes@931
    58
}
nkeynes@931
    59
nkeynes@931
    60
int CCN_load_state( FILE *f )
nkeynes@931
    61
{
nkeynes@931
    62
    /* Setup the cache mode according to the saved register value
nkeynes@931
    63
     * (mem_load runs before this point to load all MMIO data)
nkeynes@931
    64
     */
nkeynes@931
    65
    mmio_region_MMU_write( CCR, MMIO_READ(MMU, CCR) );
nkeynes@931
    66
nkeynes@931
    67
    if( fread( &ccn_icache, sizeof(ccn_icache), 1, f ) != 1 ) {
nkeynes@931
    68
        return 1;
nkeynes@931
    69
    }
nkeynes@931
    70
    if( fread( &ccn_icache_data, sizeof(ccn_icache_data), 1, f ) != 1 ) {
nkeynes@931
    71
        return 1;
nkeynes@931
    72
    }
nkeynes@931
    73
    if( fread( &ccn_ocache, sizeof(ccn_ocache), 1, f ) != 1 ) {
nkeynes@931
    74
        return 1;
nkeynes@931
    75
    }
nkeynes@931
    76
    if( fread( &ccn_ocache_data, sizeof(ccn_ocache_data), 1, f ) != 1 ) {
nkeynes@931
    77
        return 1;
nkeynes@931
    78
    }
nkeynes@931
    79
    return 0;
nkeynes@931
    80
}
nkeynes@931
    81
nkeynes@931
    82
nkeynes@931
    83
/************************* OCRAM memory address space ************************/
nkeynes@931
    84
nkeynes@931
    85
#define OCRAMPAGE0 (&ccn_ocache_data[4096])  /* Lines 128-255 */
nkeynes@931
    86
#define OCRAMPAGE1 (&ccn_ocache_data[12288]) /* Lines 384-511 */
nkeynes@931
    87
nkeynes@931
    88
static int32_t FASTCALL ocram_page0_read_long( sh4addr_t addr )
nkeynes@931
    89
{
nkeynes@931
    90
    return *((int32_t *)(OCRAMPAGE0 + (addr&0x00000FFF)));
nkeynes@931
    91
}
nkeynes@931
    92
static int32_t FASTCALL ocram_page0_read_word( sh4addr_t addr )
nkeynes@931
    93
{
nkeynes@931
    94
    return SIGNEXT16(*((int16_t *)(OCRAMPAGE0 + (addr&0x00000FFF))));
nkeynes@931
    95
}
nkeynes@931
    96
static int32_t FASTCALL ocram_page0_read_byte( sh4addr_t addr )
nkeynes@931
    97
{
nkeynes@931
    98
    return SIGNEXT8(*((int16_t *)(OCRAMPAGE0 + (addr&0x00000FFF))));
nkeynes@931
    99
}
nkeynes@931
   100
static void FASTCALL ocram_page0_write_long( sh4addr_t addr, uint32_t val )
nkeynes@931
   101
{
nkeynes@931
   102
    *(uint32_t *)(OCRAMPAGE0 + (addr&0x00000FFF)) = val;
nkeynes@931
   103
}
nkeynes@931
   104
static void FASTCALL ocram_page0_write_word( sh4addr_t addr, uint32_t val )
nkeynes@931
   105
{
nkeynes@931
   106
    *(uint16_t *)(OCRAMPAGE0 + (addr&0x00000FFF)) = (uint16_t)val;
nkeynes@931
   107
}
nkeynes@931
   108
static void FASTCALL ocram_page0_write_byte( sh4addr_t addr, uint32_t val )
nkeynes@931
   109
{
nkeynes@931
   110
    *(uint8_t *)(OCRAMPAGE0 + (addr&0x00000FFF)) = (uint8_t)val;
nkeynes@931
   111
}
nkeynes@931
   112
static void FASTCALL ocram_page0_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@931
   113
{
nkeynes@931
   114
    memcpy( dest, OCRAMPAGE0+(addr&0x00000FFF), 32 );
nkeynes@931
   115
}
nkeynes@931
   116
static void FASTCALL ocram_page0_write_burst( sh4addr_t addr, unsigned char *src )
nkeynes@931
   117
{
nkeynes@931
   118
    memcpy( OCRAMPAGE0+(addr&0x00000FFF), src, 32 );
nkeynes@931
   119
}
nkeynes@931
   120
nkeynes@931
   121
struct mem_region_fn mem_region_ocram_page0 = {
nkeynes@931
   122
        ocram_page0_read_long, ocram_page0_write_long,
nkeynes@931
   123
        ocram_page0_read_word, ocram_page0_write_word,
nkeynes@931
   124
        ocram_page0_read_byte, ocram_page0_write_byte,
nkeynes@931
   125
        ocram_page0_read_burst, ocram_page0_write_burst };
nkeynes@931
   126
nkeynes@931
   127
static int32_t FASTCALL ocram_page1_read_long( sh4addr_t addr )
nkeynes@931
   128
{
nkeynes@931
   129
    return *((int32_t *)(OCRAMPAGE1 + (addr&0x00000FFF)));
nkeynes@931
   130
}
nkeynes@931
   131
static int32_t FASTCALL ocram_page1_read_word( sh4addr_t addr )
nkeynes@931
   132
{
nkeynes@931
   133
    return SIGNEXT16(*((int16_t *)(OCRAMPAGE1 + (addr&0x00000FFF))));
nkeynes@931
   134
}
nkeynes@931
   135
static int32_t FASTCALL ocram_page1_read_byte( sh4addr_t addr )
nkeynes@931
   136
{
nkeynes@931
   137
    return SIGNEXT8(*((int16_t *)(OCRAMPAGE1 + (addr&0x00000FFF))));
nkeynes@931
   138
}
nkeynes@931
   139
static void FASTCALL ocram_page1_write_long( sh4addr_t addr, uint32_t val )
nkeynes@931
   140
{
nkeynes@931
   141
    *(uint32_t *)(OCRAMPAGE1 + (addr&0x00000FFF)) = val;
nkeynes@931
   142
}
nkeynes@931
   143
static void FASTCALL ocram_page1_write_word( sh4addr_t addr, uint32_t val )
nkeynes@931
   144
{
nkeynes@931
   145
    *(uint16_t *)(OCRAMPAGE1 + (addr&0x00000FFF)) = (uint16_t)val;
nkeynes@931
   146
}
nkeynes@931
   147
static void FASTCALL ocram_page1_write_byte( sh4addr_t addr, uint32_t val )
nkeynes@931
   148
{
nkeynes@931
   149
    *(uint8_t *)(OCRAMPAGE1 + (addr&0x00000FFF)) = (uint8_t)val;
nkeynes@931
   150
}
nkeynes@931
   151
static void FASTCALL ocram_page1_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@931
   152
{
nkeynes@931
   153
    memcpy( dest, OCRAMPAGE1+(addr&0x00000FFF), 32 );
nkeynes@931
   154
}
nkeynes@931
   155
static void FASTCALL ocram_page1_write_burst( sh4addr_t addr, unsigned char *src )
nkeynes@931
   156
{
nkeynes@931
   157
    memcpy( OCRAMPAGE1+(addr&0x00000FFF), src, 32 );
nkeynes@931
   158
}
nkeynes@931
   159
nkeynes@931
   160
struct mem_region_fn mem_region_ocram_page1 = {
nkeynes@931
   161
        ocram_page1_read_long, ocram_page1_write_long,
nkeynes@931
   162
        ocram_page1_read_word, ocram_page1_write_word,
nkeynes@931
   163
        ocram_page1_read_byte, ocram_page1_write_byte,
nkeynes@931
   164
        ocram_page1_read_burst, ocram_page1_write_burst };
nkeynes@931
   165
nkeynes@931
   166
/****************** Cache control *********************/
nkeynes@931
   167
nkeynes@931
   168
void CCN_set_cache_control( int reg )
nkeynes@931
   169
{
nkeynes@931
   170
    uint32_t i;
nkeynes@931
   171
    switch( reg & (CCR_OIX|CCR_ORA|CCR_OCE) ) {
nkeynes@931
   172
    case MEM_OC_INDEX0: /* OIX=0 */
nkeynes@931
   173
        for( i=OCRAM_START; i<OCRAM_END; i+=4 ) {
nkeynes@931
   174
            sh4_address_space[i] = &mem_region_ocram_page0;
nkeynes@931
   175
            sh4_address_space[i+1] = &mem_region_ocram_page0;
nkeynes@931
   176
            sh4_address_space[i+2] = &mem_region_ocram_page1;
nkeynes@931
   177
            sh4_address_space[i+3] = &mem_region_ocram_page1;
nkeynes@931
   178
        }
nkeynes@931
   179
        break;
nkeynes@931
   180
    case MEM_OC_INDEX1: /* OIX=1 */
nkeynes@931
   181
        for( i=OCRAM_START; i<OCRAM_MID; i++ )
nkeynes@931
   182
            sh4_address_space[i] = &mem_region_ocram_page0;
nkeynes@931
   183
        for( i=OCRAM_MID; i<OCRAM_END; i++ )
nkeynes@931
   184
            sh4_address_space[i] = &mem_region_ocram_page1;
nkeynes@931
   185
        break;
nkeynes@931
   186
    default: /* disabled */
nkeynes@931
   187
        for( i=OCRAM_START; i<OCRAM_END; i++ )
nkeynes@931
   188
            sh4_address_space[i] = &mem_region_unmapped;
nkeynes@931
   189
        break;
nkeynes@931
   190
    }
nkeynes@931
   191
}
.