25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: memory_rw.c,v 1.65 2005/10/10 18:43:36 debug Exp $ |
* $Id: memory_rw.c,v 1.75 2005/10/27 14:01:12 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 |
* |
* |
310 |
*/ |
*/ |
311 |
for (i=0; i<mem->n_mmapped_devices; i++) |
for (i=0; i<mem->n_mmapped_devices; i++) |
312 |
if (paddr >= (mem->dev_baseaddr[i] & ~offset_mask) && |
if (paddr >= (mem->dev_baseaddr[i] & ~offset_mask) && |
313 |
paddr <= ((mem->dev_baseaddr[i] + |
paddr <= ((mem->dev_endaddr[i]-1) | offset_mask)) { |
|
mem->dev_length[i] - 1) | offset_mask)) { |
|
314 |
bintrans_device_danger = 1; |
bintrans_device_danger = 1; |
315 |
break; |
break; |
316 |
} |
} |
320 |
/* Scan through all devices: */ |
/* Scan through all devices: */ |
321 |
do { |
do { |
322 |
if (paddr >= mem->dev_baseaddr[i] && |
if (paddr >= mem->dev_baseaddr[i] && |
323 |
paddr < mem->dev_baseaddr[i] + mem->dev_length[i]) { |
paddr < mem->dev_endaddr[i]) { |
324 |
/* Found a device, let's access it: */ |
/* Found a device, let's access it: */ |
325 |
mem->last_accessed_device = i; |
mem->last_accessed_device = i; |
326 |
|
|
331 |
if (cpu->update_translation_table != NULL && |
if (cpu->update_translation_table != NULL && |
332 |
mem->dev_flags[i] & MEM_DYNTRANS_OK) { |
mem->dev_flags[i] & MEM_DYNTRANS_OK) { |
333 |
int wf = writeflag == MEM_WRITE? 1 : 0; |
int wf = writeflag == MEM_WRITE? 1 : 0; |
334 |
|
unsigned char *host_addr; |
335 |
|
|
336 |
if (writeflag) { |
if (!(mem->dev_flags[i] & |
337 |
|
MEM_DYNTRANS_WRITE_OK)) |
338 |
|
wf = 0; |
339 |
|
|
340 |
|
if (writeflag && wf) { |
341 |
if (paddr < mem-> |
if (paddr < mem-> |
342 |
dev_dyntrans_write_low[i]) |
dev_dyntrans_write_low[i]) |
343 |
mem-> |
mem-> |
352 |
offset_mask; |
offset_mask; |
353 |
} |
} |
354 |
|
|
355 |
if (!(mem->dev_flags[i] & |
if (mem->dev_flags[i] & |
356 |
MEM_DYNTRANS_WRITE_OK)) |
MEM_EMULATED_RAM) { |
357 |
wf = 0; |
/* MEM_WRITE to force the page |
358 |
|
to be allocated, if it |
359 |
|
wasn't already */ |
360 |
|
uint64_t *pp = (uint64_t *) |
361 |
|
mem->dev_dyntrans_data[i]; |
362 |
|
uint64_t p = orig_paddr - *pp; |
363 |
|
host_addr = |
364 |
|
memory_paddr_to_hostaddr( |
365 |
|
mem, p, MEM_WRITE) |
366 |
|
+ (p & ~offset_mask |
367 |
|
& ((1 << |
368 |
|
BITS_PER_MEMBLOCK) - 1)); |
369 |
|
} else { |
370 |
|
host_addr = |
371 |
|
mem->dev_dyntrans_data[i] + |
372 |
|
(paddr & ~offset_mask); |
373 |
|
} |
374 |
cpu->update_translation_table(cpu, |
cpu->update_translation_table(cpu, |
375 |
vaddr & ~offset_mask, |
vaddr & ~offset_mask, host_addr, |
|
mem->dev_dyntrans_data[i] + |
|
|
(paddr & ~offset_mask), |
|
376 |
wf, orig_paddr & ~offset_mask); |
wf, orig_paddr & ~offset_mask); |
377 |
} |
} |
378 |
|
|
387 |
if (res == 0) |
if (res == 0) |
388 |
res = -1; |
res = -1; |
389 |
|
|
390 |
|
#ifdef MEM_MIPS |
391 |
cpu->cd.mips.instruction_delay += |
cpu->cd.mips.instruction_delay += |
392 |
( (abs(res) - 1) * |
( (abs(res) - 1) * |
393 |
cpu->cd.mips.cpu_type.instrs_per_cycle ); |
cpu->cd.mips.cpu_type.instrs_per_cycle ); |
394 |
#endif |
#endif |
395 |
|
#endif |
396 |
|
|
397 |
#ifndef MEM_X86 |
#ifndef MEM_X86 |
398 |
/* |
/* |
569 |
|
|
570 |
/* |
/* |
571 |
* Uncached access: |
* Uncached access: |
572 |
|
* |
573 |
|
* 1) Translate the physical address to a host address. |
574 |
|
* |
575 |
|
* 2) Insert this virtual->physical->host translation into the |
576 |
|
* fast translation arrays (using update_translation_table()). |
577 |
|
* |
578 |
|
* 3) If this was a Write, then invalidate any code translations |
579 |
|
* in that page. |
580 |
*/ |
*/ |
581 |
memblock = memory_paddr_to_hostaddr(mem, paddr, writeflag); |
memblock = memory_paddr_to_hostaddr(mem, paddr, writeflag); |
582 |
if (memblock == NULL) { |
if (memblock == NULL) { |
588 |
offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1); |
offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1); |
589 |
|
|
590 |
if (cpu->update_translation_table != NULL && !bintrans_device_danger |
if (cpu->update_translation_table != NULL && !bintrans_device_danger |
591 |
|
#ifndef MEM_MIPS |
592 |
|
/* && !(cache_flags & MEMORY_USER_ACCESS) */ |
593 |
|
#ifndef MEM_USERLAND |
594 |
|
&& !(ok & MEMORY_NOT_FULL_PAGE) |
595 |
|
#endif |
596 |
|
#endif |
597 |
&& !no_exceptions) |
&& !no_exceptions) |
598 |
cpu->update_translation_table(cpu, vaddr & ~offset_mask, |
cpu->update_translation_table(cpu, vaddr & ~offset_mask, |
599 |
memblock + (offset & ~offset_mask), |
memblock + (offset & ~offset_mask), |
600 |
|
(cache_flags & MEMORY_USER_ACCESS) | |
601 |
|
#ifndef MEM_MIPS |
602 |
|
(cache == CACHE_INSTRUCTION? TLB_CODE : 0) | |
603 |
|
#endif |
604 |
#if 0 |
#if 0 |
605 |
cache == CACHE_INSTRUCTION? |
(cache == CACHE_INSTRUCTION? |
606 |
(writeflag == MEM_WRITE? 1 : 0) |
(writeflag == MEM_WRITE? 1 : 0) |
607 |
: ok - 1, |
: ok - 1), |
608 |
#else |
#else |
609 |
writeflag == MEM_WRITE? 1 : 0, |
(writeflag == MEM_WRITE? 1 : 0), |
610 |
#endif |
#endif |
611 |
paddr & ~offset_mask); |
paddr & ~offset_mask); |
612 |
|
|
613 |
|
/* Invalidate code translations for the page we are writing to. */ |
614 |
if (writeflag == MEM_WRITE && |
if (writeflag == MEM_WRITE && |
615 |
cpu->invalidate_code_translation != NULL) |
cpu->invalidate_code_translation != NULL) |
616 |
cpu->invalidate_code_translation(cpu, paddr, INVALIDATE_PADDR); |
cpu->invalidate_code_translation(cpu, paddr, INVALIDATE_PADDR); |