Revision 3b1c8be4 target-mips/helper.c
b/target-mips/helper.c | ||
---|---|---|
41 | 41 |
static int map_address (CPUState *env, target_ulong *physical, int *prot, |
42 | 42 |
target_ulong address, int rw, int access_type) |
43 | 43 |
{ |
44 |
target_ulong tag = address & (TARGET_PAGE_MASK << 1); |
|
45 |
uint8_t ASID = env->CP0_EntryHi & 0xFF; |
|
46 |
tlb_t *tlb; |
|
47 |
int i, n; |
|
44 |
int i; |
|
48 | 45 |
|
49 | 46 |
for (i = 0; i < env->tlb_in_use; i++) { |
50 |
tlb = &env->tlb[i]; |
|
47 |
tlb_t *tlb = &env->tlb[i]; |
|
48 |
/* 1k pages are not supported. */ |
|
49 |
uint8_t ASID = env->CP0_EntryHi & 0xFF; |
|
50 |
target_ulong mask = tlb->PageMask | 0x1FFF; |
|
51 |
target_ulong tag = address & ~mask; |
|
52 |
int n; |
|
53 |
|
|
51 | 54 |
/* Check ASID, virtual page number & size */ |
52 | 55 |
if ((tlb->G == 1 || tlb->ASID == ASID) && |
53 | 56 |
tlb->VPN == tag) { |
54 | 57 |
/* TLB match */ |
55 |
n = (address >> TARGET_PAGE_BITS) & 1;
|
|
58 |
n = !!(address & mask & ~(mask >> 1));
|
|
56 | 59 |
/* Check access rights */ |
57 | 60 |
if (!(n ? tlb->V1 : tlb->V0)) |
58 | 61 |
return TLBRET_INVALID; |
59 | 62 |
if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { |
60 |
*physical = tlb->PFN[n] | (address & ~TARGET_PAGE_MASK);
|
|
63 |
*physical = tlb->PFN[n] | (address & (mask >> 1));
|
|
61 | 64 |
*prot = PAGE_READ; |
62 | 65 |
if (n ? tlb->D1 : tlb->D0) |
63 | 66 |
*prot |= PAGE_WRITE; |
... | ... | |
420 | 423 |
void invalidate_tlb (CPUState *env, int idx, int use_extra) |
421 | 424 |
{ |
422 | 425 |
tlb_t *tlb; |
423 |
uint8_t ASID; |
|
424 |
|
|
425 |
ASID = env->CP0_EntryHi & 0xFF; |
|
426 |
target_ulong addr; |
|
427 |
target_ulong end; |
|
428 |
uint8_t ASID = env->CP0_EntryHi & 0xFF; |
|
429 |
target_ulong mask; |
|
426 | 430 |
|
427 | 431 |
tlb = &env->tlb[idx]; |
428 | 432 |
/* The qemu TLB is flushed then the ASID changes, so no need to |
... | ... | |
440 | 444 |
return; |
441 | 445 |
} |
442 | 446 |
|
443 |
if (tlb->V0) |
|
444 |
tlb_flush_page (env, tlb->VPN); |
|
445 |
if (tlb->V1) |
|
446 |
tlb_flush_page (env, tlb->VPN + TARGET_PAGE_SIZE); |
|
447 |
/* 1k pages are not supported. */ |
|
448 |
mask = tlb->PageMask | 0x1FFF; |
|
449 |
if (tlb->V0) { |
|
450 |
addr = tlb->VPN; |
|
451 |
end = addr | (mask >> 1); |
|
452 |
while (addr < end) { |
|
453 |
tlb_flush_page (env, addr); |
|
454 |
addr += TARGET_PAGE_SIZE; |
|
455 |
} |
|
456 |
} |
|
457 |
if (tlb->V1) { |
|
458 |
addr = tlb->VPN | ((mask >> 1) + 1); |
|
459 |
addr = tlb->VPN + TARGET_PAGE_SIZE; |
|
460 |
end = addr | mask; |
|
461 |
while (addr < end) { |
|
462 |
tlb_flush_page (env, addr); |
|
463 |
addr += TARGET_PAGE_SIZE; |
|
464 |
} |
|
465 |
} |
|
447 | 466 |
} |
Also available in: Unified diff