Search
lxdream.org :: lxdream/src/aica/armmem.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armmem.c
changeset 934:3acd3b3ee6d1
prev931:430048ea8b71
next1067:d3c00ffccfcd
author nkeynes
date Fri Dec 26 14:25:23 2008 +0000 (15 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change Change RAM regions to use static arrays rather than mmap regions, for a 2-3% performance gain.
General mem cleanups, including some save state fixes that break states again.
file annotate diff log raw
nkeynes@934
     1
/*`*
nkeynes@561
     2
 * $Id$
nkeynes@31
     3
 *
nkeynes@31
     4
 * Implements the ARM's memory map.
nkeynes@31
     5
 *
nkeynes@31
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@31
     7
 *
nkeynes@31
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@31
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@31
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@31
    11
 * (at your option) any later version.
nkeynes@31
    12
 *
nkeynes@31
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@31
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@31
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@31
    16
 * GNU General Public License for more details.
nkeynes@31
    17
 */
nkeynes@31
    18
nkeynes@11
    19
#include <stdlib.h>
nkeynes@11
    20
#include "dream.h"
nkeynes@7
    21
#include "mem.h"
nkeynes@66
    22
#include "aica.h"
nkeynes@811
    23
#include "armcore.h"
nkeynes@7
    24
nkeynes@934
    25
unsigned char aica_main_ram[2 MB];
nkeynes@934
    26
unsigned char aica_scratch_ram[8 KB];
nkeynes@7
    27
nkeynes@931
    28
/*************** ARM memory access function blocks **************/
nkeynes@931
    29
nkeynes@931
    30
static int32_t FASTCALL ext_audioram_read_long( sh4addr_t addr )
nkeynes@931
    31
{
nkeynes@934
    32
    return *((int32_t *)(aica_main_ram + (addr&0x001FFFFF)));
nkeynes@931
    33
}
nkeynes@931
    34
static int32_t FASTCALL ext_audioram_read_word( sh4addr_t addr )
nkeynes@931
    35
{
nkeynes@934
    36
    return SIGNEXT16(*((int16_t *)(aica_main_ram + (addr&0x001FFFFF))));
nkeynes@931
    37
}
nkeynes@931
    38
static int32_t FASTCALL ext_audioram_read_byte( sh4addr_t addr )
nkeynes@931
    39
{
nkeynes@934
    40
    return SIGNEXT8(*((int16_t *)(aica_main_ram + (addr&0x001FFFFF))));
nkeynes@931
    41
}
nkeynes@931
    42
static void FASTCALL ext_audioram_write_long( sh4addr_t addr, uint32_t val )
nkeynes@931
    43
{
nkeynes@934
    44
    *(uint32_t *)(aica_main_ram + (addr&0x001FFFFF)) = val;
nkeynes@931
    45
    asic_g2_write_word();
nkeynes@931
    46
}
nkeynes@931
    47
static void FASTCALL ext_audioram_write_word( sh4addr_t addr, uint32_t val )
nkeynes@931
    48
{
nkeynes@934
    49
    *(uint16_t *)(aica_main_ram + (addr&0x001FFFFF)) = (uint16_t)val;
nkeynes@931
    50
    asic_g2_write_word();
nkeynes@931
    51
}
nkeynes@931
    52
static void FASTCALL ext_audioram_write_byte( sh4addr_t addr, uint32_t val )
nkeynes@931
    53
{
nkeynes@934
    54
    *(uint8_t *)(aica_main_ram + (addr&0x001FFFFF)) = (uint8_t)val;
nkeynes@931
    55
    asic_g2_write_word();
nkeynes@931
    56
}
nkeynes@931
    57
static void FASTCALL ext_audioram_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@931
    58
{
nkeynes@934
    59
    memcpy( dest, aica_main_ram+(addr&0x001FFFFF), 32 );
nkeynes@931
    60
}
nkeynes@931
    61
static void FASTCALL ext_audioram_write_burst( sh4addr_t addr, unsigned char *src )
nkeynes@931
    62
{
nkeynes@934
    63
    memcpy( aica_main_ram+(addr&0x001FFFFF), src, 32 );
nkeynes@931
    64
}
nkeynes@931
    65
nkeynes@931
    66
struct mem_region_fn mem_region_audioram = { ext_audioram_read_long, ext_audioram_write_long, 
nkeynes@931
    67
        ext_audioram_read_word, ext_audioram_write_word, 
nkeynes@931
    68
        ext_audioram_read_byte, ext_audioram_write_byte, 
nkeynes@931
    69
        ext_audioram_read_burst, ext_audioram_write_burst }; 
nkeynes@931
    70
nkeynes@931
    71
nkeynes@931
    72
static int32_t FASTCALL ext_audioscratch_read_long( sh4addr_t addr )
nkeynes@931
    73
{
nkeynes@934
    74
    return *((int32_t *)(aica_scratch_ram + (addr&0x00001FFF)));
nkeynes@931
    75
}
nkeynes@931
    76
static int32_t FASTCALL ext_audioscratch_read_word( sh4addr_t addr )
nkeynes@931
    77
{
nkeynes@934
    78
    return SIGNEXT16(*((int16_t *)(aica_scratch_ram + (addr&0x00001FFF))));
nkeynes@931
    79
}
nkeynes@931
    80
static int32_t FASTCALL ext_audioscratch_read_byte( sh4addr_t addr )
nkeynes@931
    81
{
nkeynes@934
    82
    return SIGNEXT8(*((int16_t *)(aica_scratch_ram + (addr&0x00001FFF))));
nkeynes@931
    83
}
nkeynes@931
    84
static void FASTCALL ext_audioscratch_write_long( sh4addr_t addr, uint32_t val )
nkeynes@931
    85
{
nkeynes@934
    86
    *(uint32_t *)(aica_scratch_ram + (addr&0x00001FFF)) = val;
nkeynes@931
    87
    asic_g2_write_word();
nkeynes@931
    88
}
nkeynes@931
    89
static void FASTCALL ext_audioscratch_write_word( sh4addr_t addr, uint32_t val )
nkeynes@931
    90
{
nkeynes@934
    91
    *(uint16_t *)(aica_scratch_ram + (addr&0x00001FFF)) = (uint16_t)val;
nkeynes@931
    92
    asic_g2_write_word();
nkeynes@931
    93
}
nkeynes@931
    94
static void FASTCALL ext_audioscratch_write_byte( sh4addr_t addr, uint32_t val )
nkeynes@931
    95
{
nkeynes@934
    96
    *(uint8_t *)(aica_scratch_ram + (addr&0x00001FFF)) = (uint8_t)val;
nkeynes@931
    97
    asic_g2_write_word();
nkeynes@931
    98
}
nkeynes@931
    99
static void FASTCALL ext_audioscratch_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@931
   100
{
nkeynes@934
   101
    memcpy( dest, aica_scratch_ram+(addr&0x00001FFF), 32 );
nkeynes@931
   102
}
nkeynes@931
   103
static void FASTCALL ext_audioscratch_write_burst( sh4addr_t addr, unsigned char *src )
nkeynes@931
   104
{
nkeynes@934
   105
    memcpy( aica_scratch_ram+(addr&0x00001FFF), src, 32 );
nkeynes@931
   106
}
nkeynes@931
   107
nkeynes@931
   108
struct mem_region_fn mem_region_audioscratch = { ext_audioscratch_read_long, ext_audioscratch_write_long, 
nkeynes@931
   109
        ext_audioscratch_read_word, ext_audioscratch_write_word, 
nkeynes@931
   110
        ext_audioscratch_read_byte, ext_audioscratch_write_byte, 
nkeynes@931
   111
        ext_audioscratch_read_burst, ext_audioscratch_write_burst }; 
nkeynes@931
   112
nkeynes@931
   113
/************************** Local ARM support **************************/
nkeynes@14
   114
int arm_has_page( uint32_t addr ) {
nkeynes@14
   115
    return ( addr < 0x00200000 ||
nkeynes@736
   116
            (addr >= 0x00800000 && addr <= 0x00805000 ) );
nkeynes@14
   117
}
nkeynes@14
   118
nkeynes@37
   119
uint32_t arm_read_long( uint32_t addr ) {
nkeynes@11
   120
    if( addr < 0x00200000 ) {
nkeynes@934
   121
        return *(int32_t *)(aica_main_ram + addr);
nkeynes@736
   122
        /* Main sound ram */
nkeynes@11
   123
    } else {
nkeynes@736
   124
        uint32_t val;
nkeynes@736
   125
        switch( addr & 0xFFFFF000 ) {
nkeynes@736
   126
        case 0x00800000:
nkeynes@736
   127
            val = mmio_region_AICA0_read(addr&0x0FFF);
nkeynes@736
   128
            //	    DEBUG( "ARM long read from %08X => %08X", addr, val );
nkeynes@736
   129
            return val;
nkeynes@736
   130
        case 0x00801000:
nkeynes@736
   131
            val = mmio_region_AICA1_read(addr&0x0FFF);
nkeynes@736
   132
            //	    DEBUG( "ARM long read from %08X => %08X", addr, val );
nkeynes@736
   133
            return val;
nkeynes@736
   134
        case 0x00802000:
nkeynes@736
   135
            val = mmio_region_AICA2_read(addr&0x0FFF);
nkeynes@736
   136
            // DEBUG( "ARM long read from %08X => %08X", addr, val );
nkeynes@736
   137
            return val;
nkeynes@736
   138
        case 0x00803000:
nkeynes@736
   139
        case 0x00804000:
nkeynes@934
   140
            return *(int32_t *)(aica_scratch_ram + addr - 0x00803000);
nkeynes@736
   141
        }
nkeynes@11
   142
    }
nkeynes@811
   143
    ERROR( "Attempted long read to undefined page: %08X at %08X",
nkeynes@811
   144
           addr, armr.r[15] );
nkeynes@37
   145
    /* Undefined memory */
nkeynes@37
   146
    return 0;
nkeynes@7
   147
}
nkeynes@7
   148
nkeynes@37
   149
uint32_t arm_read_word( uint32_t addr ) {
nkeynes@40
   150
    return (uint32_t)(uint16_t)arm_read_long( addr );
nkeynes@7
   151
}
nkeynes@7
   152
nkeynes@37
   153
uint32_t arm_read_byte( uint32_t addr ) {
nkeynes@40
   154
    return (uint32_t)(uint8_t)arm_read_long( addr );
nkeynes@7
   155
}
nkeynes@7
   156
nkeynes@37
   157
void arm_write_long( uint32_t addr, uint32_t value )
nkeynes@37
   158
{
nkeynes@37
   159
    if( addr < 0x00200000 ) {
nkeynes@736
   160
        /* Main sound ram */
nkeynes@934
   161
        *(uint32_t *)(aica_main_ram + addr) = value;
nkeynes@37
   162
    } else {
nkeynes@736
   163
        switch( addr & 0xFFFFF000 ) {
nkeynes@736
   164
        case 0x00800000:
nkeynes@736
   165
            // DEBUG( "ARM long write to %08X <= %08X", addr, value );
nkeynes@736
   166
            mmio_region_AICA0_write(addr&0x0FFF, value);
nkeynes@736
   167
            break;
nkeynes@736
   168
        case 0x00801000:
nkeynes@736
   169
            // DEBUG( "ARM long write to %08X <= %08X", addr, value );
nkeynes@736
   170
            mmio_region_AICA1_write(addr&0x0FFF, value);
nkeynes@736
   171
            break;
nkeynes@736
   172
        case 0x00802000:
nkeynes@736
   173
            // DEBUG( "ARM long write to %08X <= %08X", addr, value );
nkeynes@736
   174
            mmio_region_AICA2_write(addr&0x0FFF, value);
nkeynes@736
   175
            break;
nkeynes@736
   176
        case 0x00803000:
nkeynes@736
   177
        case 0x00804000:
nkeynes@934
   178
            *(uint32_t *)(aica_scratch_ram + addr - 0x00803000) = value;
nkeynes@736
   179
            break;
nkeynes@736
   180
        default:
nkeynes@736
   181
            ERROR( "Attempted long write to undefined address: %08X",
nkeynes@736
   182
                    addr );
nkeynes@736
   183
            /* Undefined memory */
nkeynes@736
   184
        } 
nkeynes@37
   185
    }
nkeynes@431
   186
    return;
nkeynes@37
   187
}
nkeynes@37
   188
nkeynes@66
   189
uint32_t arm_combine_byte( uint32_t addr, uint32_t val, uint8_t byte )
nkeynes@66
   190
{
nkeynes@66
   191
    switch( addr & 0x03 ) {
nkeynes@66
   192
    case 0:
nkeynes@736
   193
        return (val & 0xFFFFFF00) | byte;
nkeynes@66
   194
    case 1:
nkeynes@736
   195
        return (val & 0xFFFF00FF) | (byte<<8);
nkeynes@66
   196
    case 2:
nkeynes@736
   197
        return (val & 0xFF00FFFF) | (byte<<16);
nkeynes@66
   198
    case 3:
nkeynes@736
   199
        return (val & 0x00FFFFFF) | (byte<<24);
nkeynes@431
   200
    default:
nkeynes@736
   201
        return val; // Can't happen, but make gcc happy
nkeynes@66
   202
    }
nkeynes@66
   203
}
nkeynes@811
   204
void arm_write_word( uint32_t addr, uint32_t value )
nkeynes@811
   205
{
nkeynes@811
   206
	if( addr < 0x00200000 ) {
nkeynes@934
   207
        *(uint16_t *)(aica_main_ram + addr) = (uint16_t)value;
nkeynes@811
   208
	} else {
nkeynes@811
   209
		
nkeynes@811
   210
	}
nkeynes@811
   211
}
nkeynes@37
   212
void arm_write_byte( uint32_t addr, uint32_t value )
nkeynes@37
   213
{
nkeynes@37
   214
    if( addr < 0x00200000 ) {
nkeynes@736
   215
        /* Main sound ram */
nkeynes@934
   216
        *(uint8_t *)(aica_main_ram + addr) = (uint8_t)value;
nkeynes@37
   217
    } else {
nkeynes@736
   218
        uint32_t tmp;
nkeynes@736
   219
        switch( addr & 0xFFFFF000 ) {
nkeynes@736
   220
        case 0x00800000:
nkeynes@736
   221
            tmp = MMIO_READ( AICA0, addr & 0x0FFC );
nkeynes@736
   222
            value = arm_combine_byte( addr, tmp, value );
nkeynes@736
   223
            mmio_region_AICA0_write(addr&0x0FFC, value);
nkeynes@736
   224
            break;
nkeynes@736
   225
        case 0x00801000:
nkeynes@736
   226
            tmp = MMIO_READ( AICA1, addr & 0x0FFC );
nkeynes@736
   227
            value = arm_combine_byte( addr, tmp, value );
nkeynes@736
   228
            mmio_region_AICA1_write(addr&0x0FFC, value);
nkeynes@736
   229
            break;
nkeynes@736
   230
        case 0x00802000:
nkeynes@736
   231
            tmp = MMIO_READ( AICA2, addr & 0x0FFC );
nkeynes@736
   232
            value = arm_combine_byte( addr, tmp, value );
nkeynes@736
   233
            mmio_region_AICA2_write(addr&0x0FFC, value);
nkeynes@736
   234
            break;
nkeynes@736
   235
        case 0x00803000:
nkeynes@736
   236
        case 0x00804000:
nkeynes@934
   237
            *(uint8_t *)(aica_scratch_ram + addr - 0x00803000) = (uint8_t)value;
nkeynes@736
   238
            break;
nkeynes@736
   239
        default:
nkeynes@736
   240
            ERROR( "Attempted byte write to undefined address: %08X",
nkeynes@736
   241
                    addr );
nkeynes@736
   242
            /* Undefined memory */
nkeynes@736
   243
        } 
nkeynes@37
   244
    }
nkeynes@431
   245
    return;
nkeynes@37
   246
}
nkeynes@37
   247
nkeynes@37
   248
/* User translations - TODO */
nkeynes@37
   249
nkeynes@11
   250
uint32_t arm_read_long_user( uint32_t addr ) {
nkeynes@37
   251
    return arm_read_long( addr );
nkeynes@11
   252
}
nkeynes@11
   253
nkeynes@11
   254
uint32_t arm_read_byte_user( uint32_t addr ) {
nkeynes@37
   255
    return arm_read_byte( addr );
nkeynes@37
   256
}
nkeynes@11
   257
nkeynes@37
   258
void arm_write_long_user( uint32_t addr, uint32_t val ) {
nkeynes@37
   259
    arm_write_long( addr, val );
nkeynes@11
   260
}
nkeynes@37
   261
nkeynes@37
   262
void arm_write_byte_user( uint32_t addr, uint32_t val )
nkeynes@37
   263
{
nkeynes@37
   264
    arm_write_byte( addr, val );
nkeynes@37
   265
}
.