Search
lxdream.org :: lxdream/src/sh4/sh4mem.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4mem.c
changeset 400:049d72a7a229
prev371:f2fe152cfc9b
next406:9289b62f8f33
author nkeynes
date Thu Sep 20 08:35:04 2007 +0000 (13 years ago)
permissions -rw-r--r--
last change Add translation cache invalidation
file annotate diff log raw
nkeynes@10
     1
/**
nkeynes@400
     2
 * $Id: sh4mem.c,v 1.23 2007-09-20 08:35:04 nkeynes Exp $
nkeynes@10
     3
 * sh4mem.c is responsible for the SH4's access to memory (including memory
nkeynes@10
     4
 * mapped I/O), using the page maps created in mem.c
nkeynes@10
     5
 *
nkeynes@10
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@10
     7
 *
nkeynes@10
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@10
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@10
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@10
    11
 * (at your option) any later version.
nkeynes@10
    12
 *
nkeynes@10
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@10
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@10
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@10
    16
 * GNU General Public License for more details.
nkeynes@10
    17
 */
nkeynes@10
    18
nkeynes@35
    19
#define MODULE sh4_module
nkeynes@35
    20
nkeynes@10
    21
#include <string.h>
nkeynes@10
    22
#include <zlib.h>
nkeynes@10
    23
#include "dream.h"
nkeynes@10
    24
#include "mem.h"
nkeynes@10
    25
#include "mmio.h"
nkeynes@70
    26
#include "sh4core.h"
nkeynes@10
    27
#include "sh4mmio.h"
nkeynes@10
    28
#include "dreamcast.h"
nkeynes@100
    29
#include "pvr2/pvr2.h"
nkeynes@10
    30
nkeynes@10
    31
#define OC_BASE 0x1C000000
nkeynes@10
    32
#define OC_TOP  0x20000000
nkeynes@10
    33
nkeynes@90
    34
#define TRANSLATE_VIDEO_64BIT_ADDRESS(a)  ( (((a)&0x00FFFFF8)>>1)|(((a)&0x00000004)<<20)|((a)&0x03)|0x05000000 )
nkeynes@10
    35
nkeynes@10
    36
#ifdef ENABLE_WATCH
nkeynes@10
    37
#define CHECK_READ_WATCH( addr, size ) \
nkeynes@10
    38
    if( mem_is_watched(addr,size,WATCH_READ) != NULL ) { \
nkeynes@10
    39
        WARN( "Watch triggered at %08X by %d byte read", addr, size ); \
nkeynes@10
    40
        dreamcast_stop(); \
nkeynes@10
    41
    }
nkeynes@10
    42
#define CHECK_WRITE_WATCH( addr, size, val )                  \
nkeynes@10
    43
    if( mem_is_watched(addr,size,WATCH_WRITE) != NULL ) { \
nkeynes@10
    44
        WARN( "Watch triggered at %08X by %d byte write <= %0*X", addr, size, size*2, val ); \
nkeynes@10
    45
        dreamcast_stop(); \
nkeynes@10
    46
    }
nkeynes@10
    47
#else
nkeynes@10
    48
#define CHECK_READ_WATCH( addr, size )
nkeynes@234
    49
#define CHECK_WRITE_WATCH( addr, size, val )
nkeynes@10
    50
#endif
nkeynes@10
    51
nkeynes@172
    52
#define TRACE_IO( str, p, r, ... ) if(io_rgn[(uint32_t)p]->trace_flag && !MMIO_NOTRACE_BYNUM((uint32_t)p,r)) \
nkeynes@172
    53
    TRACE( str " [%s.%s: %s]", __VA_ARGS__,			       \
nkeynes@10
    54
    MMIO_NAME_BYNUM((uint32_t)p), MMIO_REGID_BYNUM((uint32_t)p, r), \
nkeynes@10
    55
    MMIO_REGDESC_BYNUM((uint32_t)p, r) )
nkeynes@172
    56
#define TRACE_P4IO( str, io, r, ... ) if(io->trace_flag && !MMIO_NOTRACE_IOBYNUM(io,r)) \
nkeynes@156
    57
TRACE( str " [%s.%s: %s]", __VA_ARGS__, \
nkeynes@156
    58
    io->id, MMIO_REGID_IOBYNUM(io, r), \
nkeynes@156
    59
    MMIO_REGDESC_IOBYNUM(io, r) )
nkeynes@10
    60
nkeynes@10
    61
