Revision cf7055bd
b/target-sh4/helper.c | ||
---|---|---|
43 | 43 |
env->exception_index = 0; |
44 | 44 |
switch (rw) { |
45 | 45 |
case 0: |
46 |
env->tea = address; |
|
47 | 46 |
env->exception_index = 0x0a0; |
48 | 47 |
break; |
49 | 48 |
case 1: |
50 |
env->tea = address; |
|
51 | 49 |
env->exception_index = 0x0c0; |
52 | 50 |
break; |
51 |
case 2: |
|
52 |
env->exception_index = 0x0a0; |
|
53 |
break; |
|
53 | 54 |
} |
54 | 55 |
return 1; |
55 | 56 |
} |
... | ... | |
72 | 73 |
#define MMU_DTLB_VIOLATION_WRITE (-8) |
73 | 74 |
#define MMU_DTLB_MULTIPLE (-9) |
74 | 75 |
#define MMU_DTLB_MISS (-10) |
76 |
#define MMU_IADDR_ERROR (-11) |
|
77 |
#define MMU_DADDR_ERROR_READ (-12) |
|
78 |
#define MMU_DADDR_ERROR_WRITE (-13) |
|
75 | 79 |
|
76 | 80 |
void do_interrupt(CPUState * env) |
77 | 81 |
{ |
... | ... | |
353 | 357 |
Return MMU_OK, MMU_DTLB_MISS_READ, MMU_DTLB_MISS_WRITE, |
354 | 358 |
MMU_DTLB_INITIAL_WRITE, MMU_DTLB_VIOLATION_READ, |
355 | 359 |
MMU_DTLB_VIOLATION_WRITE, MMU_ITLB_MISS, |
356 |
MMU_ITLB_MULTIPLE, MMU_ITLB_VIOLATION |
|
360 |
MMU_ITLB_MULTIPLE, MMU_ITLB_VIOLATION, |
|
361 |
MMU_IADDR_ERROR, MMU_DADDR_ERROR_READ, MMU_DADDR_ERROR_WRITE. |
|
357 | 362 |
*/ |
358 | 363 |
static int get_mmu_address(CPUState * env, target_ulong * physical, |
359 | 364 |
int *prot, target_ulong address, |
360 | 365 |
int rw, int access_type) |
361 | 366 |
{ |
362 |
int use_asid, is_code, n;
|
|
367 |
int use_asid, n; |
|
363 | 368 |
tlb_t *matching = NULL; |
364 | 369 |
|
365 | 370 |
use_asid = (env->mmucr & MMUCR_SV) == 0 || (env->sr & SR_MD) == 0; |
366 |
is_code = env->pc == address; /* Hack */ |
|
367 | 371 |
|
368 |
/* Use a hack to find if this is an instruction or data access */ |
|
369 |
if (env->pc == address && !(rw & PAGE_WRITE)) { |
|
372 |
if (rw == 2) { |
|
370 | 373 |
n = find_itlb_entry(env, address, use_asid, 1); |
371 | 374 |
if (n >= 0) { |
372 | 375 |
matching = &env->itlb[n]; |
... | ... | |
382 | 385 |
switch ((matching->pr << 1) | ((env->sr & SR_MD) ? 1 : 0)) { |
383 | 386 |
case 0: /* 000 */ |
384 | 387 |
case 2: /* 010 */ |
385 |
n = (rw & PAGE_WRITE) ? MMU_DTLB_VIOLATION_WRITE :
|
|
388 |
n = (rw == 1) ? MMU_DTLB_VIOLATION_WRITE :
|
|
386 | 389 |
MMU_DTLB_VIOLATION_READ; |
387 | 390 |
break; |
388 | 391 |
case 1: /* 001 */ |
389 | 392 |
case 4: /* 100 */ |
390 | 393 |
case 5: /* 101 */ |
391 |
if (rw & PAGE_WRITE)
|
|
394 |
if (rw == 1)
|
|
392 | 395 |
n = MMU_DTLB_VIOLATION_WRITE; |
393 | 396 |
else |
394 | 397 |
*prot = PAGE_READ; |
... | ... | |
396 | 399 |
case 3: /* 011 */ |
397 | 400 |
case 6: /* 110 */ |
398 | 401 |
case 7: /* 111 */ |
399 |
*prot = rw & (PAGE_READ | PAGE_WRITE);
|
|
402 |
*prot = (rw == 1)? PAGE_WRITE : PAGE_READ;
|
|
400 | 403 |
break; |
401 | 404 |
} |
402 | 405 |
} else if (n == MMU_DTLB_MISS) { |
403 |
n = (rw & PAGE_WRITE) ? MMU_DTLB_MISS_WRITE :
|
|
406 |
n = (rw == 1) ? MMU_DTLB_MISS_WRITE :
|
|
404 | 407 |
MMU_DTLB_MISS_READ; |
405 | 408 |
} |
406 | 409 |
} |
407 | 410 |
if (n >= 0) { |
408 | 411 |
*physical = ((matching->ppn << 10) & ~(matching->size - 1)) | |
409 | 412 |
(address & (matching->size - 1)); |
410 |
if ((rw & PAGE_WRITE) & !matching->d)
|
|
413 |
if ((rw == 1) & !matching->d)
|
|
411 | 414 |
n = MMU_DTLB_INITIAL_WRITE; |
412 | 415 |
else |
413 | 416 |
n = MMU_OK; |
... | ... | |
426 | 429 |
&& (address < 0xe0000000 || address > 0xe4000000)) { |
427 | 430 |
/* Unauthorized access in user mode (only store queues are available) */ |
428 | 431 |
fprintf(stderr, "Unauthorized access\n"); |
429 |
return (rw & PAGE_WRITE) ? MMU_DTLB_MISS_WRITE : |
|
430 |
MMU_DTLB_MISS_READ; |
|
432 |
if (rw == 0) |
|
433 |
return MMU_DADDR_ERROR_READ; |
|
434 |
else if (rw == 1) |
|
435 |
return MMU_DADDR_ERROR_WRITE; |
|
436 |
else |
|
437 |
return MMU_IADDR_ERROR; |
|
431 | 438 |
} |
432 | 439 |
if (address >= 0x80000000 && address < 0xc0000000) { |
433 | 440 |
/* Mask upper 3 bits for P1 and P2 areas */ |
... | ... | |
465 | 472 |
target_ulong physical, page_offset, page_size; |
466 | 473 |
int prot, ret, access_type; |
467 | 474 |
|
468 |
switch (rw) { |
|
469 |
case 0: |
|
470 |
rw = PAGE_READ; |
|
471 |
break; |
|
472 |
case 1: |
|
473 |
rw = PAGE_WRITE; |
|
474 |
break; |
|
475 |
case 2: /* READ_ACCESS_TYPE == 2 defined in softmmu_template.h */ |
|
476 |
rw = PAGE_READ; |
|
477 |
break; |
|
478 |
default: |
|
479 |
/* fatal error */ |
|
480 |
assert(0); |
|
481 |
} |
|
482 |
|
|
483 |
/* XXXXX */ |
|
484 |
#if 0 |
|
485 |
fprintf(stderr, "%s pc %08x ad %08x rw %d mmu_idx %d smmu %d\n", |
|
486 |
__func__, env->pc, address, rw, mmu_idx, is_softmmu); |
|
487 |
#endif |
|
488 |
|
|
489 | 475 |
access_type = ACCESS_INT; |
490 | 476 |
ret = |
491 | 477 |
get_physical_address(env, &physical, &prot, address, rw, |
... | ... | |
517 | 503 |
case MMU_DTLB_VIOLATION_WRITE: |
518 | 504 |
env->exception_index = 0x0c0; |
519 | 505 |
break; |
506 |
case MMU_IADDR_ERROR: |
|
507 |
case MMU_DADDR_ERROR_READ: |
|
508 |
env->exception_index = 0x0c0; |
|
509 |
break; |
|
510 |
case MMU_DADDR_ERROR_WRITE: |
|
511 |
env->exception_index = 0x100; |
|
512 |
break; |
|
520 | 513 |
default: |
521 | 514 |
assert(0); |
522 | 515 |
} |
... | ... | |
537 | 530 |
target_ulong physical; |
538 | 531 |
int prot; |
539 | 532 |
|
540 |
get_physical_address(env, &physical, &prot, addr, PAGE_READ, 0);
|
|
533 |
get_physical_address(env, &physical, &prot, addr, 0, 0);
|
|
541 | 534 |
return physical; |
542 | 535 |
} |
543 | 536 |
|
Also available in: Unified diff