filename | src/aica/armmem.c |
changeset | 1106:1879fd49ccf6 |
prev | 1067:d3c00ffccfcd |
author | nkeynes |
date | Tue Mar 20 08:29:38 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | More android WIP - Implement onPause/onResume (although resume is not actually working yet) - Implement BGRA => RGBA texture conversion (BGRA doesn't seem to work on the TFP) Boot swirl is now displayed, albeit depth buffering seems to be broken. |
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@968 | 23 | #include "asic.h" |
nkeynes@811 | 24 | #include "armcore.h" |
nkeynes@7 | 25 | |
nkeynes@934 | 26 | unsigned char aica_main_ram[2 MB]; |
nkeynes@934 | 27 | unsigned char aica_scratch_ram[8 KB]; |
nkeynes@7 | 28 | |
nkeynes@931 | 29 | /*************** ARM memory access function blocks **************/ |
nkeynes@931 | 30 | |
nkeynes@931 | 31 | static int32_t FASTCALL ext_audioram_read_long( sh4addr_t addr ) |
nkeynes@931 | 32 | { |
nkeynes@934 | 33 | return *((int32_t *)(aica_main_ram + (addr&0x001FFFFF))); |
nkeynes@931 | 34 | } |
nkeynes@931 | 35 | static int32_t FASTCALL ext_audioram_read_word( sh4addr_t addr ) |
nkeynes@931 | 36 | { |
nkeynes@934 | 37 | return SIGNEXT16(*((int16_t *)(aica_main_ram + (addr&0x001FFFFF)))); |
nkeynes@931 | 38 | } |
nkeynes@931 | 39 | static int32_t FASTCALL ext_audioram_read_byte( sh4addr_t addr ) |
nkeynes@931 | 40 | { |
nkeynes@934 | 41 | return SIGNEXT8(*((int16_t *)(aica_main_ram + (addr&0x001FFFFF)))); |
nkeynes@931 | 42 | } |
nkeynes@931 | 43 | static void FASTCALL ext_audioram_write_long( sh4addr_t addr, uint32_t val ) |
nkeynes@931 | 44 | { |
nkeynes@934 | 45 | *(uint32_t *)(aica_main_ram + (addr&0x001FFFFF)) = val; |
nkeynes@931 | 46 | asic_g2_write_word(); |
nkeynes@931 | 47 | } |
nkeynes@931 | 48 | static void FASTCALL ext_audioram_write_word( sh4addr_t addr, uint32_t val ) |
nkeynes@931 | 49 | { |
nkeynes@934 | 50 | *(uint16_t *)(aica_main_ram + (addr&0x001FFFFF)) = (uint16_t)val; |
nkeynes@931 | 51 | asic_g2_write_word(); |
nkeynes@931 | 52 | } |
nkeynes@931 | 53 | static void FASTCALL ext_audioram_write_byte( sh4addr_t addr, uint32_t val ) |
nkeynes@931 | 54 | { |
nkeynes@934 | 55 | *(uint8_t *)(aica_main_ram + (addr&0x001FFFFF)) = (uint8_t)val; |
nkeynes@931 | 56 | asic_g2_write_word(); |
nkeynes@931 | 57 | } |
nkeynes@931 | 58 | static void FASTCALL ext_audioram_read_burst( unsigned char *dest, sh4addr_t addr ) |
nkeynes@931 | 59 | { |
nkeynes@934 | 60 | memcpy( dest, aica_main_ram+(addr&0x001FFFFF), 32 ); |
nkeynes@931 | 61 | } |
nkeynes@931 | 62 | static void FASTCALL ext_audioram_write_burst( sh4addr_t addr, unsigned char *src ) |
nkeynes@931 | 63 | { |
nkeynes@934 | 64 | memcpy( aica_main_ram+(addr&0x001FFFFF), src, 32 ); |
nkeynes@931 | 65 | } |
nkeynes@931 | 66 | |
nkeynes@931 | 67 | struct mem_region_fn mem_region_audioram = { ext_audioram_read_long, ext_audioram_write_long, |
nkeynes@931 | 68 | ext_audioram_read_word, ext_audioram_write_word, |
nkeynes@931 | 69 | ext_audioram_read_byte, ext_audioram_write_byte, |
nkeynes@931 | 70 | ext_audioram_read_burst, ext_audioram_write_burst }; |
nkeynes@931 | 71 | |
nkeynes@931 | 72 | |
nkeynes@931 | 73 | static int32_t FASTCALL ext_audioscratch_read_long( sh4addr_t addr ) |
nkeynes@931 | 74 | { |
nkeynes@934 | 75 | return *((int32_t *)(aica_scratch_ram + (addr&0x00001FFF))); |
nkeynes@931 | 76 | } |
nkeynes@931 | 77 | static int32_t FASTCALL ext_audioscratch_read_word( sh4addr_t addr ) |
nkeynes@931 | 78 | { |
nkeynes@934 | 79 | return SIGNEXT16(*((int16_t *)(aica_scratch_ram + (addr&0x00001FFF)))); |
nkeynes@931 | 80 | } |
nkeynes@931 | 81 | static int32_t FASTCALL ext_audioscratch_read_byte( sh4addr_t addr ) |
nkeynes@931 | 82 | { |
nkeynes@934 | 83 | return SIGNEXT8(*((int16_t *)(aica_scratch_ram + (addr&0x00001FFF)))); |
nkeynes@931 | 84 | } |
nkeynes@931 | 85 | static void FASTCALL ext_audioscratch_write_long( sh4addr_t addr, uint32_t val ) |
nkeynes@931 | 86 | { |
nkeynes@934 | 87 | *(uint32_t *)(aica_scratch_ram + (addr&0x00001FFF)) = val; |
nkeynes@931 | 88 | asic_g2_write_word(); |
nkeynes@931 | 89 | } |
nkeynes@931 | 90 | static void FASTCALL ext_audioscratch_write_word( sh4addr_t addr, uint32_t val ) |
nkeynes@931 | 91 | { |
nkeynes@934 | 92 | *(uint16_t *)(aica_scratch_ram + (addr&0x00001FFF)) = (uint16_t)val; |
nkeynes@931 | 93 | asic_g2_write_word(); |
nkeynes@931 | 94 | } |
nkeynes@931 | 95 | static void FASTCALL ext_audioscratch_write_byte( sh4addr_t addr, uint32_t val ) |
nkeynes@931 | 96 | { |
nkeynes@934 | 97 | *(uint8_t *)(aica_scratch_ram + (addr&0x00001FFF)) = (uint8_t)val; |
nkeynes@931 | 98 | asic_g2_write_word(); |
nkeynes@931 | 99 | } |
nkeynes@931 | 100 | static void FASTCALL ext_audioscratch_read_burst( unsigned char *dest, sh4addr_t addr ) |
nkeynes@931 | 101 | { |
nkeynes@934 | 102 | memcpy( dest, aica_scratch_ram+(addr&0x00001FFF), 32 ); |
nkeynes@931 | 103 | } |
nkeynes@931 | 104 | static void FASTCALL ext_audioscratch_write_burst( sh4addr_t addr, unsigned char *src ) |
nkeynes@931 | 105 | { |
nkeynes@934 | 106 | memcpy( aica_scratch_ram+(addr&0x00001FFF), src, 32 ); |
nkeynes@931 | 107 | } |
nkeynes@931 | 108 | |
nkeynes@931 | 109 | struct mem_region_fn mem_region_audioscratch = { ext_audioscratch_read_long, ext_audioscratch_write_long, |
nkeynes@931 | 110 | ext_audioscratch_read_word, ext_audioscratch_write_word, |
nkeynes@931 | 111 | ext_audioscratch_read_byte, ext_audioscratch_write_byte, |
nkeynes@931 | 112 | ext_audioscratch_read_burst, ext_audioscratch_write_burst }; |
nkeynes@931 | 113 | |
nkeynes@931 | 114 | /************************** Local ARM support **************************/ |
nkeynes@14 | 115 | int arm_has_page( uint32_t addr ) { |
nkeynes@14 | 116 | return ( addr < 0x00200000 || |
nkeynes@736 | 117 | (addr >= 0x00800000 && addr <= 0x00805000 ) ); |
nkeynes@14 | 118 | } |
nkeynes@14 | 119 | |
nkeynes@37 | 120 | uint32_t arm_read_long( uint32_t addr ) { |
nkeynes@11 | 121 | if( addr < 0x00200000 ) { |
nkeynes@934 | 122 | return *(int32_t *)(aica_main_ram + addr); |
nkeynes@736 | 123 | /* Main sound ram */ |
nkeynes@11 | 124 | } else { |
nkeynes@736 | 125 | uint32_t val; |
nkeynes@736 | 126 | switch( addr & 0xFFFFF000 ) { |
nkeynes@736 | 127 | case 0x00800000: |
nkeynes@736 | 128 | val = mmio_region_AICA0_read(addr&0x0FFF); |
nkeynes@736 | 129 | // DEBUG( "ARM long read from %08X => %08X", addr, val ); |
nkeynes@736 | 130 | return val; |
nkeynes@736 | 131 | case 0x00801000: |
nkeynes@736 | 132 | val = mmio_region_AICA1_read(addr&0x0FFF); |
nkeynes@736 | 133 | // DEBUG( "ARM long read from %08X => %08X", addr, val ); |
nkeynes@736 | 134 | return val; |
nkeynes@736 | 135 | case 0x00802000: |
nkeynes@736 | 136 | val = mmio_region_AICA2_read(addr&0x0FFF); |
nkeynes@736 | 137 | // DEBUG( "ARM long read from %08X => %08X", addr, val ); |
nkeynes@736 | 138 | return val; |
nkeynes@736 | 139 | case 0x00803000: |
nkeynes@736 | 140 | case 0x00804000: |
nkeynes@934 | 141 | return *(int32_t *)(aica_scratch_ram + addr - 0x00803000); |
nkeynes@736 | 142 | } |
nkeynes@11 | 143 | } |
nkeynes@1106 | 144 | WARN( "Attempted long read to undefined page: %08X at %08X", |
nkeynes@811 | 145 | addr, armr.r[15] ); |
nkeynes@37 | 146 | /* Undefined memory */ |
nkeynes@37 | 147 | return 0; |
nkeynes@7 | 148 | } |
nkeynes@7 | 149 | |
nkeynes@37 | 150 | uint32_t arm_read_word( uint32_t addr ) { |
nkeynes@40 | 151 | return (uint32_t)(uint16_t)arm_read_long( addr ); |
nkeynes@7 | 152 | } |
nkeynes@7 | 153 | |
nkeynes@37 | 154 | uint32_t arm_read_byte( uint32_t addr ) { |
nkeynes@40 | 155 | return (uint32_t)(uint8_t)arm_read_long( addr ); |
nkeynes@7 | 156 | } |
nkeynes@7 | 157 | |
nkeynes@37 | 158 | void arm_write_long( uint32_t addr, uint32_t value ) |
nkeynes@37 | 159 | { |
nkeynes@37 | 160 | if( addr < 0x00200000 ) { |
nkeynes@736 | 161 | /* Main sound ram */ |
nkeynes@934 | 162 | *(uint32_t *)(aica_main_ram + addr) = value; |
nkeynes@37 | 163 | } else { |
nkeynes@736 | 164 | switch( addr & 0xFFFFF000 ) { |
nkeynes@736 | 165 | case 0x00800000: |
nkeynes@736 | 166 | // DEBUG( "ARM long write to %08X <= %08X", addr, value ); |
nkeynes@736 | 167 | mmio_region_AICA0_write(addr&0x0FFF, value); |
nkeynes@736 | 168 | break; |
nkeynes@736 | 169 | case 0x00801000: |
nkeynes@736 | 170 | // DEBUG( "ARM long write to %08X <= %08X", addr, value ); |
nkeynes@736 | 171 | mmio_region_AICA1_write(addr&0x0FFF, value); |
nkeynes@736 | 172 | break; |
nkeynes@736 | 173 | case 0x00802000: |
nkeynes@736 | 174 | // DEBUG( "ARM long write to %08X <= %08X", addr, value ); |
nkeynes@736 | 175 | mmio_region_AICA2_write(addr&0x0FFF, value); |
nkeynes@736 | 176 | break; |
nkeynes@736 | 177 | case 0x00803000: |
nkeynes@736 | 178 | case 0x00804000: |
nkeynes@934 | 179 | *(uint32_t *)(aica_scratch_ram + addr - 0x00803000) = value; |
nkeynes@736 | 180 | break; |
nkeynes@736 | 181 | default: |
nkeynes@1106 | 182 | WARN( "Attempted long write to undefined address: %08X", |
nkeynes@736 | 183 | addr ); |
nkeynes@736 | 184 | /* Undefined memory */ |
nkeynes@736 | 185 | } |
nkeynes@37 | 186 | } |
nkeynes@431 | 187 | return; |
nkeynes@37 | 188 | } |
nkeynes@37 | 189 | |
nkeynes@66 | 190 | uint32_t arm_combine_byte( uint32_t addr, uint32_t val, uint8_t byte ) |
nkeynes@66 | 191 | { |
nkeynes@66 | 192 | switch( addr & 0x03 ) { |
nkeynes@66 | 193 | case 0: |
nkeynes@736 | 194 | return (val & 0xFFFFFF00) | byte; |
nkeynes@66 | 195 | case 1: |
nkeynes@736 | 196 | return (val & 0xFFFF00FF) | (byte<<8); |
nkeynes@66 | 197 | case 2: |
nkeynes@736 | 198 | return (val & 0xFF00FFFF) | (byte<<16); |
nkeynes@66 | 199 | case 3: |
nkeynes@736 | 200 | return (val & 0x00FFFFFF) | (byte<<24); |
nkeynes@431 | 201 | default: |
nkeynes@736 | 202 | return val; // Can't happen, but make gcc happy |
nkeynes@66 | 203 | } |
nkeynes@66 | 204 | } |
nkeynes@811 | 205 | void arm_write_word( uint32_t addr, uint32_t value ) |
nkeynes@811 | 206 | { |
nkeynes@811 | 207 | if( addr < 0x00200000 ) { |
nkeynes@934 | 208 | *(uint16_t *)(aica_main_ram + addr) = (uint16_t)value; |
nkeynes@811 | 209 | } else { |
nkeynes@811 | 210 | |
nkeynes@811 | 211 | } |
nkeynes@811 | 212 | } |
nkeynes@37 | 213 | void arm_write_byte( uint32_t addr, uint32_t value ) |
nkeynes@37 | 214 | { |
nkeynes@37 | 215 | if( addr < 0x00200000 ) { |
nkeynes@736 | 216 | /* Main sound ram */ |
nkeynes@934 | 217 | *(uint8_t *)(aica_main_ram + addr) = (uint8_t)value; |
nkeynes@37 | 218 | } else { |
nkeynes@736 | 219 | uint32_t tmp; |
nkeynes@736 | 220 | switch( addr & 0xFFFFF000 ) { |
nkeynes@736 | 221 | case 0x00800000: |
nkeynes@736 | 222 | tmp = MMIO_READ( AICA0, addr & 0x0FFC ); |
nkeynes@736 | 223 | value = arm_combine_byte( addr, tmp, value ); |
nkeynes@736 | 224 | mmio_region_AICA0_write(addr&0x0FFC, value); |
nkeynes@736 | 225 | break; |
nkeynes@736 | 226 | case 0x00801000: |
nkeynes@736 | 227 | tmp = MMIO_READ( AICA1, addr & 0x0FFC ); |
nkeynes@736 | 228 | value = arm_combine_byte( addr, tmp, value ); |
nkeynes@736 | 229 | mmio_region_AICA1_write(addr&0x0FFC, value); |
nkeynes@736 | 230 | break; |
nkeynes@736 | 231 | case 0x00802000: |
nkeynes@736 | 232 | tmp = MMIO_READ( AICA2, addr & 0x0FFC ); |
nkeynes@736 | 233 | value = arm_combine_byte( addr, tmp, value ); |
nkeynes@736 | 234 | mmio_region_AICA2_write(addr&0x0FFC, value); |
nkeynes@736 | 235 | break; |
nkeynes@736 | 236 | case 0x00803000: |
nkeynes@736 | 237 | case 0x00804000: |
nkeynes@934 | 238 | *(uint8_t *)(aica_scratch_ram + addr - 0x00803000) = (uint8_t)value; |
nkeynes@736 | 239 | break; |
nkeynes@736 | 240 | default: |
nkeynes@1106 | 241 | WARN( "Attempted byte write to undefined address: %08X", |
nkeynes@736 | 242 | addr ); |
nkeynes@736 | 243 | /* Undefined memory */ |
nkeynes@736 | 244 | } |
nkeynes@37 | 245 | } |
nkeynes@431 | 246 | return; |
nkeynes@37 | 247 | } |
nkeynes@37 | 248 | |
nkeynes@37 | 249 | /* User translations - TODO */ |
nkeynes@37 | 250 | |
nkeynes@11 | 251 | uint32_t arm_read_long_user( uint32_t addr ) { |
nkeynes@37 | 252 | return arm_read_long( addr ); |
nkeynes@11 | 253 | } |
nkeynes@11 | 254 | |
nkeynes@11 | 255 | uint32_t arm_read_byte_user( uint32_t addr ) { |
nkeynes@37 | 256 | return arm_read_byte( addr ); |
nkeynes@37 | 257 | } |
nkeynes@11 | 258 | |
nkeynes@37 | 259 | void arm_write_long_user( uint32_t addr, uint32_t val ) { |
nkeynes@37 | 260 | arm_write_long( addr, val ); |
nkeynes@11 | 261 | } |
nkeynes@37 | 262 | |
nkeynes@37 | 263 | void arm_write_byte_user( uint32_t addr, uint32_t val ) |
nkeynes@37 | 264 | { |
nkeynes@37 | 265 | arm_write_byte( addr, val ); |
nkeynes@37 | 266 | } |
nkeynes@998 | 267 | |
nkeynes@998 | 268 | size_t arm_read_phys( unsigned char *buf, uint32_t addr, size_t length ) { |
nkeynes@998 | 269 | if( addr < sizeof(aica_main_ram) ) { |
nkeynes@998 | 270 | if( addr+length > sizeof(aica_main_ram) ) { |
nkeynes@998 | 271 | length = sizeof(aica_main_ram) - addr; |
nkeynes@998 | 272 | } |
nkeynes@998 | 273 | memcpy( buf, &aica_main_ram[addr], length ); |
nkeynes@998 | 274 | return length; |
nkeynes@998 | 275 | } else { |
nkeynes@998 | 276 | return 0; |
nkeynes@998 | 277 | } |
nkeynes@998 | 278 | } |
nkeynes@998 | 279 | |
nkeynes@998 | 280 | size_t arm_write_phys( uint32_t addr, unsigned char *buf, size_t length ) { |
nkeynes@998 | 281 | if( addr < sizeof(aica_main_ram) ) { |
nkeynes@998 | 282 | if( addr+length > sizeof(aica_main_ram) ) { |
nkeynes@998 | 283 | length = sizeof(aica_main_ram) - addr; |
nkeynes@998 | 284 | } |
nkeynes@998 | 285 | memcpy( &aica_main_ram[addr], buf, length ); |
nkeynes@998 | 286 | return length; |
nkeynes@998 | 287 | } else { |
nkeynes@998 | 288 | return 0; |
nkeynes@998 | 289 | } |
nkeynes@998 | 290 | } |
.