1 |
/* |
/* |
2 |
* Copyright (C) 2003-2005 Anders Gavare. All rights reserved. |
* Copyright (C) 2003-2006 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: memory_rw.c,v 1.80 2005/11/20 11:28:44 debug Exp $ |
* $Id: memory_rw.c,v 1.82 2005/12/31 15:48:32 debug Exp $ |
29 |
* |
* |
30 |
* Generic memory_rw(), with special hacks for specific CPU families. |
* Generic memory_rw(), with special hacks for specific CPU families. |
31 |
* |
* |
83 |
#ifdef MEM_MIPS |
#ifdef MEM_MIPS |
84 |
int bintrans_cached = cpu->machine->bintrans_enable; |
int bintrans_cached = cpu->machine->bintrans_enable; |
85 |
#endif |
#endif |
86 |
int bintrans_device_danger = 0; |
int dyntrans_device_danger = 0; |
87 |
|
|
88 |
no_exceptions = misc_flags & NO_EXCEPTIONS; |
no_exceptions = misc_flags & NO_EXCEPTIONS; |
89 |
cache = misc_flags & CACHE_FLAGS_MASK; |
cache = misc_flags & CACHE_FLAGS_MASK; |
93 |
if (REAL_MODE && !(misc_flags & PHYSICAL)) { |
if (REAL_MODE && !(misc_flags & PHYSICAL)) { |
94 |
if ((vaddr & 0xffff) + len > 0x10000) { |
if ((vaddr & 0xffff) + len > 0x10000) { |
95 |
/* Do one byte at a time: */ |
/* Do one byte at a time: */ |
96 |
int res = 0, i; |
int res = 0; |
97 |
|
size_t i; |
98 |
for (i=0; i<len; i++) |
for (i=0; i<len; i++) |
99 |
res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1, |
res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1, |
100 |
writeflag, misc_flags); |
writeflag, misc_flags); |
109 |
Then do a write of all the new bytes. This is to make sure |
Then do a write of all the new bytes. This is to make sure |
110 |
than both pages around the boundary are writable so we don't |
than both pages around the boundary are writable so we don't |
111 |
do a partial write. */ |
do a partial write. */ |
112 |
int res = 0, i; |
int res = 0; |
113 |
|
size_t i; |
114 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
115 |
unsigned char tmp; |
unsigned char tmp; |
116 |
for (i=0; i<len; i++) { |
for (i=0; i<len; i++) { |
269 |
/* |
/* |
270 |
* Memory mapped device? |
* Memory mapped device? |
271 |
* |
* |
272 |
* TODO: this is utterly slow. |
* TODO: if paddr < base, but len enough, then the device should |
273 |
* TODO2: if paddr<base, but len enough, then we should write |
* still be written to! |
|
* to a device to |
|
274 |
*/ |
*/ |
275 |
if (paddr >= mem->mmap_dev_minaddr && paddr < mem->mmap_dev_maxaddr) { |
if (paddr >= mem->mmap_dev_minaddr && paddr < mem->mmap_dev_maxaddr) { |
276 |
uint64_t orig_paddr = paddr; |
uint64_t orig_paddr = paddr; |
277 |
int i, start, res; |
int i, start, end, res; |
278 |
|
|
279 |
/* |
/* |
280 |
* Really really slow, but unfortunately necessary. This is |
* Really really slow, but unfortunately necessary. This is |
284 |
* b) offsets 0x124..0x777 are a device |
* b) offsets 0x124..0x777 are a device |
285 |
* |
* |
286 |
* 1) a read is done from offset 0x100. the page is |
* 1) a read is done from offset 0x100. the page is |
287 |
* added to the bintrans system as a "RAM" page |
* added to the dyntrans system as a "RAM" page |
288 |
* 2) a bintranslated read is done from offset 0x200, |
* 2) a dyntranslated read is done from offset 0x200, |
289 |
* which should access the device, but since the |
* which should access the device, but since the |
290 |
* entire page is added, it will access non-existant |
* entire page is added, it will access non-existant |
291 |
* RAM instead, without warning. |
* RAM instead, without warning. |
292 |
* |
* |
293 |
* Setting bintrans_device_danger = 1 on accesses which are |
* Setting dyntrans_device_danger = 1 on accesses which are |
294 |
* on _any_ offset on pages that are device mapped avoids |
* on _any_ offset on pages that are device mapped avoids |
295 |
* this problem, but it is probably not very fast. |
* this problem, but it is probably not very fast. |
296 |
|
* |
297 |
|
* TODO: Convert this into a quick (multi-level, 64-bit) |
298 |
|
* address space lookup, to find dangerous pages. |
299 |
*/ |
*/ |
300 |
|
#if 1 |
301 |
for (i=0; i<mem->n_mmapped_devices; i++) |
for (i=0; i<mem->n_mmapped_devices; i++) |
302 |
if (paddr >= (mem->dev_baseaddr[i] & ~offset_mask) && |
if (paddr >= (mem->dev_baseaddr[i] & ~offset_mask) && |
303 |
paddr <= ((mem->dev_endaddr[i]-1) | offset_mask)) { |
paddr <= ((mem->dev_endaddr[i]-1) | offset_mask)) { |
304 |
bintrans_device_danger = 1; |
dyntrans_device_danger = 1; |
305 |
break; |
break; |
306 |
} |
} |
307 |
|
#endif |
308 |
|
|
309 |
i = start = mem->last_accessed_device; |
start = 0; end = mem->n_mmapped_devices - 1; |
310 |
|
i = mem->last_accessed_device; |
311 |
|
|
312 |
/* Scan through all devices: */ |
/* Scan through all devices: */ |
313 |
do { |
do { |
407 |
goto do_return_ok; |
goto do_return_ok; |
408 |
} |
} |
409 |
|
|
410 |
i ++; |
if (paddr < mem->dev_baseaddr[i]) |
411 |
if (i == mem->n_mmapped_devices) |
end = i - 1; |
412 |
i = 0; |
if (paddr >= mem->dev_endaddr[i]) |
413 |
} while (i != start); |
start = i + 1; |
414 |
|
i = (start + end) >> 1; |
415 |
|
} while (start <= end); |
416 |
} |
} |
417 |
|
|
418 |
|
|
578 |
|
|
579 |
offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1); |
offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1); |
580 |
|
|
581 |
if (cpu->update_translation_table != NULL && !bintrans_device_danger |
if (cpu->update_translation_table != NULL && !dyntrans_device_danger |
582 |
#ifndef MEM_MIPS |
#ifndef MEM_MIPS |
583 |
/* && !(misc_flags & MEMORY_USER_ACCESS) */ |
/* && !(misc_flags & MEMORY_USER_ACCESS) */ |
584 |
#ifndef MEM_USERLAND |
#ifndef MEM_USERLAND |