nkeynes@10 | 1 | /**
|
nkeynes@586 | 2 | * $Id$
|
nkeynes@929 | 3 | * sh4mem.c is responsible for interfacing between the SH4's internal memory
|
nkeynes@10 | 4 | *
|
nkeynes@10 | 5 | * Copyright (c) 2005 Nathan Keynes.
|
nkeynes@10 | 6 | *
|
nkeynes@10 | 7 | * This program is free software; you can redistribute it and/or modify
|
nkeynes@10 | 8 | * it under the terms of the GNU General Public License as published by
|
nkeynes@10 | 9 | * the Free Software Foundation; either version 2 of the License, or
|
nkeynes@10 | 10 | * (at your option) any later version.
|
nkeynes@10 | 11 | *
|
nkeynes@10 | 12 | * This program is distributed in the hope that it will be useful,
|
nkeynes@10 | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nkeynes@10 | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nkeynes@10 | 15 | * GNU General Public License for more details.
|
nkeynes@10 | 16 | */
|
nkeynes@10 | 17 |
|
nkeynes@35 | 18 | #define MODULE sh4_module
|
nkeynes@35 | 19 |
|
nkeynes@10 | 20 | #include <string.h>
|
nkeynes@10 | 21 | #include <zlib.h>
|
nkeynes@10 | 22 | #include "dream.h"
|
nkeynes@10 | 23 | #include "mem.h"
|
nkeynes@10 | 24 | #include "mmio.h"
|
nkeynes@10 | 25 | #include "dreamcast.h"
|
nkeynes@422 | 26 | #include "sh4/sh4core.h"
|
nkeynes@422 | 27 | #include "sh4/sh4mmio.h"
|
nkeynes@422 | 28 | #include "sh4/xltcache.h"
|
nkeynes@100 | 29 | #include "pvr2/pvr2.h"
|
nkeynes@10 | 30 |
|
nkeynes@929 | 31 | /* System regions (probably should be defined elsewhere) */
|
nkeynes@929 | 32 | extern struct mem_region_fn mem_region_unmapped;
|
nkeynes@929 | 33 | extern struct mem_region_fn mem_region_sdram;
|
nkeynes@929 | 34 | extern struct mem_region_fn mem_region_vram32;
|
nkeynes@929 | 35 | extern struct mem_region_fn mem_region_vram64;
|
nkeynes@929 | 36 | extern struct mem_region_fn mem_region_audioram;
|
nkeynes@929 | 37 | extern struct mem_region_fn mem_region_flashram;
|
nkeynes@929 | 38 | extern struct mem_region_fn mem_region_bootrom;
|
nkeynes@10 | 39 |
|
nkeynes@929 | 40 | /* On-chip regions other than defined MMIO regions */
|
nkeynes@929 | 41 | extern struct mem_region_fn mem_region_storequeue;
|
nkeynes@929 | 42 | extern struct mem_region_fn mem_region_icache_addr;
|
nkeynes@929 | 43 | extern struct mem_region_fn mem_region_icache_data;
|
nkeynes@929 | 44 | extern struct mem_region_fn mem_region_ocache_addr;
|
nkeynes@929 | 45 | extern struct mem_region_fn mem_region_ocache_data;
|
nkeynes@929 | 46 | extern struct mem_region_fn mem_region_itlb_addr;
|
nkeynes@929 | 47 | extern struct mem_region_fn mem_region_itlb_data;
|
nkeynes@929 | 48 | extern struct mem_region_fn mem_region_utlb_addr;
|
nkeynes@929 | 49 | extern struct mem_region_fn mem_region_utlb_data;
|
nkeynes@10 | 50 |
|
nkeynes@929 | 51 | /********************* The main ram address space **********************/
|
nkeynes@929 | 52 | static int32_t FASTCALL ext_sdram_read_long( sh4addr_t addr )
|
nkeynes@929 | 53 | {
|
nkeynes@929 | 54 | return *((int32_t *)(sh4_main_ram + (addr&0x00FFFFFF)));
|
nkeynes@929 | 55 | }
|
nkeynes@929 | 56 | static int32_t FASTCALL ext_sdram_read_word( sh4addr_t addr )
|
nkeynes@929 | 57 | {
|
nkeynes@929 | 58 | return SIGNEXT16(*((int16_t *)(sh4_main_ram + (addr&0x00FFFFFF))));
|
nkeynes@929 | 59 | }
|
nkeynes@929 | 60 | static int32_t FASTCALL ext_sdram_read_byte( sh4addr_t addr )
|
nkeynes@929 | 61 | {
|
nkeynes@929 | 62 | return SIGNEXT8(*((int16_t *)(sh4_main_ram + (addr&0x00FFFFFF))));
|
nkeynes@929 | 63 | }
|
nkeynes@929 | 64 | static void FASTCALL ext_sdram_write_long( sh4addr_t addr, uint32_t val )
|
nkeynes@929 | 65 | {
|
nkeynes@929 | 66 | *(uint32_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = val;
|
nkeynes@929 | 67 | xlat_invalidate_long(addr);
|
nkeynes@929 | 68 | }
|
nkeynes@929 | 69 | static void FASTCALL ext_sdram_write_word( sh4addr_t addr, uint32_t val )
|
nkeynes@929 | 70 | {
|
nkeynes@929 | 71 | *(uint16_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = (uint16_t)val;
|
nkeynes@929 | 72 | xlat_invalidate_word(addr);
|
nkeynes@929 | 73 | }
|
nkeynes@929 | 74 | static void FASTCALL ext_sdram_write_byte( sh4addr_t addr, uint32_t val )
|
nkeynes@929 | 75 | {
|
nkeynes@929 | 76 | *(uint8_t *)(sh4_main_ram + (addr&0x00FFFFFF)) = (uint8_t)val;
|
nkeynes@929 | 77 | xlat_invalidate_word(addr);
|
nkeynes@929 | 78 | }
|
nkeynes@929 | 79 | static void FASTCALL ext_sdram_read_burst( unsigned char *dest, sh4addr_t addr )
|
nkeynes@929 | 80 | {
|
nkeynes@929 | 81 | memcpy( dest, sh4_main_ram+(addr&0x00FFFFFF), 32 );
|
nkeynes@929 | 82 | }
|
nkeynes@929 | 83 | static void FASTCALL ext_sdram_write_burst( sh4addr_t addr, unsigned char *src )
|
nkeynes@929 | 84 | {
|
nkeynes@929 | 85 | memcpy( sh4_main_ram+(addr&0x00FFFFFF), src, 32 );
|
nkeynes@929 | 86 | }
|
nkeynes@929 | 87 |
|
nkeynes@929 | 88 | struct mem_region_fn mem_region_sdram = { ext_sdram_read_long, ext_sdram_write_long,
|
nkeynes@929 | 89 | ext_sdram_read_word, ext_sdram_write_word,
|
nkeynes@929 | 90 | ext_sdram_read_byte, ext_sdram_write_byte,
|
nkeynes@929 | 91 | ext_sdram_read_burst, ext_sdram_write_burst };
|
nkeynes@929 | 92 |
|
nkeynes@929 | 93 |
|
nkeynes@929 | 94 | /********************* The Boot ROM address space **********************/
|
nkeynes@929 | 95 | extern sh4ptr_t dc_boot_rom;
|
nkeynes@929 | 96 | extern sh4ptr_t dc_flash_ram;
|
nkeynes@929 | 97 | extern sh4ptr_t dc_audio_ram;
|
nkeynes@929 | 98 | static int32_t FASTCALL ext_bootrom_read_long( sh4addr_t addr )
|
nkeynes@929 | 99 | {
|
nkeynes@929 | 100 | return *((int32_t *)(dc_boot_rom + (addr&0x001FFFFF)));
|
nkeynes@929 | 101 | }
|
nkeynes@929 | 102 | static int32_t FASTCALL ext_bootrom_read_word( sh4addr_t addr )
|
nkeynes@929 | 103 | {
|
nkeynes@929 | 104 | return SIGNEXT16(*((int16_t *)(dc_boot_rom + (addr&0x001FFFFF))));
|
nkeynes@929 | 105 | }
|
nkeynes@929 | 106 | static int32_t FASTCALL ext_bootrom_read_byte( sh4addr_t addr )
|
nkeynes@929 | 107 | {
|
nkeynes@929 | 108 | return SIGNEXT8(*((int16_t *)(dc_boot_rom + (addr&0x001FFFFF))));
|
nkeynes@929 | 109 | }
|
nkeynes@929 | 110 | static void FASTCALL ext_bootrom_read_burst( unsigned char *dest, sh4addr_t addr )
|
nkeynes@929 | 111 | {
|
nkeynes@929 | 112 | memcpy( dest, sh4_main_ram+(addr&0x001FFFFF), 32 );
|
nkeynes@929 | 113 | }
|
nkeynes@929 | 114 |
|
nkeynes@929 | 115 | struct mem_region_fn mem_region_bootrom = {
|
nkeynes@929 | 116 | ext_bootrom_read_long, unmapped_write_long,
|
nkeynes@929 | 117 | ext_bootrom_read_word, unmapped_write_long,
|
nkeynes@929 | 118 | ext_bootrom_read_byte, unmapped_write_long,
|
nkeynes@929 | 119 | ext_bootrom_read_burst, unmapped_write_burst };
|
nkeynes@929 | 120 |
|
nkeynes@929 | 121 | /********************* The Flash RAM address space **********************/
|
nkeynes@929 | 122 | static int32_t FASTCALL ext_flashram_read_long( sh4addr_t addr )
|
nkeynes@929 | 123 | {
|
nkeynes@929 | 124 | return *((int32_t *)(dc_flash_ram + (addr&0x0001FFFF)));
|
nkeynes@929 | 125 | }
|
nkeynes@929 | 126 | static int32_t FASTCALL ext_flashram_read_word( sh4addr_t addr )
|
nkeynes@929 | 127 | {
|
nkeynes@929 | 128 | return SIGNEXT16(*((int16_t *)(dc_flash_ram + (addr&0x0001FFFF))));
|
nkeynes@929 | 129 | }
|
nkeynes@929 | 130 | static int32_t FASTCALL ext_flashram_read_byte( sh4addr_t addr )
|
nkeynes@929 | 131 | {
|
nkeynes@929 | 132 | return SIGNEXT8(*((int16_t *)(dc_flash_ram + (addr&0x0001FFFF))));
|
nkeynes@929 | 133 | }
|
nkeynes@929 | 134 | static void FASTCALL ext_flashram_write_long( sh4addr_t addr, uint32_t val )
|
nkeynes@929 | 135 | {
|
nkeynes@929 | 136 | *(uint32_t *)(dc_flash_ram + (addr&0x0001FFFF)) = val;
|
nkeynes@929 | 137 | asic_g2_write_word();
|
nkeynes@929 | 138 | }
|
nkeynes@929 | 139 | static void FASTCALL ext_flashram_write_word( sh4addr_t addr, uint32_t val )
|
nkeynes@929 | 140 | {
|
nkeynes@929 | 141 | *(uint16_t *)(dc_flash_ram + (addr&0x0001FFFF)) = (uint16_t)val;
|
nkeynes@929 | 142 | asic_g2_write_word();
|
nkeynes@929 | 143 | }
|
nkeynes@929 | 144 | static void FASTCALL ext_flashram_write_byte( sh4addr_t addr, uint32_t val )
|
nkeynes@929 | 145 | {
|
nkeynes@929 | 146 | *(uint8_t *)(dc_flash_ram + (addr&0x0001FFFF)) = (uint8_t)val;
|
nkeynes@929 | 147 | asic_g2_write_word();
|
nkeynes@929 | 148 | }
|
nkeynes@929 | 149 | static void FASTCALL ext_flashram_read_burst( unsigned char *dest, sh4addr_t addr )
|
nkeynes@929 | 150 | {
|
nkeynes@929 | 151 | memcpy( dest, dc_flash_ram+(addr&0x0001FFFF), 32 );
|
nkeynes@929 | 152 | }
|
nkeynes@929 | 153 | static void FASTCALL ext_flashram_write_burst( sh4addr_t addr, unsigned char *src )
|
nkeynes@929 | 154 | {
|
nkeynes@929 | 155 | memcpy( dc_flash_ram+(addr&0x0001FFFF), src, 32 );
|
nkeynes@929 | 156 | }
|
nkeynes@929 | 157 |
|
nkeynes@929 | 158 | struct mem_region_fn mem_region_flashram = { ext_flashram_read_long, ext_flashram_write_long,
|
nkeynes@929 | 159 | ext_flashram_read_word, ext_flashram_write_word,
|
nkeynes@929 | 160 | ext_flashram_read_byte, ext_flashram_write_byte,
|
nkeynes@929 | 161 | ext_flashram_read_burst, ext_flashram_write_burst };
|
nkeynes@929 | 162 |
|
nkeynes@931 | 163 | /***************************** P4 Regions ************************************/
|
nkeynes@929 | 164 |
|
nkeynes@931 | 165 | /* Store-queue (long-write only?) */
|
nkeynes@931 | 166 | static void FASTCALL p4_storequeue_write_long( sh4addr_t addr, uint32_t val )
|
nkeynes@931 | 167 | {
|
nkeynes@931 | 168 | sh4r.store_queue[(addr>>2)&0xF] = val;
|
nkeynes@931 | 169 | }
|
nkeynes@931 | 170 | static int32_t FASTCALL p4_storequeue_read_long( sh4addr_t addr )
|
nkeynes@931 | 171 | {
|
nkeynes@931 | 172 | return sh4r.store_queue[(addr>>2)&0xF];
|
nkeynes@931 | 173 | }
|
nkeynes@931 | 174 |
|
nkeynes@931 | 175 | struct mem_region_fn p4_region_storequeue = {
|
nkeynes@931 | 176 | p4_storequeue_read_long, p4_storequeue_write_long,
|
nkeynes@931 | 177 | p4_storequeue_read_long, p4_storequeue_write_long,
|
nkeynes@931 | 178 | p4_storequeue_read_long, p4_storequeue_write_long,
|
nkeynes@931 | 179 | unmapped_read_burst, unmapped_write_burst }; // No burst access.
|
nkeynes@931 | 180 |
|
nkeynes@931 | 181 | /* Cache access */
|
nkeynes@929 | 182 | struct mem_region_fn p4_region_icache_addr = {
|
nkeynes@929 | 183 | mmu_icache_addr_read, mmu_icache_addr_write,
|
nkeynes@929 | 184 | mmu_icache_addr_read, mmu_icache_addr_write,
|
nkeynes@929 | 185 | mmu_icache_addr_read, mmu_icache_addr_write,
|
nkeynes@929 | 186 | unmapped_read_burst, unmapped_write_burst };
|
nkeynes@929 | 187 | struct mem_region_fn p4_region_icache_data = {
|
nkeynes@929 | 188 | mmu_icache_data_read, mmu_icache_data_write,
|
nkeynes@929 | 189 | mmu_icache_data_read, mmu_icache_data_write,
|
nkeynes@929 | 190 | mmu_icache_data_read, mmu_icache_data_write,
|
nkeynes@929 | 191 | unmapped_read_burst, unmapped_write_burst };
|
nkeynes@929 | 192 | struct mem_region_fn p4_region_ocache_addr = {
|
nkeynes@929 | 193 | mmu_ocache_addr_read, mmu_ocache_addr_write,
|
nkeynes@929 | 194 | mmu_ocache_addr_read, mmu_ocache_addr_write,
|
nkeynes@929 | 195 | mmu_ocache_addr_read, mmu_ocache_addr_write,
|
nkeynes@929 | 196 | unmapped_read_burst, unmapped_write_burst };
|
nkeynes@929 | 197 | struct mem_region_fn p4_region_ocache_data = {
|
nkeynes@929 | 198 | mmu_ocache_data_read, mmu_ocache_data_write,
|
nkeynes@929 | 199 | mmu_ocache_data_read, mmu_ocache_data_write,
|
nkeynes@929 | 200 | mmu_ocache_data_read, mmu_ocache_data_write,
|
nkeynes@929 | 201 | unmapped_read_burst, unmapped_write_burst };
|
nkeynes@931 | 202 |
|
nkeynes@931 | 203 | /* TLB access */
|
nkeynes@929 | 204 | struct mem_region_fn p4_region_itlb_addr = {
|
nkeynes@929 | 205 | mmu_itlb_addr_read, mmu_itlb_addr_write,
|
nkeynes@929 | 206 | mmu_itlb_addr_read, mmu_itlb_addr_write,
|
nkeynes@929 | 207 | mmu_itlb_addr_read, mmu_itlb_addr_write,
|
nkeynes@929 | 208 | unmapped_read_burst, unmapped_write_burst };
|
nkeynes@929 | 209 | struct mem_region_fn p4_region_itlb_data = {
|
nkeynes@929 | 210 | mmu_itlb_data_read, mmu_itlb_data_write,
|
nkeynes@929 | 211 | mmu_itlb_data_read, mmu_itlb_data_write,
|
nkeynes@929 | 212 | mmu_itlb_data_read, mmu_itlb_data_write,
|
nkeynes@929 | 213 | unmapped_read_burst, unmapped_write_burst };
|
nkeynes@929 | 214 | struct mem_region_fn p4_region_utlb_addr = {
|
nkeynes@929 | 215 | mmu_utlb_addr_read, mmu_utlb_addr_write,
|
nkeynes@929 | 216 | mmu_utlb_addr_read, mmu_utlb_addr_write,
|
nkeynes@929 | 217 | mmu_utlb_addr_read, mmu_utlb_addr_write,
|
nkeynes@929 | 218 | unmapped_read_burst, unmapped_write_burst };
|
nkeynes@929 | 219 | struct mem_region_fn p4_region_utlb_data = {
|
nkeynes@929 | 220 | mmu_utlb_data_read, mmu_utlb_data_write,
|
nkeynes@929 | 221 | mmu_utlb_data_read, mmu_utlb_data_write,
|
nkeynes@929 | 222 | mmu_utlb_data_read, mmu_utlb_data_write,
|
nkeynes@929 | 223 | unmapped_read_burst, unmapped_write_burst };
|
nkeynes@929 | 224 |
|
nkeynes@931 | 225 | /********************** Initialization *************************/
|
nkeynes@931 | 226 |
|
nkeynes@931 | 227 | mem_region_fn_t *sh4_address_space;
|
nkeynes@931 | 228 |
|
nkeynes@931 | 229 | static void sh4_register_mem_region( uint32_t start, uint32_t end, mem_region_fn_t fn )
|
nkeynes@931 | 230 | {
|
nkeynes@931 | 231 | int count = (end - start) >> 12;
|
nkeynes@931 | 232 | mem_region_fn_t *ptr = &sh4_address_space[start>>12];
|
nkeynes@931 | 233 | while( count-- > 0 ) {
|
nkeynes@931 | 234 | *ptr++ = fn;
|
nkeynes@931 | 235 | }
|
nkeynes@931 | 236 | }
|
nkeynes@931 | 237 |
|
nkeynes@931 | 238 | static gboolean sh4_ext_page_remapped( sh4addr_t page, mem_region_fn_t fn, void *user_data )
|
nkeynes@931 | 239 | {
|
nkeynes@931 | 240 | int i;
|
nkeynes@931 | 241 | for( i=0; i<= 0xC0000000; i+= 0x20000000 ) {
|
nkeynes@931 | 242 | sh4_address_space[(page|i)>>12] = fn;
|
nkeynes@931 | 243 | }
|
nkeynes@931 | 244 | }
|
nkeynes@931 | 245 |
|
nkeynes@931 | 246 |
|
nkeynes@931 | 247 | void sh4_mem_init()
|
nkeynes@931 | 248 | {
|
nkeynes@931 | 249 | int i;
|
nkeynes@931 | 250 | mem_region_fn_t *ptr;
|
nkeynes@931 | 251 | sh4_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 256 );
|
nkeynes@931 | 252 | for( i=0, ptr = sh4_address_space; i<7; i++, ptr += LXDREAM_PAGE_TABLE_ENTRIES ) {
|
nkeynes@931 | 253 | memcpy( ptr, ext_address_space, sizeof(mem_region_fn_t) * LXDREAM_PAGE_TABLE_ENTRIES );
|
nkeynes@931 | 254 | }
|
nkeynes@931 | 255 |
|
nkeynes@931 | 256 | /* Setup main P4 regions */
|
nkeynes@931 | 257 | sh4_register_mem_region( 0xE0000000, 0xE4000000, &p4_region_storequeue );
|
nkeynes@931 | 258 | sh4_register_mem_region( 0xE4000000, 0xF0000000, &mem_region_unmapped );
|
nkeynes@931 | 259 | sh4_register_mem_region( 0xF0000000, 0xF1000000, &p4_region_icache_addr );
|
nkeynes@931 | 260 | sh4_register_mem_region( 0xF1000000, 0xF2000000, &p4_region_icache_data );
|
nkeynes@931 | 261 | sh4_register_mem_region( 0xF2000000, 0xF3000000, &p4_region_itlb_addr );
|
nkeynes@931 | 262 | sh4_register_mem_region( 0xF3000000, 0xF4000000, &p4_region_itlb_data );
|
nkeynes@931 | 263 | sh4_register_mem_region( 0xF4000000, 0xF5000000, &p4_region_ocache_addr );
|
nkeynes@931 | 264 | sh4_register_mem_region( 0xF5000000, 0xF6000000, &p4_region_ocache_data );
|
nkeynes@931 | 265 | sh4_register_mem_region( 0xF6000000, 0xF7000000, &p4_region_utlb_addr );
|
nkeynes@931 | 266 | sh4_register_mem_region( 0xF7000000, 0xF8000000, &p4_region_utlb_data );
|
nkeynes@931 | 267 | sh4_register_mem_region( 0xF8000000, 0x00000000, &mem_region_unmapped );
|
nkeynes@931 | 268 |
|
nkeynes@931 | 269 | /* Setup P4 control region */
|
nkeynes@931 | 270 | sh4_register_mem_region( 0xFF000000, 0xFF001000, &mmio_region_MMU.fn );
|
nkeynes@931 | 271 | sh4_register_mem_region( 0xFF100000, 0xFF101000, &mmio_region_PMM.fn );
|
nkeynes@931 | 272 | sh4_register_mem_region( 0xFF200000, 0xFF201000, &mmio_region_UBC.fn );
|
nkeynes@931 | 273 | sh4_register_mem_region( 0xFF800000, 0xFF801000, &mmio_region_BSC.fn );
|
nkeynes@931 | 274 | sh4_register_mem_region( 0xFF900000, 0xFFA00000, &mem_region_unmapped ); // SDMR2 + SDMR3
|
nkeynes@931 | 275 | sh4_register_mem_region( 0xFFA00000, 0xFFA01000, &mmio_region_DMAC.fn );
|
nkeynes@931 | 276 | sh4_register_mem_region( 0xFFC00000, 0xFFC01000, &mmio_region_CPG.fn );
|
nkeynes@931 | 277 | sh4_register_mem_region( 0xFFC80000, 0xFFC81000, &mmio_region_RTC.fn );
|
nkeynes@931 | 278 | sh4_register_mem_region( 0xFFD00000, 0xFFD01000, &mmio_region_INTC.fn );
|
nkeynes@931 | 279 | sh4_register_mem_region( 0xFFD80000, 0xFFD81000, &mmio_region_TMU.fn );
|
nkeynes@931 | 280 | sh4_register_mem_region( 0xFFE00000, 0xFFE01000, &mmio_region_SCI.fn );
|
nkeynes@931 | 281 | sh4_register_mem_region( 0xFFE80000, 0xFFE81000, &mmio_region_SCIF.fn );
|
nkeynes@931 | 282 | sh4_register_mem_region( 0xFFF00000, 0xFFF01000, &mem_region_unmapped ); // H-UDI
|
nkeynes@931 | 283 |
|
nkeynes@931 | 284 | register_mem_page_remapped_hook( sh4_ext_page_remapped, NULL );
|
nkeynes@931 | 285 | }
|
nkeynes@931 | 286 |
|
nkeynes@931 | 287 | /************** Access methods ***************/
|
nkeynes@929 | 288 | #ifdef HAVE_FRAME_ADDRESS
|
nkeynes@929 | 289 | #define RETURN_VIA(exc) do{ *(((void **)__builtin_frame_address(0))+1) = exc; return; } while(0)
|
nkeynes@10 | 290 | #else
|
nkeynes@929 | 291 | #define RETURN_VIA(exc) return NULL
|
nkeynes@10 | 292 | #endif
|
nkeynes@10 | 293 |
|
nkeynes@931 | 294 |
|
nkeynes@931 | 295 | int32_t FASTCALL sh4_read_long( sh4addr_t addr )
|
nkeynes@10 | 296 | {
|
nkeynes@931 | 297 | return sh4_address_space[addr>>12]->read_long(addr);
|
nkeynes@10 | 298 | }
|
nkeynes@10 | 299 |
|
nkeynes@931 | 300 | int32_t FASTCALL sh4_read_word( sh4addr_t addr )
|
nkeynes@10 | 301 | {
|
nkeynes@931 | 302 | return sh4_address_space[addr>>12]->read_word(addr);
|
nkeynes@10 | 303 | }
|
nkeynes@10 | 304 |
|
nkeynes@931 | 305 | int32_t FASTCALL sh4_read_byte( sh4addr_t addr )
|
nkeynes@10 | 306 | {
|
nkeynes@931 | 307 | return sh4_address_space[addr>>12]->read_byte(addr);
|
nkeynes@931 | 308 | }
|
nkeynes@931 | 309 |
|
nkeynes@931 | 310 | void FASTCALL sh4_write_long( sh4addr_t addr, uint32_t val )
|
nkeynes@931 | 311 | {
|
nkeynes@931 | 312 | sh4_address_space[addr>>12]->write_long(addr, val);
|
nkeynes@931 | 313 | }
|
nkeynes@931 | 314 |
|
nkeynes@931 | 315 | void FASTCALL sh4_write_word( sh4addr_t addr, uint32_t val )
|
nkeynes@931 | 316 | {
|
nkeynes@931 | 317 | sh4_address_space[addr>>12]->write_word(addr,val);
|
nkeynes@931 | 318 | }
|
nkeynes@931 | 319 |
|
nkeynes@931 | 320 | void FASTCALL sh4_write_byte( sh4addr_t addr, uint32_t val )
|
nkeynes@931 | 321 | {
|
nkeynes@931 | 322 | sh4_address_space[addr>>12]->write_byte(addr, val);
|
nkeynes@10 | 323 | }
|
nkeynes@10 | 324 |
|
nkeynes@10 | 325 | /* FIXME: Handle all the many special cases when the range doesn't fall cleanly
|
nkeynes@400 | 326 | * into the same memory block
|
nkeynes@10 | 327 | */
|
nkeynes@912 | 328 | void mem_copy_from_sh4( sh4ptr_t dest, sh4addr_t srcaddr, size_t count ) {
|
nkeynes@103 | 329 | if( srcaddr >= 0x04000000 && srcaddr < 0x05000000 ) {
|
nkeynes@736 | 330 | pvr2_vram64_read( dest, srcaddr, count );
|
nkeynes@103 | 331 | } else {
|
nkeynes@736 | 332 | sh4ptr_t src = mem_get_region(srcaddr);
|
nkeynes@736 | 333 | if( src == NULL ) {
|
nkeynes@736 | 334 | WARN( "Attempted block read from unknown address %08X", srcaddr );
|
nkeynes@736 | 335 | } else {
|
nkeynes@736 | 336 | memcpy( dest, src, count );
|
nkeynes@736 | 337 | }
|
nkeynes@103 | 338 | }
|
nkeynes@10 | 339 | }
|
nkeynes@10 | 340 |
|
nkeynes@912 | 341 | void mem_copy_to_sh4( sh4addr_t destaddr, sh4ptr_t src, size_t count ) {
|
nkeynes@325 | 342 | if( destaddr >= 0x10000000 && destaddr < 0x14000000 ) {
|
nkeynes@736 | 343 | pvr2_dma_write( destaddr, src, count );
|
nkeynes@736 | 344 | return;
|
nkeynes@325 | 345 | } else if( (destaddr & 0x1F800000) == 0x05000000 ) {
|
nkeynes@736 | 346 | pvr2_render_buffer_invalidate( destaddr, TRUE );
|
nkeynes@325 | 347 | } else if( (destaddr & 0x1F800000) == 0x04000000 ) {
|
nkeynes@736 | 348 | pvr2_vram64_write( destaddr, src, count );
|
nkeynes@736 | 349 | return;
|
nkeynes@325 | 350 | }
|
nkeynes@502 | 351 | sh4ptr_t dest = mem_get_region(destaddr);
|
nkeynes@325 | 352 | if( dest == NULL )
|
nkeynes@736 | 353 | WARN( "Attempted block write to unknown address %08X", destaddr );
|
nkeynes@325 | 354 | else {
|
nkeynes@736 | 355 | xlat_invalidate_block( destaddr, count );
|
nkeynes@736 | 356 | memcpy( dest, src, count );
|
nkeynes@90 | 357 | }
|
nkeynes@10 | 358 | }
|