Search
lxdream.org :: lxdream/src/aica/armmem.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armmem.c
changeset 66:2ec5b6eb75e5
prev40:852ee31ace0d
next431:248dd77a9e44
author nkeynes
date Tue Jun 27 09:34:27 2006 +0000 (17 years ago)
permissions -rw-r--r--
last change Update for change to bootstrap dumper
file annotate diff log raw
nkeynes@31
     1
/**
nkeynes@66
     2
 * $Id: armmem.c,v 1.7 2006-01-10 13:56:54 nkeynes Exp $
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@7
    23
nkeynes@11
    24
char *arm_mem = NULL;
nkeynes@40
    25
char *arm_mem_scratch = NULL;
nkeynes@11
    26
nkeynes@7
    27
void arm_mem_init() {
nkeynes@11
    28
    arm_mem = mem_get_region_by_name( MEM_REGION_AUDIO );
nkeynes@40
    29
    arm_mem_scratch = mem_get_region_by_name( MEM_REGION_AUDIO_SCRATCH );
nkeynes@7
    30
}
nkeynes@7
    31
nkeynes@14
    32
int arm_has_page( uint32_t addr ) {
nkeynes@14
    33
    return ( addr < 0x00200000 ||
nkeynes@14
    34
	     (addr >= 0x00800000 && addr <= 0x00805000 ) );
nkeynes@14
    35
}
nkeynes@14
    36
nkeynes@37
    37
uint32_t arm_read_long( uint32_t addr ) {
nkeynes@11
    38
    if( addr < 0x00200000 ) {
nkeynes@11
    39
	return *(int32_t *)(arm_mem + addr);
nkeynes@11
    40
	/* Main sound ram */
nkeynes@11
    41
    } else {
nkeynes@66
    42
	uint32_t val;
nkeynes@37
    43
	switch( addr & 0xFFFFF000 ) {
nkeynes@37
    44
	case 0x00800000:
nkeynes@66
    45
	    val = mmio_region_AICA0_read(addr&0x0FFF);
nkeynes@66
    46
	    //	    DEBUG( "ARM long read from %08X => %08X", addr, val );
nkeynes@66
    47
	    return val;
nkeynes@37
    48
	case 0x00801000:
nkeynes@66
    49
	    val = mmio_region_AICA1_read(addr&0x0FFF);
nkeynes@66
    50
	    //	    DEBUG( "ARM long read from %08X => %08X", addr, val );
nkeynes@66
    51
	    return val;
nkeynes@37
    52
	case 0x00802000:
nkeynes@66
    53
	    val = mmio_region_AICA2_read(addr&0x0FFF);
nkeynes@66
    54
	    // DEBUG( "ARM long read from %08X => %08X", addr, val );
nkeynes@66
    55
	    return val;
nkeynes@37
    56
	case 0x00803000:
nkeynes@37
    57
	case 0x00804000:
nkeynes@40
    58
	    return *(int32_t *)(arm_mem_scratch + addr - 0x00803000);
nkeynes@37
    59
	}
nkeynes@11
    60
    }
nkeynes@37
    61
    ERROR( "Attempted long read to undefined page: %08X",
nkeynes@37
    62
	   addr );
nkeynes@37
    63
    /* Undefined memory */
nkeynes@37
    64
    return 0;
nkeynes@7
    65
}
nkeynes@7
    66
nkeynes@37
    67
uint32_t arm_read_word( uint32_t addr ) {
nkeynes@40
    68
    return (uint32_t)(uint16_t)arm_read_long( addr );
nkeynes@7
    69
}
nkeynes@7
    70
nkeynes@37
    71
uint32_t arm_read_byte( uint32_t addr ) {
nkeynes@40
    72
    return (uint32_t)(uint8_t)arm_read_long( addr );
nkeynes@7
    73
}
nkeynes@7
    74
nkeynes@37
    75
void arm_write_long( uint32_t addr, uint32_t value )
nkeynes@37
    76
{
nkeynes@37
    77
    if( addr < 0x00200000 ) {
nkeynes@40
    78
	/* Main sound ram */
nkeynes@37
    79
	*(uint32_t *)(arm_mem + addr) = value;
nkeynes@37
    80
    } else {
nkeynes@40
    81
	switch( addr & 0xFFFFF000 ) {
nkeynes@40
    82
	case 0x00800000:
nkeynes@66
    83
	    // DEBUG( "ARM long write to %08X <= %08X", addr, value );
nkeynes@66
    84
	    mmio_region_AICA0_write(addr&0x0FFF, value);
nkeynes@40
    85
	    break;
nkeynes@40
    86
	case 0x00801000:
nkeynes@66
    87
	    // DEBUG( "ARM long write to %08X <= %08X", addr, value );
nkeynes@66
    88
	    mmio_region_AICA1_write(addr&0x0FFF, value);
nkeynes@40
    89
	    break;
nkeynes@40
    90
	case 0x00802000:
nkeynes@66
    91
	    // DEBUG( "ARM long write to %08X <= %08X", addr, value );
nkeynes@66
    92
	    mmio_region_AICA2_write(addr&0x0FFF, value);
nkeynes@40
    93
	    break;
nkeynes@40
    94
	case 0x00803000:
nkeynes@40
    95
	case 0x00804000:
nkeynes@40
    96
	    *(uint32_t *)(arm_mem_scratch + addr - 0x00803000) = value;
nkeynes@40
    97
	    break;
nkeynes@40
    98
	default:
nkeynes@40
    99
	    ERROR( "Attempted long write to undefined address: %08X",
nkeynes@40
   100
		   addr );
nkeynes@40
   101
	    /* Undefined memory */
nkeynes@40
   102
	} 
nkeynes@37
   103
    }
nkeynes@40
   104
    return 0;
nkeynes@37
   105
}
nkeynes@37
   106
