Search
lxdream.org :: lxdream/src/sh4/sh4mem.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4mem.c
changeset 35:21a4be098304
prev10:c898b37506e0
next38:9ccc7ac66a9d
author nkeynes
date Mon Dec 26 03:54:55 2005 +0000 (14 years ago)
permissions -rw-r--r--
last change Remove modules.h - move definitions into dream.h
Add source string to output list (taken from module name)
ARM Work in progress
view annotate diff log raw
     1 /**
     2  * $Id: sh4mem.c,v 1.2 2005-12-26 03:54:55 nkeynes Exp $
     3  * sh4mem.c is responsible for the SH4's access to memory (including memory
     4  * mapped I/O), using the page maps created in mem.c
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    19 #define MODULE sh4_module
    21 #include <string.h>
    22 #include <zlib.h>
    23 #include "dream.h"
    24 #include "mem.h"
    25 #include "mmio.h"
    26 #include "sh4mmio.h"
    27 #include "dreamcast.h"
    29 #define OC_BASE 0x1C000000
    30 #define OC_TOP  0x20000000
    32 #define TRANSLATE_VIDEO_64BIT_ADDRESS(a)  ( (((a)&0x00FFFFF8)>>1)|(((a)&0x00000004)<<20)|((a)&0x03)|0x05000000 );
    34 #ifdef ENABLE_WATCH
    35 #define CHECK_READ_WATCH( addr, size ) \
    36     if( mem_is_watched(addr,size,WATCH_READ) != NULL ) { \
    37         WARN( "Watch triggered at %08X by %d byte read", addr, size ); \
    38         dreamcast_stop(); \
    39     }
    40 #define CHECK_WRITE_WATCH( addr, size, val )                  \
    41     if( mem_is_watched(addr,size,WATCH_WRITE) != NULL ) { \
    42         WARN( "Watch triggered at %08X by %d byte write <= %0*X", addr, size, size*2, val ); \
    43         dreamcast_stop(); \
    44     }
    45 #else
    46 #define CHECK_READ_WATCH( addr, size )
    47 #define CHECK_WRITE_WATCH( addr, size )
    48 #endif
    50 #define TRACE_IO( str, p, r, ... ) if(io_rgn[(uint32_t)p]->trace_flag) \
    51 TRACE( str " [%s.%s: %s]", __VA_ARGS__, \
    52     MMIO_NAME_BYNUM((uint32_t)p), MMIO_REGID_BYNUM((uint32_t)p, r), \
    53     MMIO_REGDESC_BYNUM((uint32_t)p, r) )
    55 extern struct mem_region mem_rgn[];
    56 extern struct mmio_region *P4_io[];
    58 int32_t sh4_read_p4( uint32_t addr )
    59 {
    60     struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
    61     if( !io ) {
    62         ERROR( "Attempted read from unknown P4 region: %08X", addr );
    63         return 0;
    64     } else {
    65         return io->io_read( addr&0xFFF );
    66     }    
    67 }
    69 void sh4_write_p4( uint32_t addr, int32_t val )
    70 {
    71     struct mmio_region *io = P4_io[(addr&0x1FFFFFFF)>>19];
    72     if( !io ) {
    73         if( (addr & 0xFC000000) == 0xE0000000 ) {
    74             /* Store queue */
    75             SH4_WRITE_STORE_QUEUE( addr, val );
    76         } else {
    77             ERROR( "Attempted write to unknown P4 region: %08X", addr );
    78         }
    79     } else {
    80         io->io_write( addr&0xFFF, val );
    81     }
    82 }
    84 int32_t sh4_read_phys_word( uint32_t addr )
    85 {
    86     char *page;
    87     if( addr > 0xE0000000 ) /* P4 Area, handled specially */
    88         return SIGNEXT16(sh4_read_p4( addr ));
    90     if( (addr&0x1F800000) == 0x04000000 ) {
    91         addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
    92     }
    94     page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
    95     if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
    96         if( page == NULL ) {
    97             ERROR( "Attempted word read to missing page: %08X",
    98                    addr );
    99             return 0;
   100         }
   101         return SIGNEXT16(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
   102     } else {
   103         return SIGNEXT16(*(int16_t *)(page+(addr&0xFFF)));
   104     }
   105 }
   107 int32_t sh4_read_long( uint32_t addr )
   108 {
   109     char *page;
   111     CHECK_READ_WATCH(addr,4);
   113     if( addr > 0xE0000000 ) /* P4 Area, handled specially */
   114         return sh4_read_p4( addr );
   116     if( (addr&0x1F800000) == 0x04000000 ) {
   117         addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
   118     }
   120     if( IS_MMU_ENABLED() ) {
   121         ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
   122         sh4_stop();
   123         return 0;
   124     }
   126     page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
   127     if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
   128         int32_t val;
   129         if( page == NULL ) {
   130             ERROR( "Attempted long read to missing page: %08X", addr );
   131             return 0;
   132         }
   133         val = io_rgn[(uint32_t)page]->io_read(addr&0xFFF);
   134         TRACE_IO( "Long read %08X <= %08X", page, (addr&0xFFF), val, addr );
   135         return val;
   136     } else {
   137         return *(int32_t *)(page+(addr&0xFFF));
   138     }
   139 }
   141 int32_t sh4_read_word( uint32_t addr )
   142 {
   143     char *page;
   145     CHECK_READ_WATCH(addr,2);
   147     if( addr > 0xE0000000 ) /* P4 Area, handled specially */
   148         return SIGNEXT16(sh4_read_p4( addr ));
   150     if( (addr&0x1F800000) == 0x04000000 ) {
   151         addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
   152     }
   154     if( IS_MMU_ENABLED() ) {
   155         ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
   156         sh4_stop();
   157         return 0;
   158     }
   160     page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
   161     if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
   162         int32_t val;
   163         if( page == NULL ) {
   164             ERROR( "Attempted word read to missing page: %08X", addr );
   165             return 0;
   166         }
   167         val = SIGNEXT16(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
   168         TRACE_IO( "Word read %04X <= %08X", page, (addr&0xFFF), val&0xFFFF, addr );
   169         return val;
   170     } else {
   171         return SIGNEXT16(*(int16_t *)(page+(addr&0xFFF)));
   172     }
   173 }
   175 int32_t sh4_read_byte( uint32_t addr )
   176 {
   177     char *page;
   179     CHECK_READ_WATCH(addr,1);
   181     if( addr > 0xE0000000 ) /* P4 Area, handled specially */
   182         return SIGNEXT8(sh4_read_p4( addr ));
   183     if( (addr&0x1F800000) == 0x04000000 ) {
   184         addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
   185     }
   187     if( IS_MMU_ENABLED() ) {
   188         ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
   189         sh4_stop();
   190         return 0;
   191     }
   193     page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
   194     if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
   195         int32_t val;
   196         if( page == NULL ) {
   197             ERROR( "Attempted byte read to missing page: %08X", addr );
   198             return 0;
   199         }
   200         val = SIGNEXT8(io_rgn[(uint32_t)page]->io_read(addr&0xFFF));
   201         TRACE_IO( "Byte read %02X <= %08X", page, (addr&0xFFF), val&0xFF, addr );
   202         return val;
   203     } else {
   204         return SIGNEXT8(*(int8_t *)(page+(addr&0xFFF)));
   205     }
   206 }
   208 void sh4_write_long( uint32_t addr, uint32_t val )
   209 {
   210     char *page;
   212     CHECK_WRITE_WATCH(addr,4,val);
   214     if( addr > 0xE0000000 ) {
   215         sh4_write_p4( addr, val );
   216         return;
   217     }
   218     if( (addr&0x1F800000) == 0x04000000 ) {
   219         addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
   220     }
   222     if( IS_MMU_ENABLED() ) {
   223         ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
   224         sh4_stop();
   225         return;
   226     }
   227     if( (addr&0x1FFFFFFF) < 0x200000 ) {
   228         ERROR( "Attempted write to read-only memory: %08X => %08X", val, addr);
   229         sh4_stop();
   230         return;
   231     }
   232     page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
   233     if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
   234         if( page == NULL ) {
   235             ERROR( "Long write to missing page: %08X => %08X", val, addr );
   236             return;
   237         }
   238         TRACE_IO( "Long write %08X => %08X", page, (addr&0xFFF), val, addr );
   239         io_rgn[(uint32_t)page]->io_write(addr&0xFFF, val);
   240     } else {
   241         *(uint32_t *)(page+(addr&0xFFF)) = val;
   242     }
   243 }
   245 void sh4_write_word( uint32_t addr, uint32_t val )
   246 {
   247     char *page;
   249     CHECK_WRITE_WATCH(addr,2,val);
   251     if( addr > 0xE0000000 ) {
   252         sh4_write_p4( addr, (int16_t)val );
   253         return;
   254     }
   255     if( (addr&0x1F800000) == 0x04000000 ) {
   256         addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
   257     }
   258     if( IS_MMU_ENABLED() ) {
   259         ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
   260         sh4_stop();
   261         return;
   262     }
   263     page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
   264     if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
   265         if( page == NULL ) {
   266             ERROR( "Attempted word write to missing page: %08X", addr );
   267             return;
   268         }
   269         TRACE_IO( "Word write %04X => %08X", page, (addr&0xFFF), val&0xFFFF, addr );
   270         io_rgn[(uint32_t)page]->io_write(addr&0xFFF, val);
   271     } else {
   272         *(uint16_t *)(page+(addr&0xFFF)) = val;
   273     }
   274 }
   276 void sh4_write_byte( uint32_t addr, uint32_t val )
   277 {
   278     char *page;
   280     CHECK_WRITE_WATCH(addr,1,val);
   282     if( addr > 0xE0000000 ) {
   283         sh4_write_p4( addr, (int8_t)val );
   284         return;
   285     }
   286     if( (addr&0x1F800000) == 0x04000000 ) {
   287         addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
   288     }
   290     if( IS_MMU_ENABLED() ) {
   291         ERROR( "user-mode & mmu translation not implemented, aborting", NULL );
   292         sh4_stop();
   293         return;
   294     }
   295     page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
   296     if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */
   297         if( page == NULL ) {
   298             ERROR( "Attempted byte write to missing page: %08X", addr );
   299             return;
   300         }
   301         TRACE_IO( "Byte write %02X => %08X", page, (addr&0xFFF), val&0xFF, addr );
   302         io_rgn[(uint32_t)page]->io_write( (addr&0xFFF), val);
   303     } else {
   304         *(uint8_t *)(page+(addr&0xFFF)) = val;
   305     }
   306 }
   310 /* FIXME: Handle all the many special cases when the range doesn't fall cleanly
   311  * into the same memory black
   312  */
   313 void mem_copy_from_sh4( char *dest, uint32_t srcaddr, size_t count ) {
   314     char *src = mem_get_region(srcaddr);
   315     memcpy( dest, src, count );
   316 }
   318 void mem_copy_to_sh4( uint32_t destaddr, char *src, size_t count ) {
   319     char *dest = mem_get_region(destaddr);
   320     memcpy( dest, src, count );
   321 }
.