Search
lxdream.org :: lxdream/src/sh4/cache.c :: diff
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
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/sh4/cache.c Tue Dec 23 05:48:05 2008 +0000
1.3 @@ -0,0 +1,191 @@
1.4 +/**
1.5 + * $Id$
1.6 + * Implements the on-chip operand cache and instruction caches
1.7 + *
1.8 + * Copyright (c) 2008 Nathan Keynes.
1.9 + *
1.10 + * This program is free software; you can redistribute it and/or modify
1.11 + * it under the terms of the GNU General Public License as published by
1.12 + * the Free Software Foundation; either version 2 of the License, or
1.13 + * (at your option) any later version.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful,
1.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.18 + * GNU General Public License for more details.
1.19 + */
1.20 +
1.21 +#define MODULE sh4_module
1.22 +
1.23 +#include <string.h>
1.24 +#include "dream.h"
1.25 +#include "mem.h"
1.26 +#include "mmio.h"
1.27 +#include "sh4/sh4core.h"
1.28 +#include "sh4/sh4mmio.h"
1.29 +#include "sh4/xltcache.h"
1.30 +
1.31 +#define OCRAM_START (0x7C000000>>LXDREAM_PAGE_BITS)
1.32 +#define OCRAM_MID (0x7E000000>>LXDREAM_PAGE_BITS)
1.33 +#define OCRAM_END (0x80000000>>LXDREAM_PAGE_BITS)
1.34 +
1.35 +#define CACHE_VALID 1
1.36 +#define CACHE_DIRTY 2
1.37 +
1.38 +#define ICACHE_ENTRY_COUNT 256
1.39 +#define OCACHE_ENTRY_COUNT 512
1.40 +
1.41 +struct cache_line {
1.42 + uint32_t key; // Fast address match - bits 5..28 for valid entry, -1 for invalid entry
1.43 + uint32_t tag; // tag + flags value from the address field
1.44 +};
1.45 +
1.46 +
1.47 +static struct cache_line ccn_icache[ICACHE_ENTRY_COUNT];
1.48 +static struct cache_line ccn_ocache[OCACHE_ENTRY_COUNT];
1.49 +static unsigned char ccn_icache_data[ICACHE_ENTRY_COUNT*32];
1.50 +static unsigned char ccn_ocache_data[OCACHE_ENTRY_COUNT*32];
1.51 +
1.52 +
1.53 +/*********************** General module requirements ********************/
1.54 +
1.55 +void CCN_save_state( FILE *f )
1.56 +{
1.57 + fwrite( &ccn_icache, sizeof(ccn_icache), 1, f );
1.58 + fwrite( &ccn_icache_data, sizeof(ccn_icache_data), 1, f );
1.59 + fwrite( &ccn_ocache, sizeof(ccn_ocache), 1, f);
1.60 + fwrite( &ccn_ocache_data, sizeof(ccn_ocache_data), 1, f);
1.61 +}
1.62 +
1.63 +int CCN_load_state( FILE *f )
1.64 +{
1.65 + /* Setup the cache mode according to the saved register value
1.66 + * (mem_load runs before this point to load all MMIO data)
1.67 + */
1.68 + mmio_region_MMU_write( CCR, MMIO_READ(MMU, CCR) );
1.69 +
1.70 + if( fread( &ccn_icache, sizeof(ccn_icache), 1, f ) != 1 ) {
1.71 + return 1;
1.72 + }
1.73 + if( fread( &ccn_icache_data, sizeof(ccn_icache_data), 1, f ) != 1 ) {
1.74 + return 1;
1.75 + }
1.76 + if( fread( &ccn_ocache, sizeof(ccn_ocache), 1, f ) != 1 ) {
1.77 + return 1;
1.78 + }
1.79 + if( fread( &ccn_ocache_data, sizeof(ccn_ocache_data), 1, f ) != 1 ) {
1.80 + return 1;
1.81 + }
1.82 + return 0;
1.83 +}
1.84 +
1.85 +
1.86 +/************************* OCRAM memory address space ************************/
1.87 +
1.88 +#define OCRAMPAGE0 (&ccn_ocache_data[4096]) /* Lines 128-255 */
1.89 +#define OCRAMPAGE1 (&ccn_ocache_data[12288]) /* Lines 384-511 */
1.90 +
1.91 +static int32_t FASTCALL ocram_page0_read_long( sh4addr_t addr )
1.92 +{
1.93 + return *((int32_t *)(OCRAMPAGE0 + (addr&0x00000FFF)));
1.94 +}
1.95 +static int32_t FASTCALL ocram_page0_read_word( sh4addr_t addr )
1.96 +{
1.97 + return SIGNEXT16(*((int16_t *)(OCRAMPAGE0 + (addr&0x00000FFF))));
1.98 +}
1.99 +static int32_t FASTCALL ocram_page0_read_byte( sh4addr_t addr )
1.100 +{
1.101 + return SIGNEXT8(*((int16_t *)(OCRAMPAGE0 + (addr&0x00000FFF))));
1.102 +}
1.103 +static void FASTCALL ocram_page0_write_long( sh4addr_t addr, uint32_t val )
1.104 +{
1.105 + *(uint32_t *)(OCRAMPAGE0 + (addr&0x00000FFF)) = val;
1.106 +}
1.107 +static void FASTCALL ocram_page0_write_word( sh4addr_t addr, uint32_t val )
1.108 +{
1.109 + *(uint16_t *)(OCRAMPAGE0 + (addr&0x00000FFF)) = (uint16_t)val;
1.110 +}
1.111 +static void FASTCALL ocram_page0_write_byte( sh4addr_t addr, uint32_t val )
1.112 +{
1.113 + *(uint8_t *)(OCRAMPAGE0 + (addr&0x00000FFF)) = (uint8_t)val;
1.114 +}
1.115 +static void FASTCALL ocram_page0_read_burst( unsigned char *dest, sh4addr_t addr )
1.116 +{
1.117 + memcpy( dest, OCRAMPAGE0+(addr&0x00000FFF), 32 );
1.118 +}
1.119 +static void FASTCALL ocram_page0_write_burst( sh4addr_t addr, unsigned char *src )
1.120 +{
1.121 + memcpy( OCRAMPAGE0+(addr&0x00000FFF), src, 32 );
1.122 +}
1.123 +
1.124 +struct mem_region_fn mem_region_ocram_page0 = {
1.125 + ocram_page0_read_long, ocram_page0_write_long,
1.126 + ocram_page0_read_word, ocram_page0_write_word,
1.127 + ocram_page0_read_byte, ocram_page0_write_byte,
1.128 + ocram_page0_read_burst, ocram_page0_write_burst };
1.129 +
1.130 +static int32_t FASTCALL ocram_page1_read_long( sh4addr_t addr )
1.131 +{
1.132 + return *((int32_t *)(OCRAMPAGE1 + (addr&0x00000FFF)));
1.133 +}
1.134 +static int32_t FASTCALL ocram_page1_read_word( sh4addr_t addr )
1.135 +{
1.136 + return SIGNEXT16(*((int16_t *)(OCRAMPAGE1 + (addr&0x00000FFF))));
1.137 +}
1.138 +static int32_t FASTCALL ocram_page1_read_byte( sh4addr_t addr )
1.139 +{
1.140 + return SIGNEXT8(*((int16_t *)(OCRAMPAGE1 + (addr&0x00000FFF))));
1.141 +}
1.142 +static void FASTCALL ocram_page1_write_long( sh4addr_t addr, uint32_t val )
1.143 +{
1.144 + *(uint32_t *)(OCRAMPAGE1 + (addr&0x00000FFF)) = val;
1.145 +}
1.146 +static void FASTCALL ocram_page1_write_word( sh4addr_t addr, uint32_t val )
1.147 +{
1.148 + *(uint16_t *)(OCRAMPAGE1 + (addr&0x00000FFF)) = (uint16_t)val;
1.149 +}
1.150 +static void FASTCALL ocram_page1_write_byte( sh4addr_t addr, uint32_t val )
1.151 +{
1.152 + *(uint8_t *)(OCRAMPAGE1 + (addr&0x00000FFF)) = (uint8_t)val;
1.153 +}
1.154 +static void FASTCALL ocram_page1_read_burst( unsigned char *dest, sh4addr_t addr )
1.155 +{
1.156 + memcpy( dest, OCRAMPAGE1+(addr&0x00000FFF), 32 );
1.157 +}
1.158 +static void FASTCALL ocram_page1_write_burst( sh4addr_t addr, unsigned char *src )
1.159 +{
1.160 + memcpy( OCRAMPAGE1+(addr&0x00000FFF), src, 32 );
1.161 +}
1.162 +
1.163 +struct mem_region_fn mem_region_ocram_page1 = {
1.164 + ocram_page1_read_long, ocram_page1_write_long,
1.165 + ocram_page1_read_word, ocram_page1_write_word,
1.166 + ocram_page1_read_byte, ocram_page1_write_byte,
1.167 + ocram_page1_read_burst, ocram_page1_write_burst };
1.168 +
1.169 +/****************** Cache control *********************/
1.170 +
1.171 +void CCN_set_cache_control( int reg )
1.172 +{
1.173 + uint32_t i;
1.174 + switch( reg & (CCR_OIX|CCR_ORA|CCR_OCE) ) {
1.175 + case MEM_OC_INDEX0: /* OIX=0 */
1.176 + for( i=OCRAM_START; i<OCRAM_END; i+=4 ) {
1.177 + sh4_address_space[i] = &mem_region_ocram_page0;
1.178 + sh4_address_space[i+1] = &mem_region_ocram_page0;
1.179 + sh4_address_space[i+2] = &mem_region_ocram_page1;
1.180 + sh4_address_space[i+3] = &mem_region_ocram_page1;
1.181 + }
1.182 + break;
1.183 + case MEM_OC_INDEX1: /* OIX=1 */
1.184 + for( i=OCRAM_START; i<OCRAM_MID; i++ )
1.185 + sh4_address_space[i] = &mem_region_ocram_page0;
1.186 + for( i=OCRAM_MID; i<OCRAM_END; i++ )
1.187 + sh4_address_space[i] = &mem_region_ocram_page1;
1.188 + break;
1.189 + default: /* disabled */
1.190 + for( i=OCRAM_START; i<OCRAM_END; i++ )
1.191 + sh4_address_space[i] = &mem_region_unmapped;
1.192 + break;
1.193 + }
1.194 +}
1.195 \ No newline at end of file
.