Search
lxdream.org :: lxdream/src/sh4/cache.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/cache.c
changeset 971:886e1ec8447d
prev968:6fb1481859a4
next975:007bf7eb944f
author nkeynes
date Thu Jan 22 02:58:13 2009 +0000 (13 years ago)
permissions -rw-r--r--
last change Fix 1k-entry allocation
Break asid remap into two passes for simplicity
view annotate diff log raw
     1 /**
     2  * $Id$
     3  * Implements the on-chip operand cache, instruction cache, and store queue.
     4  *
     5  * Copyright (c) 2008 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 "dream.h"
    22 #include "mem.h"
    23 #include "mmio.h"
    24 #include "clock.h"
    25 #include "sh4/sh4core.h"
    26 #include "sh4/sh4mmio.h"
    27 #include "sh4/xltcache.h"
    28 #include "sh4/mmu.h"
    30 #define OCRAM_START (0x7C000000>>LXDREAM_PAGE_BITS)
    31 #define OCRAM_MID   (0x7E000000>>LXDREAM_PAGE_BITS)
    32 #define OCRAM_END   (0x80000000>>LXDREAM_PAGE_BITS)
    34 #define CACHE_VALID 1
    35 #define CACHE_DIRTY 2
    37 #define ICACHE_ENTRY_COUNT 256
    38 #define OCACHE_ENTRY_COUNT 512
    40 struct cache_line {
    41     uint32_t key;  // Fast address match - bits 5..28 for valid entry, -1 for invalid entry
    42     uint32_t tag;  // tag + flags value from the address field
    43 };    
    46 static struct cache_line ccn_icache[ICACHE_ENTRY_COUNT];
    47 struct cache_line ccn_ocache[OCACHE_ENTRY_COUNT];
    48 static unsigned char ccn_icache_data[ICACHE_ENTRY_COUNT*32];
    49 unsigned char ccn_ocache_data[OCACHE_ENTRY_COUNT*32];
    52 /*********************** General module requirements ********************/
    54 void CCN_reset()
    55 {
    56     /* Clear everything for consistency */
    57     memset( ccn_icache, 0, sizeof(ccn_icache) );
    58     memset( ccn_ocache, 0, sizeof(ccn_icache) );
    59     memset( ccn_icache_data, 0, sizeof(ccn_icache) );
    60     memset( ccn_ocache_data, 0, sizeof(ccn_icache) );
    61 }
    63 void CCN_save_state( FILE *f )
    64 {
    65     fwrite( &ccn_icache, sizeof(ccn_icache), 1, f );
    66     fwrite( &ccn_icache_data, sizeof(ccn_icache_data), 1, f );
    67     fwrite( &ccn_ocache, sizeof(ccn_ocache), 1, f);
    68     fwrite( &ccn_ocache_data, sizeof(ccn_ocache_data), 1, f);
    69 }
    71 int CCN_load_state( FILE *f )
    72 {
    73     /* Setup the cache mode according to the saved register value
    74      * (mem_load runs before this point to load all MMIO data)
    75      */
    76     mmio_region_MMU_write( CCR, MMIO_READ(MMU, CCR) );
    78     if( fread( &ccn_icache, sizeof(ccn_icache), 1, f ) != 1 ) {
    79         return 1;
    80     }
    81     if( fread( &ccn_icache_data, sizeof(ccn_icache_data), 1, f ) != 1 ) {
    82         return 1;
    83     }
    84     if( fread( &ccn_ocache, sizeof(ccn_ocache), 1, f ) != 1 ) {
    85         return 1;
    86     }
    87     if( fread( &ccn_ocache_data, sizeof(ccn_ocache_data), 1, f ) != 1 ) {
    88         return 1;
    89     }
    90     return 0;
    91 }
    93 /************************* OCRAM memory address space ************************/
    95 #define OCRAMPAGE0 (&ccn_ocache_data[4096])  /* Lines 128-255 */
    96 #define OCRAMPAGE1 (&ccn_ocache_data[12288]) /* Lines 384-511 */
    98 static int32_t FASTCALL ocram_page0_read_long( sh4addr_t addr )
    99 {
   100     return *((int32_t *)(OCRAMPAGE0 + (addr&0x00000FFF)));
   101 }
   102 static int32_t FASTCALL ocram_page0_read_word( sh4addr_t addr )
   103 {
   104     return SIGNEXT16(*((int16_t *)(OCRAMPAGE0 + (addr&0x00000FFF))));
   105 }
   106 static int32_t FASTCALL ocram_page0_read_byte( sh4addr_t addr )
   107 {
   108     return SIGNEXT8(*((int16_t *)(OCRAMPAGE0 + (addr&0x00000FFF))));
   109 }
   110 static void FASTCALL ocram_page0_write_long( sh4addr_t addr, uint32_t val )
   111 {
   112     *(uint32_t *)(OCRAMPAGE0 + (addr&0x00000FFF)) = val;
   113 }
   114 static void FASTCALL ocram_page0_write_word( sh4addr_t addr, uint32_t val )
   115 {
   116     *(uint16_t *)(OCRAMPAGE0 + (addr&0x00000FFF)) = (uint16_t)val;
   117 }
   118 static void FASTCALL ocram_page0_write_byte( sh4addr_t addr, uint32_t val )
   119 {
   120     *(uint8_t *)(OCRAMPAGE0 + (addr&0x00000FFF)) = (uint8_t)val;
   121 }
   122 static void FASTCALL ocram_page0_read_burst( unsigned char *dest, sh4addr_t addr )
   123 {
   124     memcpy( dest, OCRAMPAGE0+(addr&0x00000FFF), 32 );
   125 }
   126 static void FASTCALL ocram_page0_write_burst( sh4addr_t addr, unsigned char *src )
   127 {
   128     memcpy( OCRAMPAGE0+(addr&0x00000FFF), src, 32 );
   129 }
   131 struct mem_region_fn mem_region_ocram_page0 = {
   132         ocram_page0_read_long, ocram_page0_write_long,
   133         ocram_page0_read_word, ocram_page0_write_word,
   134         ocram_page0_read_byte, ocram_page0_write_byte,
   135         ocram_page0_read_burst, ocram_page0_write_burst,
   136         unmapped_prefetch };
   138 static int32_t FASTCALL ocram_page1_read_long( sh4addr_t addr )
   139 {
   140     return *((int32_t *)(OCRAMPAGE1 + (addr&0x00000FFF)));
   141 }
   142 static int32_t FASTCALL ocram_page1_read_word( sh4addr_t addr )
   143 {
   144     return SIGNEXT16(*((int16_t *)(OCRAMPAGE1 + (addr&0x00000FFF))));
   145 }
   146 static int32_t FASTCALL ocram_page1_read_byte( sh4addr_t addr )
   147 {
   148     return SIGNEXT8(*((int16_t *)(OCRAMPAGE1 + (addr&0x00000FFF))));
   149 }
   150 static void FASTCALL ocram_page1_write_long( sh4addr_t addr, uint32_t val )
   151 {
   152     *(uint32_t *)(OCRAMPAGE1 + (addr&0x00000FFF)) = val;
   153 }
   154 static void FASTCALL ocram_page1_write_word( sh4addr_t addr, uint32_t val )
   155 {
   156     *(uint16_t *)(OCRAMPAGE1 + (addr&0x00000FFF)) = (uint16_t)val;
   157 }
   158 static void FASTCALL ocram_page1_write_byte( sh4addr_t addr, uint32_t val )
   159 {
   160     *(uint8_t *)(OCRAMPAGE1 + (addr&0x00000FFF)) = (uint8_t)val;
   161 }
   162 static void FASTCALL ocram_page1_read_burst( unsigned char *dest, sh4addr_t addr )
   163 {
   164     memcpy( dest, OCRAMPAGE1+(addr&0x00000FFF), 32 );
   165 }
   166 static void FASTCALL ocram_page1_write_burst( sh4addr_t addr, unsigned char *src )
   167 {
   168     memcpy( OCRAMPAGE1+(addr&0x00000FFF), src, 32 );
   169 }
   171 struct mem_region_fn mem_region_ocram_page1 = {
   172         ocram_page1_read_long, ocram_page1_write_long,
   173         ocram_page1_read_word, ocram_page1_write_word,
   174         ocram_page1_read_byte, ocram_page1_write_byte,
   175         ocram_page1_read_burst, ocram_page1_write_burst,
   176         unmapped_prefetch };
   178 /**************************** Cache functions ********************************/
   179 char ccn_cache_map[16 MB]; // 24 bits of address space
   181 /**
   182  * Load a 32-byte cache line from external memory at the given ext address.
   183  * @param addr external address pre-masked to 1FFFFFFE0 
   184  */
   185 sh4addr_t FASTCALL ccn_ocache_load_line( sh4addr_t addr )
   186 {
   187     int entry = addr & 0x00003FE0;
   188     struct cache_line *line = &ccn_ocache[entry>>5];
   189     char *cache_data = &ccn_ocache_data[entry];
   190     sh4addr_t old_addr = line->tag;
   191     line->tag = addr & 0x1FFFFFE0;
   192     char oldstate = ccn_cache_map[old_addr>>5];
   193     ccn_cache_map[old_addr>>5] = 0;
   194     ccn_cache_map[addr>>5] = CACHE_VALID;
   195     if( oldstate == (CACHE_VALID|CACHE_DIRTY) ) {
   196         // Cache line is dirty - writeback. 
   197         ext_address_space[old_addr>>12]->write_burst(old_addr, cache_data);
   198     }
   199     ext_address_space[addr>>12]->read_burst(cache_data, addr & 0x1FFFFFE0);
   200     return addr;
   201 }
   203 /* Long read through the operand cache */
   204 /*
   205 int32_t FASTCALL ccn_ocache_read_long( sh4addr_t addr );
   206 int32_t FASTCALL ccn_ocache_read_word( sh4addr_t addr );
   207 int32_t FASTCALL ccn_ocache_read_byte( sh4addr_t addr );
   208 void FASTCALL ccn_ocache_write_long_copyback( sh4addr_t addr, uint32_t val );
   209 void FASTCALL ccn_ocache_write_word_copyback( sh4addr_t addr, uint32_t val );
   210 void FASTCALL ccn_ocache_write_byte_copyback( sh4addr_t addr, uint32_t val );
   212 */
   213 static int32_t FASTCALL ccn_ocache_read_long( sh4addr_t addr )
   214 {
   215     addr &= 0x1FFFFFFF;
   216     if( (ccn_cache_map[addr>>5] & CACHE_VALID) == 0 ) {
   217         ccn_ocache_load_line(addr);
   218     }
   219     return *(int32_t *)&ccn_ocache_data[addr & 0x3FFF];
   220 }
   222 static int32_t FASTCALL ccn_ocache_read_word( sh4addr_t addr )
   223 {
   224     addr &= 0x1FFFFFFF;
   225     if( (ccn_cache_map[addr>>5] & CACHE_VALID) == 0 ) {
   226         ccn_ocache_load_line(addr);
   227     }
   228     return SIGNEXT16(*(int16_t *)&ccn_ocache_data[addr&0x3FFF]);    
   229 }
   231 static int32_t FASTCALL ccn_ocache_read_byte( sh4addr_t addr )
   232 {
   233     addr &= 0x1FFFFFFF;
   234     if( (ccn_cache_map[addr>>5] & CACHE_VALID) == 0 ) {
   235         ccn_ocache_load_line(addr);
   236     }
   237     return SIGNEXT8(ccn_ocache_data[addr&0x3FFF]);        
   238 }
   240 static void FASTCALL ccn_ocache_write_long_copyback( sh4addr_t addr, uint32_t value )
   241 {
   242     addr &= 0x1FFFFFFF;
   243     if( (ccn_cache_map[addr>>5] & CACHE_VALID) == 0 ) {
   244         ccn_ocache_load_line(addr);
   245     }
   246     ccn_cache_map[addr>>5] |= CACHE_DIRTY;
   247     *(uint32_t *)&ccn_ocache_data[addr&0x3FFF] = value;
   248 }
   250 static void FASTCALL ccn_ocache_write_word_copyback( sh4addr_t addr, uint32_t value )
   251 {
   252     addr &= 0x1FFFFFFF;
   253     if( (ccn_cache_map[addr>>5] & CACHE_VALID) == 0 ) {
   254         ccn_ocache_load_line(addr);
   255     }
   256     ccn_cache_map[addr>>5] |= CACHE_DIRTY;
   257     *(uint16_t *)&ccn_ocache_data[addr&0x3FFF] = (uint16_t)value;
   258 }
   260 static void FASTCALL ccn_ocache_write_byte_copyback( sh4addr_t addr, uint32_t value )
   261 {
   262     addr &= 0x1FFFFFFF;
   263     if( (ccn_cache_map[addr>>5] & CACHE_VALID) == 0 ) {
   264         ccn_ocache_load_line(addr);
   265     }
   266     ccn_cache_map[addr>>5] |= CACHE_DIRTY;
   267     ccn_ocache_data[addr&0x3FFF] = (uint8_t)value;
   268 }
   270 static void FASTCALL ccn_ocache_prefetch( sh4addr_t addr )
   271 {
   272     addr &= 0x1FFFFFFF;
   273     if( (ccn_cache_map[addr>>5] & CACHE_VALID) == 0 ) {
   274         ccn_ocache_load_line(addr);
   275     }
   276 }
   278 void FASTCALL ccn_ocache_invalidate( sh4addr_t addr )
   279 {
   280     addr &= 0x1FFFFFFF;
   281     ccn_cache_map[addr>>5] &= ~CACHE_VALID;
   282 }
   284 void FASTCALL ccn_ocache_purge( sh4addr_t addr )
   285 {
   286     addr &= 0x1FFFFFE0;
   287     int oldflags = ccn_cache_map[addr>>5]; 
   288     ccn_cache_map[addr>>5] &= ~CACHE_VALID;
   289     if( oldflags == (CACHE_VALID|CACHE_DIRTY) ) {
   290         char *cache_data = &ccn_ocache_data[addr & 0x3FE0];
   291         ext_address_space[addr>>12]->write_burst(addr, cache_data);
   292     }
   293 }
   295 void FASTCALL ccn_ocache_writeback( sh4addr_t addr )
   296 {
   297     addr &= 0x1FFFFFE0;
   298     if( ccn_cache_map[addr>>5] == (CACHE_VALID|CACHE_DIRTY) ) {
   299         ccn_cache_map[addr>>5] &= ~CACHE_DIRTY;
   300         char *cache_data = &ccn_ocache_data[addr & 0x3FE0];
   301         ext_address_space[addr>>12]->write_burst(addr, cache_data);
   302     }
   303 }
   305 struct mem_region_fn ccn_ocache_cb_region = {
   306     ccn_ocache_read_long, ccn_ocache_write_long_copyback,
   307     ccn_ocache_read_word, ccn_ocache_write_word_copyback,
   308     ccn_ocache_read_byte, ccn_ocache_write_byte_copyback,
   309     unmapped_read_burst, unmapped_write_burst,
   310     ccn_ocache_prefetch };
   313 /************************** Cache direct access ******************************/
   315 static int32_t FASTCALL ccn_icache_addr_read( sh4addr_t addr )
   316 {
   317     int entry = (addr & 0x00001FE0);
   318     return ccn_icache[entry>>5].tag;
   319 }
   321 static void FASTCALL ccn_icache_addr_write( sh4addr_t addr, uint32_t val )
   322 {
   323     int entry = (addr & 0x00003FE0);
   324     struct cache_line *line = &ccn_ocache[entry>>5];
   325     if( addr & 0x08 ) { // Associative
   326         /* FIXME: implement this - requires ITLB lookups, with exception in case of multi-hit */
   327     } else {
   328         line->tag = val & 0x1FFFFC01;
   329         line->key = (val & 0x1FFFFC00)|(entry & 0x000003E0);
   330     }
   331 }
   333 struct mem_region_fn p4_region_icache_addr = {
   334         ccn_icache_addr_read, ccn_icache_addr_write,
   335         unmapped_read_long, unmapped_write_long,
   336         unmapped_read_long, unmapped_write_long,
   337         unmapped_read_burst, unmapped_write_burst,
   338         unmapped_prefetch };
   341 static int32_t FASTCALL ccn_icache_data_read( sh4addr_t addr )
   342 {
   343     int entry = (addr & 0x00001FFC);
   344     return *(uint32_t *)&ccn_icache_data[entry];
   345 }
   347 static void FASTCALL ccn_icache_data_write( sh4addr_t addr, uint32_t val )
   348 {
   349     int entry = (addr & 0x00001FFC);
   350     *(uint32_t *)&ccn_icache_data[entry] = val;    
   351 }
   353 struct mem_region_fn p4_region_icache_data = {
   354         ccn_icache_data_read, ccn_icache_data_write,
   355         unmapped_read_long, unmapped_write_long,
   356         unmapped_read_long, unmapped_write_long,
   357         unmapped_read_burst, unmapped_write_burst,
   358         unmapped_prefetch };
   360 static int32_t FASTCALL ccn_ocache_addr_read( sh4addr_t addr )
   361 {
   362     int entry = (addr & 0x00003FE0);
   363     sh4addr_t tag = ccn_ocache[entry>>5].tag;
   364     return (tag&0x1FFFFC00) | ccn_cache_map[tag>>5];
   365 }
   367 static void FASTCALL ccn_ocache_addr_write( sh4addr_t addr, uint32_t val )
   368 {
   369     int entry = (addr & 0x00003FE0);
   370     struct cache_line *line = &ccn_ocache[entry>>5];
   371     if( addr & 0x08 ) { // Associative
   372     } else {
   373         sh4addr_t tag = line->tag;
   374         if( ccn_cache_map[tag>>5] == (CACHE_VALID|CACHE_DIRTY) ) {
   375             // Cache line is dirty - writeback. 
   376             unsigned char *cache_data = &ccn_ocache_data[entry];
   377             ext_address_space[tag>>12]->write_burst(tag, cache_data);
   378         }
   379         line->tag = tag = (val & 0x1FFFFC00) | (addr & 0x3E0);
   380         ccn_cache_map[tag>>5] = val & 0x03;
   381     }
   382 }
   384 struct mem_region_fn p4_region_ocache_addr = {
   385         ccn_ocache_addr_read, ccn_ocache_addr_write,
   386         unmapped_read_long, unmapped_write_long,
   387         unmapped_read_long, unmapped_write_long,
   388         unmapped_read_burst, unmapped_write_burst,
   389         unmapped_prefetch };
   392 static int32_t FASTCALL ccn_ocache_data_read( sh4addr_t addr )
   393 {
   394     int entry = (addr & 0x00003FFC);
   395     return *(uint32_t *)&ccn_ocache_data[entry];
   396 }
   398 static void FASTCALL ccn_ocache_data_write( sh4addr_t addr, uint32_t val )
   399 {
   400     int entry = (addr & 0x00003FFC);
   401     *(uint32_t *)&ccn_ocache_data[entry] = val;
   402 }
   404 struct mem_region_fn p4_region_ocache_data = {
   405         ccn_ocache_data_read, ccn_ocache_data_write,
   406         unmapped_read_long, unmapped_write_long,
   407         unmapped_read_long, unmapped_write_long,
   408         unmapped_read_burst, unmapped_write_burst,
   409         unmapped_prefetch };
   412 /****************** Cache control *********************/
   414 void CCN_set_cache_control( int reg )
   415 {
   416     uint32_t i;
   418     if( reg & CCR_ICI ) { /* icache invalidate */
   419         for( i=0; i<ICACHE_ENTRY_COUNT; i++ ) {
   420             ccn_icache[i].key = -1;
   421             ccn_icache[i].tag &= ~CACHE_VALID;
   422         }
   423     }
   425     if( reg & CCR_OCI ) { /* ocache invalidate */
   426         for( i=0; i<OCACHE_ENTRY_COUNT; i++ ) {
   427             ccn_icache[i].key = -1;
   428             ccn_ocache[i].tag &= ~(CACHE_VALID|CACHE_DIRTY);
   429         }
   430     }
   432     switch( reg & (CCR_OIX|CCR_ORA|CCR_OCE) ) {
   433     case MEM_OC_INDEX0: /* OIX=0 */
   434         for( i=OCRAM_START; i<OCRAM_END; i+=4 ) {
   435             sh4_address_space[i] = &mem_region_ocram_page0;
   436             sh4_address_space[i+1] = &mem_region_ocram_page0;
   437             sh4_address_space[i+2] = &mem_region_ocram_page1;
   438             sh4_address_space[i+3] = &mem_region_ocram_page1;
   439         }
   440         break;
   441     case MEM_OC_INDEX1: /* OIX=1 */
   442         for( i=OCRAM_START; i<OCRAM_MID; i++ )
   443             sh4_address_space[i] = &mem_region_ocram_page0;
   444         for( i=OCRAM_MID; i<OCRAM_END; i++ )
   445             sh4_address_space[i] = &mem_region_ocram_page1;
   446         break;
   447     default: /* disabled */
   448         for( i=OCRAM_START; i<OCRAM_END; i++ )
   449             sh4_address_space[i] = &mem_region_unmapped;
   450         break;
   451     }
   452 }
   454 /**
   455  * Prefetch for non-storequeue regions
   456  */
   457 void FASTCALL ccn_prefetch( sh4addr_t addr )
   458 {
   460 }
   462 /************************** Uncached memory access ***************************/
   463 int32_t FASTCALL ccn_uncached_read_long( sh4addr_t addr )
   464 {
   465     sh4r.slice_cycle += (4*sh4_bus_period);
   466     addr &= 0x1FFFFFFF;
   467     return ext_address_space[addr>>12]->read_long(addr);
   468 }
   469 int32_t FASTCALL ccn_uncached_read_word( sh4addr_t addr )
   470 {
   471     sh4r.slice_cycle += (4*sh4_bus_period);
   472     addr &= 0x1FFFFFFF;
   473     return ext_address_space[addr>>12]->read_word(addr);
   474 }
   475 int32_t FASTCALL ccn_uncached_read_byte( sh4addr_t addr )
   476 {
   477     sh4r.slice_cycle += (4*sh4_bus_period);
   478     addr &= 0x1FFFFFFF;
   479     return ext_address_space[addr>>12]->read_byte(addr);
   480 }
   481 void FASTCALL ccn_uncached_write_long( sh4addr_t addr, uint32_t val )
   482 {
   483     sh4r.slice_cycle += (4*sh4_bus_period);
   484     addr &= 0x1FFFFFFF;
   485     return ext_address_space[addr>>12]->write_long(addr, val);
   486 }
   487 void FASTCALL ccn_uncached_write_word( sh4addr_t addr, uint32_t val )
   488 {
   489     sh4r.slice_cycle += (4*sh4_bus_period);
   490     addr &= 0x1FFFFFFF;
   491     return ext_address_space[addr>>12]->write_word(addr, val);
   492 }
   493 void FASTCALL ccn_uncached_write_byte( sh4addr_t addr, uint32_t val )
   494 {
   495     sh4r.slice_cycle += (4*sh4_bus_period);
   496     addr &= 0x1FFFFFFF;
   497     return ext_address_space[addr>>12]->write_byte(addr, val);
   498 }
   499 void FASTCALL ccn_uncached_prefetch( sh4addr_t addr )
   500 {
   501 }
   503 struct mem_region_fn ccn_uncached_region = {
   504         ccn_uncached_read_long, ccn_uncached_write_long,
   505         ccn_uncached_read_word, ccn_uncached_write_word,
   506         ccn_uncached_read_byte, ccn_uncached_write_byte,
   507         unmapped_read_burst, unmapped_write_burst,
   508         ccn_uncached_prefetch };
   511 /********************************* Store-queue *******************************/
   512 /*
   513  * The storequeue is strictly speaking part of the cache, but most of 
   514  * the complexity is actually around its addressing (ie in the MMU). The
   515  * methods here can assume we've already passed SQMD protection and the TLB
   516  * lookups (where appropriate).
   517  */  
   518 void FASTCALL ccn_storequeue_write_long( sh4addr_t addr, uint32_t val )
   519 {
   520     sh4r.store_queue[(addr>>2)&0xF] = val;
   521 }
   522 int32_t FASTCALL ccn_storequeue_read_long( sh4addr_t addr )
   523 {
   524     return sh4r.store_queue[(addr>>2)&0xF];
   525 }
   527 /**
   528  * Variant used when tlb is disabled - address will be the original prefetch
   529  * address (ie 0xE0001234). Due to the way the SQ addressing is done, it can't
   530  * be hardcoded on 4K page boundaries, so we manually decode it here.
   531  */
   532 void FASTCALL ccn_storequeue_prefetch( sh4addr_t addr ) 
   533 {
   534     int queue = (addr&0x20)>>2;
   535     sh4ptr_t src = (sh4ptr_t)&sh4r.store_queue[queue];
   536     uint32_t hi = MMIO_READ( MMU, QACR0 + (queue>>1)) << 24;
   537     sh4addr_t target = (addr&0x03FFFFE0) | hi;
   538     ext_address_space[target>>12]->write_burst( target, src );
   539 }
   541 /**
   542  * Variant used when tlb is enabled - address in this case is already
   543  * mapped to the external target address.
   544  */
   545 void FASTCALL ccn_storequeue_prefetch_tlb( sh4addr_t addr )
   546 {
   547     int queue = (addr&0x20)>>2;
   548     sh4ptr_t src = (sh4ptr_t)&sh4r.store_queue[queue];
   549     ext_address_space[addr>>12]->write_burst( (addr & 0x1FFFFFE0), src );
   550 }
.