extern struct mem_region mem_rgn[];
nkeynes@10
    62
extern struct mmio_region *P4_io[];
nkeynes@10
    63
nkeynes@10
    64
int32_t sh4_read_p4( uint32_t addr )
nkeynes@10
    65
{
nkeynes@10
    66
    struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
nkeynes@10
    67
    if( !io ) {
nkeynes@282
    68
        if( (addr & 0xFF000000) != 0xF4000000 ) {
nkeynes@282
    69
	    /* OC address cache isn't implemented, but don't complain about it.
nkeynes@282
    70
	     * Complain about anything else though */
nkeynes@282
    71
            ERROR( "Attempted read from unknown P4 region: %08X", addr );
nkeynes@282
    72
        }
nkeynes@10
    73
        return 0;
nkeynes@10
    74
    } else {
nkeynes@156
    75
	int32_t val = io->io_read( addr&0xFFF );
nkeynes@156
    76
	TRACE_P4IO( "Long read %08X <= %08X", io, (addr&0xFFF), val, addr );
nkeynes@156
    77
        return val;
nkeynes@10
    78
    }    
nkeynes@10
    79
}
nkeynes@10
    80
nkeynes@10
    81
void sh4_write_p4( uint32_t addr, int32_t val )
nkeynes@10
    82
{
nkeynes@10
    83
    struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
nkeynes@10
    84
    if( !io ) {
nkeynes@10
    85
        if( (addr & 0xFC000000) == 0xE0000000 ) {
nkeynes@10
    86
            /* Store queue */
nkeynes@10
    87
            SH4_WRITE_STORE_QUEUE( addr, val );
nkeynes@38
    88
        } else if( (addr & 0xFF000000) != 0xF4000000 ) {
nkeynes@38
    89
	    /* OC address cache isn't implemented, but don't complain about it.
nkeynes@38
    90
	     * Complain about anything else though */
nkeynes@10
    91
            ERROR( "Attempted write to unknown P4 region: %08X", addr );
nkeynes@10
    92
        }
nkeynes@10
    93
    } else {
nkeynes@156
    94
	TRACE_P4IO( "Long write %08X => %08X", io, (addr&0xFFF), val, addr );
nkeynes@10
    95
        io->io_write( addr&0xFFF, val );
nkeynes@10
    96
    }
nkeynes@10
    97
}
nkeynes@10
    98
nkeynes@10
    99
int32_t sh4_read_phys_word( uint32_t addr )
nkeynes@10
   100
{
nkeynes@10
   101
    char *page;
nkeynes@83
   102
    if( addr >= 0xE0000000 ) /* P4 Area, handled specially */
nkeynes@10
   103
        return SIGNEXT16(sh4_read_p4( addr ));
nkeynes@10
   104
    
nkeynes@10
   105
    if( (addr&0x1F800000) == 0x04000000 ) {
nkeynes@10
   106
        addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
nkeynes@10
   107
    }
nkeynes@10
   108
nkeynes@10
   109
    page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
nkeynes@10
   110
    if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
nkeynes@10
   111
        if( page == NULL ) {
nkeynes@10
   112
            ERROR( "Attempted word read to missing page: %08X",
nkeynes@10
   113
                   addr );
nkeynes@10
   114
            return 0;
nkeynes@10
   115
        }
nkeynes@10
   116
        return SIGNEXT16(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
nkeynes@10
   117
    } else {
nkeynes@10
   118
        return SIGNEXT16(*(int16_t *)(page+(addr&0xFFF)));
nkeynes@10
   119
    }
nkeynes@10
   120
}
nkeynes@10
   121
nkeynes@10
   122
int32_t sh4_read_long( uint32_t addr )
nkeynes@10
   123
{
nkeynes@10
   124
    char *page;
nkeynes@10
   125
    
nkeynes@10
   126
    CHECK_READ_WATCH(addr,4);
nkeynes@10
   127
nkeynes@83
   128
    if( addr >= 0xE0000000 ) /* P4 Area, handled specially */
nkeynes@10
   129
        return sh4_read_p4( addr );
nkeynes@10
   130
    
nkeynes@10
   131
    if( (addr&0x1F800000) == 0x04000000 ) {
nkeynes@10
   132
        addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
nkeynes@355
   133
	pvr2_render_buffer_invalidate(addr, FALSE);
nkeynes@217
   134
    } else if( (addr&0x1F800000) == 0x05000000 ) {
nkeynes@355
   135
	pvr2_render_buffer_invalidate(addr, FALSE);
nkeynes@10
   136
    }
nkeynes@10
   137
nkeynes@10
   138
    if( IS_MMU_ENABLED() ) {
nkeynes@10
   139
        ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
nkeynes@10
   140
        sh4_stop();
nkeynes@10
   141
        return 0;
nkeynes@10
   142
    }
nkeynes@10
   143
nkeynes@10
   144
    page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
nkeynes@10
   145
    if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
nkeynes@10
   146
        int32_t val;
nkeynes@10
   147
        if( page == NULL ) {
nkeynes@10
   148
            ERROR( "Attempted long read to missing page: %08X", addr );
nkeynes@10
   149
            return 0;
nkeynes@10
   150
        }
nkeynes@10
   151
        val = io_rgn[(uint32_t)page]->io_read(addr&0xFFF);
nkeynes@10
   152
        TRACE_IO( "Long read %08X <= %08X", page, (addr&0xFFF), val, addr );
nkeynes@10
   153
        return val;
nkeynes@10
   154
    } else {
nkeynes@400
   155
	// fprintf( stderr, "MOV.L %08X <= %08X\n",*(int32_t *)(page+(addr&0xFFF)), addr );
nkeynes@10
   156
        return *(int32_t *)(page+(addr&0xFFF));
nkeynes@10
   157
    }
nkeynes@10
   158
}
nkeynes@10
   159
nkeynes@10
   160
int32_t sh4_read_word( uint32_t addr )
nkeynes@10
   161
{
nkeynes@10
   162
    char *page;
nkeynes@10
   163
nkeynes@10
   164
    CHECK_READ_WATCH(addr,2);
nkeynes@10
   165
nkeynes@83
   166
    if( addr >= 0xE0000000 ) /* P4 Area, handled specially */
nkeynes@10
   167
        return SIGNEXT16(sh4_read_p4( addr ));
nkeynes@10
   168
    
nkeynes@10
   169
    if( (addr&0x1F800000) == 0x04000000 ) {
nkeynes@10
   170
        addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
nkeynes@355
   171
	pvr2_render_buffer_invalidate(addr, FALSE);
nkeynes@217
   172
    } else if( (addr&0x1F800000) == 0x05000000 ) {
nkeynes@355
   173
	pvr2_render_buffer_invalidate(addr, FALSE);
nkeynes@10
   174
    }
nkeynes@217
   175
    
nkeynes@10
   176
nkeynes@10
   177
    if( IS_MMU_ENABLED() ) {
nkeynes@10
   178
        ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
nkeynes@10
   179
        sh4_stop();
nkeynes@10
   180
        return 0;
nkeynes@10
   181
    }
nkeynes@10
   182
nkeynes@10
   183
    page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
nkeynes@10
   184
    if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
nkeynes@10
   185
        int32_t val;
nkeynes@10
   186
        if( page == NULL ) {
nkeynes@10
   187
            ERROR( "Attempted word read to missing page: %08X", addr );
nkeynes@10
   188
            return 0;
nkeynes@10
   189
        }
nkeynes@10
   190
        val = SIGNEXT16(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
nkeynes@10
   191
        TRACE_IO( "Word read %04X <= %08X", page, (addr&0xFFF), val&0xFFFF, addr );
nkeynes@10
   192
        return val;
nkeynes@10
   193
    } else {
nkeynes@10
   194
        return SIGNEXT16(*(int16_t *)(page+(addr&0xFFF)));
nkeynes@10
   195
    }
nkeynes@10
   196
}
nkeynes@10
   197
nkeynes@10
   198
