mirror of https://github.com/proxmox/mirror_qemu
Avoid op helpers that would just call helpers for TLB & SLB management:
call the helpers directly from the micro-ops. Avoid duplicated code for tlbsx. implementation. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3302 c046a42c-6fe2-441c-8c8c-71466251a162master
parent
035feb8857
commit
daf4f96ece
|
@ -656,6 +656,11 @@ void store_40x_sler (CPUPPCState *env, uint32_t val);
|
||||||
void store_booke_tcr (CPUPPCState *env, target_ulong val);
|
void store_booke_tcr (CPUPPCState *env, target_ulong val);
|
||||||
void store_booke_tsr (CPUPPCState *env, target_ulong val);
|
void store_booke_tsr (CPUPPCState *env, target_ulong val);
|
||||||
void ppc_tlb_invalidate_all (CPUPPCState *env);
|
void ppc_tlb_invalidate_all (CPUPPCState *env);
|
||||||
|
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr);
|
||||||
|
#if defined(TARGET_PPC64)
|
||||||
|
void ppc_slb_invalidate_all (CPUPPCState *env);
|
||||||
|
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0);
|
||||||
|
#endif
|
||||||
int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid);
|
int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -100,14 +100,8 @@ void do_raise_exception (uint32_t exception);
|
||||||
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong vaddr,
|
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong vaddr,
|
||||||
int rw, int access_type, int check_BATs);
|
int rw, int access_type, int check_BATs);
|
||||||
|
|
||||||
void ppc6xx_tlb_invalidate_all (CPUState *env);
|
|
||||||
void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
|
|
||||||
int is_code);
|
|
||||||
void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
|
void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
|
||||||
target_ulong pte0, target_ulong pte1);
|
target_ulong pte0, target_ulong pte1);
|
||||||
void ppc4xx_tlb_invalidate_all (CPUState *env);
|
|
||||||
void ppc4xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
|
|
||||||
uint32_t pid);
|
|
||||||
|
|
||||||
static inline void env_to_regs (void)
|
static inline void env_to_regs (void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -237,7 +237,7 @@ static int ppc6xx_tlb_getnum (CPUState *env, target_ulong eaddr,
|
||||||
return nr;
|
return nr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ppc6xx_tlb_invalidate_all (CPUState *env)
|
static void ppc6xx_tlb_invalidate_all (CPUState *env)
|
||||||
{
|
{
|
||||||
ppc6xx_tlb_t *tlb;
|
ppc6xx_tlb_t *tlb;
|
||||||
int nr, max;
|
int nr, max;
|
||||||
|
@ -253,14 +253,9 @@ void ppc6xx_tlb_invalidate_all (CPUState *env)
|
||||||
max *= 2;
|
max *= 2;
|
||||||
for (nr = 0; nr < max; nr++) {
|
for (nr = 0; nr < max; nr++) {
|
||||||
tlb = &env->tlb[nr].tlb6;
|
tlb = &env->tlb[nr].tlb6;
|
||||||
#if !defined(FLUSH_ALL_TLBS)
|
|
||||||
tlb_flush_page(env, tlb->EPN);
|
|
||||||
#endif
|
|
||||||
pte_invalidate(&tlb->pte0);
|
pte_invalidate(&tlb->pte0);
|
||||||
}
|
}
|
||||||
#if defined(FLUSH_ALL_TLBS)
|
|
||||||
tlb_flush(env, 1);
|
tlb_flush(env, 1);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __ppc6xx_tlb_invalidate_virt (CPUState *env,
|
static inline void __ppc6xx_tlb_invalidate_virt (CPUState *env,
|
||||||
|
@ -292,8 +287,8 @@ static inline void __ppc6xx_tlb_invalidate_virt (CPUState *env,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
|
static void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
|
||||||
int is_code)
|
int is_code)
|
||||||
{
|
{
|
||||||
__ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
|
__ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
|
||||||
}
|
}
|
||||||
|
@ -834,11 +829,13 @@ static int ppcemb_tlb_check (CPUState *env, ppcemb_tlb_t *tlb,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
mask = ~(tlb->size - 1);
|
mask = ~(tlb->size - 1);
|
||||||
|
#if defined (DEBUG_SOFTWARE_TLB)
|
||||||
if (loglevel != 0) {
|
if (loglevel != 0) {
|
||||||
fprintf(logfile, "%s: TLB %d address " ADDRX " PID %d <=> "
|
fprintf(logfile, "%s: TLB %d address " ADDRX " PID %d <=> "
|
||||||
ADDRX " " ADDRX " %d\n",
|
ADDRX " " ADDRX " %d\n",
|
||||||
__func__, i, address, pid, tlb->EPN, mask, (int)tlb->PID);
|
__func__, i, address, pid, tlb->EPN, mask, (int)tlb->PID);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* Check PID */
|
/* Check PID */
|
||||||
if (tlb->PID != 0 && tlb->PID != pid)
|
if (tlb->PID != 0 && tlb->PID != pid)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -876,9 +873,23 @@ int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ppc4xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
|
/* Helpers specific to PowerPC 40x implementations */
|
||||||
uint32_t pid)
|
static void ppc4xx_tlb_invalidate_all (CPUState *env)
|
||||||
{
|
{
|
||||||
|
ppcemb_tlb_t *tlb;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < env->nb_tlb; i++) {
|
||||||
|
tlb = &env->tlb[i].tlbe;
|
||||||
|
tlb->prot &= ~PAGE_VALID;
|
||||||
|
}
|
||||||
|
tlb_flush(env, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ppc4xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
|
||||||
|
uint32_t pid)
|
||||||
|
{
|
||||||
|
#if !defined(FLUSH_ALL_TLBS)
|
||||||
ppcemb_tlb_t *tlb;
|
ppcemb_tlb_t *tlb;
|
||||||
target_phys_addr_t raddr;
|
target_phys_addr_t raddr;
|
||||||
target_ulong page, end;
|
target_ulong page, end;
|
||||||
|
@ -894,26 +905,9 @@ void ppc4xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
#else
|
||||||
|
ppc4xx_tlb_invalidate_all(env);
|
||||||
/* Helpers specific to PowerPC 40x implementations */
|
|
||||||
void ppc4xx_tlb_invalidate_all (CPUState *env)
|
|
||||||
{
|
|
||||||
ppcemb_tlb_t *tlb;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < env->nb_tlb; i++) {
|
|
||||||
tlb = &env->tlb[i].tlbe;
|
|
||||||
if (tlb->prot & PAGE_VALID) {
|
|
||||||
#if 0 // XXX: TLB have variable sizes then we flush all Qemu TLB.
|
|
||||||
end = tlb->EPN + tlb->size;
|
|
||||||
for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
|
|
||||||
tlb_flush_page(env, page);
|
|
||||||
#endif
|
#endif
|
||||||
tlb->prot &= ~PAGE_VALID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tlb_flush(env, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
|
int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
|
||||||
|
@ -932,10 +926,12 @@ int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
|
||||||
continue;
|
continue;
|
||||||
zsel = (tlb->attr >> 4) & 0xF;
|
zsel = (tlb->attr >> 4) & 0xF;
|
||||||
zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;
|
zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;
|
||||||
|
#if defined (DEBUG_SOFTWARE_TLB)
|
||||||
if (loglevel != 0) {
|
if (loglevel != 0) {
|
||||||
fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
|
fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
|
||||||
__func__, i, zsel, zpr, rw, tlb->attr);
|
__func__, i, zsel, zpr, rw, tlb->attr);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (access_type == ACCESS_CODE) {
|
if (access_type == ACCESS_CODE) {
|
||||||
/* Check execute enable bit */
|
/* Check execute enable bit */
|
||||||
switch (zpr) {
|
switch (zpr) {
|
||||||
|
@ -1009,19 +1005,23 @@ int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
|
||||||
}
|
}
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
ctx->raddr = raddr;
|
ctx->raddr = raddr;
|
||||||
|
#if defined (DEBUG_SOFTWARE_TLB)
|
||||||
if (loglevel != 0) {
|
if (loglevel != 0) {
|
||||||
fprintf(logfile, "%s: access granted " ADDRX " => " REGX
|
fprintf(logfile, "%s: access granted " ADDRX " => " REGX
|
||||||
" %d %d\n", __func__, address, ctx->raddr, ctx->prot,
|
" %d %d\n", __func__, address, ctx->raddr, ctx->prot,
|
||||||
ret);
|
ret);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if defined (DEBUG_SOFTWARE_TLB)
|
||||||
if (loglevel != 0) {
|
if (loglevel != 0) {
|
||||||
fprintf(logfile, "%s: access refused " ADDRX " => " REGX
|
fprintf(logfile, "%s: access refused " ADDRX " => " REGX
|
||||||
" %d %d\n", __func__, address, raddr, ctx->prot,
|
" %d %d\n", __func__, address, raddr, ctx->prot,
|
||||||
ret);
|
ret);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1569,15 +1569,77 @@ void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
|
||||||
/* TLB management */
|
/* TLB management */
|
||||||
void ppc_tlb_invalidate_all (CPUPPCState *env)
|
void ppc_tlb_invalidate_all (CPUPPCState *env)
|
||||||
{
|
{
|
||||||
if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx)) {
|
switch (env->mmu_model) {
|
||||||
|
case POWERPC_MMU_SOFT_6xx:
|
||||||
ppc6xx_tlb_invalidate_all(env);
|
ppc6xx_tlb_invalidate_all(env);
|
||||||
} else if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_4xx)) {
|
break;
|
||||||
|
case POWERPC_MMU_SOFT_4xx:
|
||||||
|
case POWERPC_MMU_SOFT_4xx_Z:
|
||||||
ppc4xx_tlb_invalidate_all(env);
|
ppc4xx_tlb_invalidate_all(env);
|
||||||
} else {
|
break;
|
||||||
|
default:
|
||||||
tlb_flush(env, 1);
|
tlb_flush(env, 1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
|
||||||
|
{
|
||||||
|
#if !defined(FLUSH_ALL_TLBS)
|
||||||
|
addr &= TARGET_PAGE_MASK;
|
||||||
|
switch (env->mmu_model) {
|
||||||
|
case POWERPC_MMU_SOFT_6xx:
|
||||||
|
ppc6xx_tlb_invalidate_virt(env, addr, 0);
|
||||||
|
if (env->id_tlbs == 1)
|
||||||
|
ppc6xx_tlb_invalidate_virt(env, addr, 1);
|
||||||
|
break;
|
||||||
|
case POWERPC_MMU_SOFT_4xx:
|
||||||
|
case POWERPC_MMU_SOFT_4xx_Z:
|
||||||
|
ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* tlbie invalidate TLBs for all segments */
|
||||||
|
addr &= ~((target_ulong)-1 << 28);
|
||||||
|
/* XXX: this case should be optimized,
|
||||||
|
* giving a mask to tlb_flush_page
|
||||||
|
*/
|
||||||
|
tlb_flush_page(env, addr | (0x0 << 28));
|
||||||
|
tlb_flush_page(env, addr | (0x1 << 28));
|
||||||
|
tlb_flush_page(env, addr | (0x2 << 28));
|
||||||
|
tlb_flush_page(env, addr | (0x3 << 28));
|
||||||
|
tlb_flush_page(env, addr | (0x4 << 28));
|
||||||
|
tlb_flush_page(env, addr | (0x5 << 28));
|
||||||
|
tlb_flush_page(env, addr | (0x6 << 28));
|
||||||
|
tlb_flush_page(env, addr | (0x7 << 28));
|
||||||
|
tlb_flush_page(env, addr | (0x8 << 28));
|
||||||
|
tlb_flush_page(env, addr | (0x9 << 28));
|
||||||
|
tlb_flush_page(env, addr | (0xA << 28));
|
||||||
|
tlb_flush_page(env, addr | (0xB << 28));
|
||||||
|
tlb_flush_page(env, addr | (0xC << 28));
|
||||||
|
tlb_flush_page(env, addr | (0xD << 28));
|
||||||
|
tlb_flush_page(env, addr | (0xE << 28));
|
||||||
|
tlb_flush_page(env, addr | (0xF << 28));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ppc_tlb_invalidate_all(env);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(TARGET_PPC64)
|
||||||
|
void ppc_slb_invalidate_all (CPUPPCState *env)
|
||||||
|
{
|
||||||
|
/* XXX: TODO */
|
||||||
|
tlb_flush(env, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
|
||||||
|
{
|
||||||
|
/* XXX: TODO */
|
||||||
|
tlb_flush(env, 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Special registers manipulation */
|
/* Special registers manipulation */
|
||||||
#if defined(TARGET_PPC64)
|
#if defined(TARGET_PPC64)
|
||||||
|
|
|
@ -1985,21 +1985,21 @@ void OPPROTO op_td (void)
|
||||||
/* tlbia */
|
/* tlbia */
|
||||||
void OPPROTO op_tlbia (void)
|
void OPPROTO op_tlbia (void)
|
||||||
{
|
{
|
||||||
do_tlbia();
|
ppc_tlb_invalidate_all(env);
|
||||||
RETURN();
|
RETURN();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tlbie */
|
/* tlbie */
|
||||||
void OPPROTO op_tlbie (void)
|
void OPPROTO op_tlbie (void)
|
||||||
{
|
{
|
||||||
do_tlbie();
|
ppc_tlb_invalidate_one(env, (uint32_t)T0);
|
||||||
RETURN();
|
RETURN();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(TARGET_PPC64)
|
#if defined(TARGET_PPC64)
|
||||||
void OPPROTO op_tlbie_64 (void)
|
void OPPROTO op_tlbie_64 (void)
|
||||||
{
|
{
|
||||||
do_tlbie_64();
|
ppc_tlb_invalidate_one(env, T0);
|
||||||
RETURN();
|
RETURN();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2007,13 +2007,19 @@ void OPPROTO op_tlbie_64 (void)
|
||||||
#if defined(TARGET_PPC64)
|
#if defined(TARGET_PPC64)
|
||||||
void OPPROTO op_slbia (void)
|
void OPPROTO op_slbia (void)
|
||||||
{
|
{
|
||||||
do_slbia();
|
ppc_slb_invalidate_all(env);
|
||||||
RETURN();
|
RETURN();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_slbie (void)
|
void OPPROTO op_slbie (void)
|
||||||
{
|
{
|
||||||
do_slbie();
|
ppc_slb_invalidate_one(env, (uint32_t)T0);
|
||||||
|
RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OPPROTO op_slbie_64 (void)
|
||||||
|
{
|
||||||
|
ppc_slb_invalidate_one(env, T0);
|
||||||
RETURN();
|
RETURN();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2487,13 +2493,18 @@ void OPPROTO op_440_tlbre (void)
|
||||||
|
|
||||||
void OPPROTO op_440_tlbsx (void)
|
void OPPROTO op_440_tlbsx (void)
|
||||||
{
|
{
|
||||||
do_440_tlbsx();
|
T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF);
|
||||||
RETURN();
|
RETURN();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_440_tlbsx_ (void)
|
void OPPROTO op_4xx_tlbsx_check (void)
|
||||||
{
|
{
|
||||||
do_440_tlbsx_();
|
int tmp;
|
||||||
|
|
||||||
|
tmp = xer_so;
|
||||||
|
if (T0 != -1)
|
||||||
|
tmp |= 0x02;
|
||||||
|
env->crf[0] = tmp;
|
||||||
RETURN();
|
RETURN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2517,13 +2528,7 @@ void OPPROTO op_4xx_tlbre_hi (void)
|
||||||
|
|
||||||
void OPPROTO op_4xx_tlbsx (void)
|
void OPPROTO op_4xx_tlbsx (void)
|
||||||
{
|
{
|
||||||
do_4xx_tlbsx();
|
T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]);
|
||||||
RETURN();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_4xx_tlbsx_ (void)
|
|
||||||
{
|
|
||||||
do_4xx_tlbsx_();
|
|
||||||
RETURN();
|
RETURN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
//#define DEBUG_OP
|
//#define DEBUG_OP
|
||||||
//#define DEBUG_EXCEPTIONS
|
//#define DEBUG_EXCEPTIONS
|
||||||
//#define DEBUG_SOFTWARE_TLB
|
//#define DEBUG_SOFTWARE_TLB
|
||||||
//#define FLUSH_ALL_TLBS
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Exceptions processing helpers */
|
/* Exceptions processing helpers */
|
||||||
|
@ -2336,118 +2335,6 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
|
||||||
env = saved_env;
|
env = saved_env;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TLB invalidation helpers */
|
|
||||||
void do_tlbia (void)
|
|
||||||
{
|
|
||||||
ppc_tlb_invalidate_all(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_tlbie (void)
|
|
||||||
{
|
|
||||||
T0 = (uint32_t)T0;
|
|
||||||
#if !defined(FLUSH_ALL_TLBS)
|
|
||||||
/* XXX: Remove thoses tests */
|
|
||||||
if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx)) {
|
|
||||||
ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 0);
|
|
||||||
if (env->id_tlbs == 1)
|
|
||||||
ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 1);
|
|
||||||
} else if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_4xx)) {
|
|
||||||
ppc4xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK,
|
|
||||||
env->spr[SPR_40x_PID]);
|
|
||||||
} else {
|
|
||||||
/* tlbie invalidate TLBs for all segments */
|
|
||||||
T0 &= TARGET_PAGE_MASK;
|
|
||||||
T0 &= ~((target_ulong)-1 << 28);
|
|
||||||
/* XXX: this case should be optimized,
|
|
||||||
* giving a mask to tlb_flush_page
|
|
||||||
*/
|
|
||||||
tlb_flush_page(env, T0 | (0x0 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x1 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x2 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x3 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x4 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x5 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x6 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x7 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x8 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x9 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0xA << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0xB << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0xC << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0xD << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0xE << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0xF << 28));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
do_tlbia();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(TARGET_PPC64)
|
|
||||||
void do_tlbie_64 (void)
|
|
||||||
{
|
|
||||||
T0 = (uint64_t)T0;
|
|
||||||
#if !defined(FLUSH_ALL_TLBS)
|
|
||||||
if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx)) {
|
|
||||||
ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 0);
|
|
||||||
if (env->id_tlbs == 1)
|
|
||||||
ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 1);
|
|
||||||
} else if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_4xx)) {
|
|
||||||
/* XXX: TODO */
|
|
||||||
#if 0
|
|
||||||
ppcbooke_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK,
|
|
||||||
env->spr[SPR_BOOKE_PID]);
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
/* tlbie invalidate TLBs for all segments
|
|
||||||
* As we have 2^36 segments, invalidate all qemu TLBs
|
|
||||||
*/
|
|
||||||
#if 0
|
|
||||||
T0 &= TARGET_PAGE_MASK;
|
|
||||||
T0 &= ~((target_ulong)-1 << 28);
|
|
||||||
/* XXX: this case should be optimized,
|
|
||||||
* giving a mask to tlb_flush_page
|
|
||||||
*/
|
|
||||||
tlb_flush_page(env, T0 | (0x0 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x1 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x2 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x3 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x4 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x5 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x6 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x7 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x8 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0x9 << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0xA << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0xB << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0xC << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0xD << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0xE << 28));
|
|
||||||
tlb_flush_page(env, T0 | (0xF << 28));
|
|
||||||
#else
|
|
||||||
tlb_flush(env, 1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
do_tlbia();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(TARGET_PPC64)
|
|
||||||
void do_slbia (void)
|
|
||||||
{
|
|
||||||
/* XXX: TODO */
|
|
||||||
tlb_flush(env, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_slbie (void)
|
|
||||||
{
|
|
||||||
/* XXX: TODO */
|
|
||||||
tlb_flush(env, 1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Software driven TLBs management */
|
/* Software driven TLBs management */
|
||||||
/* PowerPC 602/603 software TLB load instructions helpers */
|
/* PowerPC 602/603 software TLB load instructions helpers */
|
||||||
void do_load_6xx_tlb (int is_code)
|
void do_load_6xx_tlb (int is_code)
|
||||||
|
@ -2575,21 +2462,6 @@ void do_4xx_tlbre_hi (void)
|
||||||
T0 |= 0x100;
|
T0 |= 0x100;
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_4xx_tlbsx (void)
|
|
||||||
{
|
|
||||||
T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_4xx_tlbsx_ (void)
|
|
||||||
{
|
|
||||||
int tmp = xer_so;
|
|
||||||
|
|
||||||
T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]);
|
|
||||||
if (T0 != -1)
|
|
||||||
tmp |= 0x02;
|
|
||||||
env->crf[0] = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_4xx_tlbwe_hi (void)
|
void do_4xx_tlbwe_hi (void)
|
||||||
{
|
{
|
||||||
ppcemb_tlb_t *tlb;
|
ppcemb_tlb_t *tlb;
|
||||||
|
@ -2757,21 +2629,6 @@ void do_440_tlbwe (int word)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_440_tlbsx (void)
|
|
||||||
{
|
|
||||||
T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_440_tlbsx_ (void)
|
|
||||||
{
|
|
||||||
int tmp = xer_so;
|
|
||||||
|
|
||||||
T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF);
|
|
||||||
if (T0 != -1)
|
|
||||||
tmp |= 0x02;
|
|
||||||
env->crf[0] = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_440_tlbre (int word)
|
void do_440_tlbre (int word)
|
||||||
{
|
{
|
||||||
ppcemb_tlb_t *tlb;
|
ppcemb_tlb_t *tlb;
|
||||||
|
|
|
@ -4991,10 +4991,9 @@ GEN_HANDLER(tlbsx_40x, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gen_addr_reg_index(ctx);
|
gen_addr_reg_index(ctx);
|
||||||
|
gen_op_4xx_tlbsx();
|
||||||
if (Rc(ctx->opcode))
|
if (Rc(ctx->opcode))
|
||||||
gen_op_4xx_tlbsx_();
|
gen_op_4xx_tlbsx_check();
|
||||||
else
|
|
||||||
gen_op_4xx_tlbsx();
|
|
||||||
gen_op_store_T0_gpr(rD(ctx->opcode));
|
gen_op_store_T0_gpr(rD(ctx->opcode));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -5064,10 +5063,9 @@ GEN_HANDLER(tlbsx_440, 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gen_addr_reg_index(ctx);
|
gen_addr_reg_index(ctx);
|
||||||
|
gen_op_440_tlbsx();
|
||||||
if (Rc(ctx->opcode))
|
if (Rc(ctx->opcode))
|
||||||
gen_op_440_tlbsx_();
|
gen_op_4xx_tlbsx_check();
|
||||||
else
|
|
||||||
gen_op_440_tlbsx();
|
|
||||||
gen_op_store_T0_gpr(rD(ctx->opcode));
|
gen_op_store_T0_gpr(rD(ctx->opcode));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue