25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: memory.c,v 1.187 2006/01/14 12:51:59 debug Exp $ |
* $Id: memory.c,v 1.190 2006/06/16 18:31:25 debug Exp $ |
29 |
* |
* |
30 |
* Functions for handling the memory of an emulated machine. |
* Functions for handling the memory of an emulated machine. |
31 |
*/ |
*/ |
270 |
void memory_device_dyntrans_access(struct cpu *cpu, struct memory *mem, |
void memory_device_dyntrans_access(struct cpu *cpu, struct memory *mem, |
271 |
void *extra, uint64_t *low, uint64_t *high) |
void *extra, uint64_t *low, uint64_t *high) |
272 |
{ |
{ |
|
int i, j; |
|
273 |
size_t s; |
size_t s; |
274 |
int need_inval = 0; |
int i, need_inval = 0; |
275 |
|
|
276 |
/* TODO: This is O(n), so it might be good to rewrite it some day. |
/* TODO: This is O(n), so it might be good to rewrite it some day. |
277 |
For now, it will be enough, as long as this function is not |
For now, it will be enough, as long as this function is not |
306 |
| INVALIDATE_PADDR); |
| INVALIDATE_PADDR); |
307 |
} |
} |
308 |
|
|
|
if (cpu->machine->arch == ARCH_MIPS) { |
|
|
/* |
|
|
* ... and invalidate the "fast_vaddr_to_ |
|
|
* hostaddr" cache entries that contain |
|
|
* pointers to this device: (NOTE: Device i, |
|
|
* cache entry j) |
|
|
*/ |
|
|
for (j=0; j<N_BINTRANS_VADDR_TO_HOST; j++) { |
|
|
if (cpu->cd. |
|
|
mips.bintrans_data_hostpage[j] >= |
|
|
mem->dev_dyntrans_data[i] && |
|
|
cpu->cd.mips. |
|
|
bintrans_data_hostpage[j] < |
|
|
mem->dev_dyntrans_data[i] + |
|
|
mem->dev_length[i]) |
|
|
cpu->cd.mips. |
|
|
bintrans_data_hostpage[j] |
|
|
= NULL; |
|
|
} |
|
|
} |
|
309 |
return; |
return; |
310 |
} |
} |
311 |
} |
} |
366 |
|
|
367 |
if (verbose >= 2) { |
if (verbose >= 2) { |
368 |
/* (40 bits of physical address is displayed) */ |
/* (40 bits of physical address is displayed) */ |
369 |
debug("device at 0x%010llx: %s", (long long)baseaddr, |
debug("device at 0x%010"PRIx64": %s", (uint64_t) baseaddr, |
370 |
device_name); |
device_name); |
371 |
|
|
372 |
if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK) |
if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK) |
373 |
&& (baseaddr & mem->dev_dyntrans_alignment) != 0) { |
&& (baseaddr & mem->dev_dyntrans_alignment) != 0) { |
374 |
fatal("\nWARNING: Device dyntrans access, but unaligned" |
fatal("\nWARNING: Device dyntrans access, but unaligned" |
375 |
" baseaddr 0x%llx.\n", (long long)baseaddr); |
" baseaddr 0x%"PRIx64".\n", (uint64_t) baseaddr); |
376 |
} |
} |
377 |
|
|
378 |
if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) { |
if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) { |
534 |
table = mem->pagetable; |
table = mem->pagetable; |
535 |
entry = (paddr >> shrcount) & mask; |
entry = (paddr >> shrcount) & mask; |
536 |
|
|
537 |
/* printf("memory_paddr_to_hostaddr(): p=%16llx w=%i => entry=0x%x\n", |
/* printf("memory_paddr_to_hostaddr(): p=%16"PRIx64 |
538 |
(long long)paddr, writeflag, entry); */ |
" w=%i => entry=0x%x\n", (uint64_t) paddr, writeflag, entry); */ |
539 |
|
|
540 |
if (table[entry] == NULL) { |
if (table[entry] == NULL) { |
541 |
size_t alloclen; |
size_t alloclen; |
572 |
return (unsigned char *) table[entry]; |
return (unsigned char *) table[entry]; |
573 |
} |
} |
574 |
|
|
575 |
|
|
576 |
|
#define UPDATE_CHECKSUM(value) { \ |
577 |
|
internal_state -= 0x118c7771c0c0a77fULL; \ |
578 |
|
internal_state = ((internal_state + (value)) << 7) ^ \ |
579 |
|
(checksum >> 11) ^ ((checksum - (value)) << 3) ^ \ |
580 |
|
(internal_state - checksum) ^ ((value) - internal_state); \ |
581 |
|
checksum ^= internal_state; \ |
582 |
|
} |
583 |
|
|
584 |
|
|
585 |
|
/* |
586 |
|
* memory_checksum(): |
587 |
|
* |
588 |
|
* Calculate a 64-bit checksum of everything in a struct memory. This is |
589 |
|
* useful for tracking down bugs; an old (presumably working) version of |
590 |
|
* the emulator can be compared to a newer (buggy) version. |
591 |
|
*/ |
592 |
|
uint64_t memory_checksum(struct memory *mem) |
593 |
|
{ |
594 |
|
uint64_t internal_state = 0x80624185376feff2ULL; |
595 |
|
uint64_t checksum = 0xcb9a87d5c010072cULL; |
596 |
|
const int n_entries = (1 << BITS_PER_PAGETABLE) - 1; |
597 |
|
const size_t len = (1 << BITS_PER_MEMBLOCK) / sizeof(uint64_t); |
598 |
|
size_t entry, i; |
599 |
|
|
600 |
|
for (entry=0; entry<=n_entries; entry++) { |
601 |
|
uint64_t **table = mem->pagetable; |
602 |
|
uint64_t *memblock = table[entry]; |
603 |
|
|
604 |
|
if (memblock == NULL) { |
605 |
|
UPDATE_CHECKSUM(0x1198ab7c8174a76fULL); |
606 |
|
continue; |
607 |
|
} |
608 |
|
|
609 |
|
for (i=0; i<len; i++) |
610 |
|
UPDATE_CHECKSUM(memblock[i]); |
611 |
|
} |
612 |
|
|
613 |
|
return checksum; |
614 |
|
} |
615 |
|
|