int32_t sh4_read_byte( uint32_t addr )
nkeynes@10
   199
{
nkeynes@10
   200
    char *page;
nkeynes@10
   201
nkeynes@10
   202
    CHECK_READ_WATCH(addr,1);
nkeynes@10
   203
nkeynes@83
   204
    if( addr >= 0xE0000000 ) /* P4 Area, handled specially */
nkeynes@10
   205
        return SIGNEXT8(sh4_read_p4( addr ));
nkeynes@10
   206
    if( (addr&0x1F800000) == 0x04000000 ) {
nkeynes@10
   207
        addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
nkeynes@355
   208
    	pvr2_render_buffer_invalidate(addr, FALSE);
nkeynes@217
   209
    } else if( (addr&0x1F800000) == 0x05000000 ) {
nkeynes@355
   210
	pvr2_render_buffer_invalidate(addr, FALSE);
nkeynes@10
   211
    }
nkeynes@217
   212
nkeynes@10
   213
    
nkeynes@10
   214
    if( IS_MMU_ENABLED() ) {
nkeynes@10
   215
        ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
nkeynes@10
   216
        sh4_stop();
nkeynes@10
   217
        return 0;
nkeynes@10
   218
    }
nkeynes@10
   219
nkeynes@10
   220
    page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
nkeynes@10
   221
    if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
nkeynes@10
   222
        int32_t val;
nkeynes@10
   223
        if( page == NULL ) {
nkeynes@10
   224
            ERROR( "Attempted byte read to missing page: %08X", addr );
nkeynes@10
   225
            return 0;
nkeynes@10
   226
        }
nkeynes@10
   227
        val = SIGNEXT8(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
nkeynes@10
   228
        TRACE_IO( "Byte read %02X <= %08X", page, (addr&0xFFF), val&0xFF, addr );
nkeynes@10
   229
        return val;
nkeynes@10
   230
    } else {
nkeynes@400
   231
	//	fprintf( stderr, "MOV.B %02X <= %08X\n",(uint32_t)*(uint8_t *)(page+(addr&0xFFF)), addr );
nkeynes@10
   232
        return SIGNEXT8(*(int8_t *)(page+(addr&0xFFF)));
nkeynes@10
   233
    }
nkeynes@10
   234
}
nkeynes@10
   235
nkeynes@10
   236
void sh4_write_long( uint32_t addr, uint32_t val )
nkeynes@10
   237
{
nkeynes@10
   238
    char *page;
nkeynes@400
   239
nkeynes@400
   240
    // fprintf( stderr, "MOV.L %08X => %08X\n", val, addr );
nkeynes@10
   241
    CHECK_WRITE_WATCH(addr,4,val);
nkeynes@10
   242
nkeynes@83
   243
    if( addr >= 0xE0000000 ) {
nkeynes@10
   244
        sh4_write_p4( addr, val );
nkeynes@10
   245
        return;
nkeynes@10
   246
    }
nkeynes@130
   247
    if( (addr&0x1F800000) == 0x04000000 || 
nkeynes@130
   248
	(addr&0x1F800000) == 0x11000000 ) {
nkeynes@150
   249
	texcache_invalidate_page(addr& 0x7FFFFF);
nkeynes@10
   250
        addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
nkeynes@355
   251
	pvr2_render_buffer_invalidate(addr, TRUE);
nkeynes@165
   252
    } else if( (addr&0x1F800000) == 0x05000000 ) {
nkeynes@355
   253
	pvr2_render_buffer_invalidate(addr, TRUE);
nkeynes@10
   254
    }
nkeynes@10
   255
nkeynes@10
   256
    if( IS_MMU_ENABLED() ) {
nkeynes@10
   257
        ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
nkeynes@10
   258
        sh4_stop();
nkeynes@10
   259
        return;
nkeynes@10
   260
    }
nkeynes@10
   261
    if( (addr&0x1FFFFFFF) < 0x200000 ) {
nkeynes@10
   262
        ERROR( "Attempted write to read-only memory: %08X => %08X", val, addr);
nkeynes@10
   263
        sh4_stop();
nkeynes@10
   264
        return;
nkeynes@10
   265
    }
nkeynes@137
   266
    if( (addr&0x1F800000) == 0x00800000 )
nkeynes@137
   267
	asic_g2_write_word();
nkeynes@137
   268
nkeynes@10
   269
    page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
nkeynes@10
   270
    if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
nkeynes@10
   271
        if( page == NULL ) {
nkeynes@137
   272
	    if( (addr & 0x1F000000) >= 0x04000000 &&
nkeynes@137
   273
		(addr & 0x1F000000) < 0x07000000 )
nkeynes@137
   274
		return;
nkeynes@10
   275
            ERROR( "Long write to missing page: %08X => %08X", val, addr );
nkeynes@10
   276
            return;
nkeynes@10
   277
        }
nkeynes@10
   278
        TRACE_IO( "Long write %08X => %08X", page, (addr&0xFFF), val, addr );
nkeynes@10
   279
        io_rgn[(uint32_t)page]->io_write(addr&0xFFF, val);
nkeynes@10
   280
    } else {
nkeynes@400
   281
	xlat_invalidate_long(addr);
nkeynes@10
   282
        *(uint32_t *)(page+(addr&0xFFF)) = val;
nkeynes@10
   283
    }
