target-mips: support Page Frame Number Extension field

Update tlb->PFN to contain PFN concatenated with PFNX. PFNX is 0 if large
physical address is not supported.

Backports commit cd0d45c40133ef8b409aede5ad8a99aeaf6a70fe from qemu
This commit is contained in:
Leon Alrae 2018-02-13 13:49:19 -05:00 committed by Lioncash
parent 95ed79d9c2
commit a13d401fe8
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -1833,6 +1833,16 @@ static void r4k_mips_tlb_flush_extra (CPUMIPSState *env, int first)
}
}
static inline uint64_t get_tlb_pfn_from_entrylo(uint64_t entrylo)
{
#if defined(TARGET_MIPS64)
return extract64(entrylo, 6, 54);
#else
return extract64(entrylo, 6, 24) | /* PFN */
(extract64(entrylo, 32, 32) << 24); /* PFNX */
#endif
}
static void r4k_fill_tlb(CPUMIPSState *env, int idx)
{
r4k_tlb_t *tlb;
@ -1856,13 +1866,13 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1;
tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1;
tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
tlb->PFN[0] = get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) << 12;
tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1;
tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1;
tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
tlb->PFN[1] = get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) << 12;
}
void r4k_helper_tlbinv(CPUMIPSState *env)
@ -1979,6 +1989,16 @@ void r4k_helper_tlbp(CPUMIPSState *env)
}
}
static inline uint64_t get_entrylo_pfn_from_tlb(uint64_t tlb_pfn)
{
#if defined(TARGET_MIPS64)
return tlb_pfn << 6;
#else
return (extract64(tlb_pfn, 0, 24) << 6) | /* PFN */
(extract64(tlb_pfn, 24, 32) << 32); /* PFNX */
#endif
}
void r4k_helper_tlbr(CPUMIPSState *env)
{
r4k_tlb_t *tlb;
@ -2005,12 +2025,12 @@ void r4k_helper_tlbr(CPUMIPSState *env)
env->CP0_PageMask = tlb->PageMask;
env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
((uint64_t)tlb->RI0 << CP0EnLo_RI) |
((uint64_t)tlb->XI0 << CP0EnLo_XI) |
(tlb->C0 << 3) | (tlb->PFN[0] >> 6);
((uint64_t)tlb->XI0 << CP0EnLo_XI) | (tlb->C0 << 3) |
get_entrylo_pfn_from_tlb(tlb->PFN[0] >> 12);
env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
((uint64_t)tlb->RI1 << CP0EnLo_RI) |
((uint64_t)tlb->XI1 << CP0EnLo_XI) |
(tlb->C1 << 3) | (tlb->PFN[1] >> 6);
((uint64_t)tlb->XI1 << CP0EnLo_XI) | (tlb->C1 << 3) |
get_entrylo_pfn_from_tlb(tlb->PFN[1] >> 12);
}
}