nkeynes@66
   107
uint32_t arm_combine_byte( uint32_t addr, uint32_t val, uint8_t byte )
nkeynes@66
   108
{
nkeynes@66
   109
    switch( addr & 0x03 ) {
nkeynes@66
   110
    case 0:
nkeynes@66
   111
	return (val & 0xFFFFFF00) | byte;
nkeynes@66
   112
    case 1:
nkeynes@66
   113
	return (val & 0xFFFF00FF) | (byte<<8);
nkeynes@66
   114
    case 2:
nkeynes@66
   115
	return (val & 0xFF00FFFF) | (byte<<16);
nkeynes@66
   116
    case 3:
nkeynes@66
   117
	return (val & 0x00FFFFFF) | (byte<<24);
nkeynes@66
   118
    }
nkeynes@66
   119
}
nkeynes@66
   120
nkeynes@37
   121
void arm_write_byte( uint32_t addr, uint32_t value )
nkeynes@37
   122
{
nkeynes@37
   123
    if( addr < 0x00200000 ) {
nkeynes@40
   124
	/* Main sound ram */
nkeynes@40
   125
	*(uint8_t *)(arm_mem + addr) = (uint8_t)value;
nkeynes@37
   126
    } else {
nkeynes@66
   127
	uint32_t tmp;
nkeynes@40
   128
	switch( addr & 0xFFFFF000 ) {
nkeynes@40
   129
	case 0x00800000:
nkeynes@66
   130
	    tmp = MMIO_READ( AICA0, addr & 0x0FFC );
nkeynes@66
   131
	    value = arm_combine_byte( addr, tmp, value );
nkeynes@66
   132
	    mmio_region_AICA0_write(addr&0x0FFC, value);
nkeynes@40
   133
	    break;
nkeynes@40
   134
	case 0x00801000:
nkeynes@66
   135
	    tmp = MMIO_READ( AICA1, addr & 0x0FFC );
nkeynes@66
   136
	    value = arm_combine_byte( addr, tmp, value );
nkeynes@66
   137
	    mmio_region_AICA1_write(addr&0x0FFC, value);
nkeynes@40
   138
	    break;
nkeynes@40
   139
	case 0x00802000:
nkeynes@66
   140
	    tmp = MMIO_READ( AICA2, addr & 0x0FFC );
nkeynes@66
   141
	    value = arm_combine_byte( addr, tmp, value );
nkeynes@66
   142
	    mmio_region_AICA2_write(addr&0x0FFC, value);
nkeynes@40
   143
	    break;
nkeynes@40
   144
	case 0x00803000:
nkeynes@40
   145
	case 0x00804000:
nkeynes@40
   146
	    *(uint8_t *)(arm_mem_scratch + addr - 0x00803000) = (uint8_t)value;
nkeynes@40
   147
	    break;
nkeynes@40
   148
	default:
nkeynes@40
   149
	    ERROR( "Attempted byte write to undefined address: %08X",
nkeynes@40
   150
		   addr );
nkeynes@40
   151
	    /* Undefined memory */
nkeynes@40
   152
	} 
nkeynes@37
   153
    }
nkeynes@40
   154
    return 0;
nkeynes@37
   155
}
nkeynes@37
   156
nkeynes@37
   157
/* User translations - TODO */
nkeynes@37
   158
nkeynes@11
   159
uint32_t arm_read_long_user( uint32_t addr ) {
nkeynes@37
   160
    return arm_read_long( addr );
nkeynes@11
   161
}
nkeynes@11
   162
nkeynes@11
   163
uint32_t arm_read_byte_user( uint32_t addr ) {
nkeynes@37
   164
    return arm_read_byte( addr );
nkeynes@37
   165
}
nkeynes@11
   166
nkeynes@37
   167
void arm_write_long_user( uint32_t addr, uint32_t val ) {
nkeynes@37
   168
    arm_write_long( addr, val );
nkeynes@11
   169
}
nkeynes@37
   170
nkeynes@37
   171
void arm_write_byte_user( uint32_t addr, uint32_t val )
nkeynes@37
   172
{
nkeynes@37
   173
    arm_write_byte( addr, val );
nkeynes@37
   174
}
.