nkeynes@10
   284
}
nkeynes@10
   285
nkeynes@10
   286
void sh4_write_word( uint32_t addr, uint32_t val )
nkeynes@10
   287
{
nkeynes@10
   288
    char *page;
nkeynes@10
   289
nkeynes@400
   290
    //    fprintf( stderr, "MOV.W %04X => %08X\n", val, addr );
nkeynes@10
   291
    CHECK_WRITE_WATCH(addr,2,val);
nkeynes@10
   292
nkeynes@83
   293
    if( addr >= 0xE0000000 ) {
nkeynes@10
   294
        sh4_write_p4( addr, (int16_t)val );
nkeynes@10
   295
        return;
nkeynes@10
   296
    }
nkeynes@130
   297
    if( (addr&0x1F800000) == 0x04000000 ||
nkeynes@130
   298
	(addr&0x1F800000) == 0x11000000 ) {
nkeynes@150
   299
	texcache_invalidate_page(addr& 0x7FFFFF);
nkeynes@10
   300
        addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
nkeynes@355
   301
	pvr2_render_buffer_invalidate(addr, TRUE);
nkeynes@165
   302
    } else if( (addr&0x1F800000) == 0x05000000 ) {
nkeynes@355
   303
	pvr2_render_buffer_invalidate(addr, TRUE);
nkeynes@10
   304
    }
nkeynes@10
   305
    if( IS_MMU_ENABLED() ) {
nkeynes@10
   306
        ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
nkeynes@10
   307
        sh4_stop();
nkeynes@10
   308
        return;
nkeynes@10
   309
    }
nkeynes@400
   310
    if( (addr&0x1FFFFFFF) < 0x200000 ) {
nkeynes@400
   311
        ERROR( "Attempted write to read-only memory: %08X => %08X", val, addr);
nkeynes@400
   312
        sh4_stop();
nkeynes@400
   313
        return;
nkeynes@400
   314
    }
nkeynes@10
   315
    page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
nkeynes@10
   316
    if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
nkeynes@10
   317
        if( page == NULL ) {
nkeynes@10
   318
            ERROR( "Attempted word write to missing page: %08X", addr );
nkeynes@10
   319
            return;
nkeynes@10
   320
        }
nkeynes@10
   321
        TRACE_IO( "Word write %04X => %08X", page, (addr&0xFFF), val&0xFFFF, addr );
nkeynes@10
   322
        io_rgn[(uint32_t)page]->io_write(addr&0xFFF, val);
nkeynes@10
   323
    } else {
nkeynes@400
   324
	xlat_invalidate_word(addr);
nkeynes@10
   325
        *(uint16_t *)(page+(addr&0xFFF)) = val;
nkeynes@10
   326
    }
nkeynes@10
   327
}
nkeynes@10
   328
nkeynes@10
   329
void sh4_write_byte( uint32_t addr, uint32_t val )
nkeynes@10
   330
{
nkeynes@10
   331
    char *page;
nkeynes@10
   332
    
nkeynes@400
   333
    //    fprintf( stderr, "MOV.B %02X => %08X\n", val, addr );
nkeynes@10
   334
    CHECK_WRITE_WATCH(addr,1,val);
nkeynes@10
   335
nkeynes@83
   336
    if( addr >= 0xE0000000 ) {
nkeynes@10
   337
        sh4_write_p4( addr, (int8_t)val );
nkeynes@10
   338
        return;
nkeynes@10
   339
    }
nkeynes@130
   340
    if( (addr&0x1F800000) == 0x04000000 ||
nkeynes@130
   341
	(addr&0x1F800000) == 0x11000000 ) {
nkeynes@150
   342
	texcache_invalidate_page(addr& 0x7FFFFF);
nkeynes@10
   343
        addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
nkeynes@355
   344
	pvr2_render_buffer_invalidate(addr, TRUE);
nkeynes@165
   345
    } else if( (addr&0x1F800000) == 0x05000000 ) {
nkeynes@355
   346
	pvr2_render_buffer_invalidate(addr, TRUE);
nkeynes@10
   347
    }
nkeynes@10
   348
    
nkeynes@10
   349
    if( IS_MMU_ENABLED() ) {
nkeynes@10
   350
        ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
nkeynes@10
   351
        sh4_stop();
nkeynes@10
   352
        return;
nkeynes@10
   353
    }
nkeynes@400
   354
    if( (addr&0x1FFFFFFF) < 0x200000 ) {
nkeynes@400
   355
        ERROR( "Attempted write to read-only memory: %08X => %08X", val, addr);
nkeynes@400
   356
        sh4_stop();
nkeynes@400
   357
        return;
nkeynes@400
   358
    }
nkeynes@10
   359
    page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
nkeynes@10
   360
    if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
nkeynes@10
   361
        if( page == NULL ) {
nkeynes@10
   362
            ERROR( "Attempted byte write to missing page: %08X", addr );
nkeynes@10
   363
            return;
nkeynes@10
   364
        }
nkeynes@10
   365
        TRACE_IO( "Byte write %02X => %08X", page, (addr&0xFFF), val&0xFF, addr );
nkeynes@10
   366
        io_rgn[(uint32_t)page]->io_write( (addr&0xFFF), val);
nkeynes@10
   367
    } else {
nkeynes@400
   368
	xlat_invalidate_word(addr);
nkeynes@10
   369
        *(uint8_t *)(page+(addr&0xFFF)) = val;
nkeynes@10
   370
    }
nkeynes@10
   371
}
nkeynes@10
   372
nkeynes@10
   373
nkeynes@10
   374
nkeynes@10
   375
/* FIXME: Handle all the many special cases when the range doesn't fall cleanly
nkeynes@400
   376
 * into the same memory block
nkeynes@10
   377
 */
nkeynes@10
   378
void mem_copy_from_sh4( char *dest, uint32_t srcaddr, size_t count ) {
nkeynes@103
   379
    if( srcaddr >= 0x04000000 && srcaddr < 0x05000000 ) {
nkeynes@103
   380
	pvr2_vram64_read( dest, srcaddr, count );
nkeynes@103
   381
    } else {
nkeynes@103
   382
	char *src = mem_get_region(srcaddr);
nkeynes@103
   383
	if( src == NULL ) {
nkeynes@103
   384
	    ERROR( "Attempted block read from unknown address %08X", srcaddr );
nkeynes@103
   385
	} else {
nkeynes@103
   386
	    memcpy( dest, src, count );
nkeynes@103
   387
	}
nkeynes@103
   388
    }
nkeynes@10
   389
}
nkeynes@10
   390
nkeynes@10
   391
void mem_copy_to_sh4( uint32_t destaddr, char *src, size_t count ) {
nkeynes@325
   392
    int region;
nkeynes@325
   393
nkeynes@325
   394
    if( destaddr >= 0x10000000 && destaddr < 0x14000000 ) {
nkeynes@325
   395
	pvr2_dma_write( destaddr, src, count );
nkeynes@325
   396
	return;
nkeynes@325
   397
    } else if( (destaddr & 0x1F800000) == 0x05000000 ) {
nkeynes@355
   398
	pvr2_render_buffer_invalidate( destaddr, TRUE );
nkeynes@325
   399
    } else if( (destaddr & 0x1F800000) == 0x04000000 ) {
nkeynes@103
   400
	pvr2_vram64_write( destaddr, src, count );
nkeynes@325
   401
	return;
nkeynes@325
   402
    }
nkeynes@325
   403
    char *dest = mem_get_region(destaddr);
nkeynes@325
   404
    if( dest == NULL )
nkeynes@325
   405
	ERROR( "Attempted block write to unknown address %08X", destaddr );
nkeynes@325
   406
    else {
nkeynes@400
   407
	xlat_invalidate_block( destaddr, count );
nkeynes@325
   408
	memcpy( dest, src, count );
nkeynes@90
   409
    }
nkeynes@10
   410
}
nkeynes@369
   411
nkeynes@369
   412
void sh4_flush_store_queue( uint32_t addr )
nkeynes@369
   413
{
nkeynes@369
   414
    /* Store queue operation */
nkeynes@369
   415
    int queue = (addr&0x20)>>2;
nkeynes@371
   416
    char *src = (char *)&sh4r.store_queue[queue];
nkeynes@369
   417
    uint32_t hi = (MMIO_READ( MMU, (queue == 0 ? QACR0 : QACR1) ) & 0x1C) << 24;
nkeynes@369
   418
    uint32_t target = addr&0x03FFFFE0 | hi;
nkeynes@369
   419
    mem_copy_to_sh4( target, src, 32 );
nkeynes@369
   420
}
.