diff options
author | aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-12-06 21:46:17 +0000 |
---|---|---|
committer | aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-12-06 21:46:17 +0000 |
commit | 74d37793f4ea5f30ed6c0af6c449a204dacd8b44 (patch) | |
tree | 2af7cbe375158ea786fa3aa8f2d47974cd989f66 /target-ppc/op_helper.c | |
parent | 331dadde1900247ee90547ce51c620432c5a8f79 (diff) |
target-ppc: convert SLB/TLB instructions to TCG
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5895 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc/op_helper.c')
-rw-r--r-- | target-ppc/op_helper.c | 211 |
1 files changed, 137 insertions, 74 deletions
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 8c9b804716..a4dc41d0c4 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -2552,9 +2552,55 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) env = saved_env; } +/* Segment registers load and store */ +target_ulong helper_load_sr (target_ulong sr_num) +{ + return env->sr[sr_num]; +} + +void helper_store_sr (target_ulong sr_num, target_ulong val) +{ + do_store_sr(env, sr_num, val); +} + +/* SLB management */ +#if defined(TARGET_PPC64) +target_ulong helper_load_slb (target_ulong slb_nr) +{ + return ppc_load_slb(env, slb_nr); +} + +void helper_store_slb (target_ulong slb_nr, target_ulong rs) +{ + ppc_store_slb(env, slb_nr, rs); +} + +void helper_slbia (void) +{ + ppc_slb_invalidate_all(env); +} + +void helper_slbie (target_ulong addr) +{ + ppc_slb_invalidate_one(env, addr); +} + +#endif /* defined(TARGET_PPC64) */ + +/* TLB management */ +void helper_tlbia (void) +{ + ppc_tlb_invalidate_all(env); +} + +void helper_tlbie (target_ulong addr) +{ + ppc_tlb_invalidate_one(env, addr); +} + /* Software driven TLBs management */ /* PowerPC 602/603 software TLB load instructions helpers */ -static void helper_load_6xx_tlb (target_ulong new_EPN, int is_code) +static void do_6xx_tlb (target_ulong new_EPN, int is_code) { target_ulong RPN, CMP, EPN; int way; @@ -2580,18 +2626,18 @@ static void helper_load_6xx_tlb (target_ulong new_EPN, int is_code) way, is_code, CMP, RPN); } -void helper_load_6xx_tlbd (target_ulong EPN) +void helper_6xx_tlbd (target_ulong EPN) { - helper_load_6xx_tlb(EPN, 0); + do_6xx_tlb(EPN, 0); } -void helper_load_6xx_tlbi (target_ulong EPN) +void helper_6xx_tlbi (target_ulong EPN) { - helper_load_6xx_tlb(EPN, 1); + do_6xx_tlb(EPN, 1); } /* PowerPC 74xx software TLB load instructions helpers */ -static void helper_load_74xx_tlb (target_ulong new_EPN, int is_code) +static void do_74xx_tlb (target_ulong new_EPN, int is_code) { target_ulong RPN, CMP, EPN; int way; @@ -2612,14 +2658,14 @@ static void helper_load_74xx_tlb (target_ulong new_EPN, int is_code) way, is_code, CMP, RPN); } -void helper_load_74xx_tlbd (target_ulong EPN) +void helper_74xx_tlbd (target_ulong EPN) { - helper_load_74xx_tlb(EPN, 0); + do_74xx_tlb(EPN, 0); } -void helper_load_74xx_tlbi (target_ulong EPN) +void helper_74xx_tlbi (target_ulong EPN) { - helper_load_74xx_tlb(EPN, 1); + do_74xx_tlb(EPN, 1); } static always_inline target_ulong booke_tlb_to_page_size (int size) @@ -2691,81 +2737,85 @@ static always_inline int booke_page_size_to_tlb (target_ulong page_size) } /* Helpers for 4xx TLB management */ -void do_4xx_tlbre_lo (void) +target_ulong helper_4xx_tlbre_lo (target_ulong entry) { ppcemb_tlb_t *tlb; + target_ulong ret; int size; - T0 &= 0x3F; - tlb = &env->tlb[T0].tlbe; - T0 = tlb->EPN; + entry &= 0x3F; + tlb = &env->tlb[entry].tlbe; + ret = tlb->EPN; if (tlb->prot & PAGE_VALID) - T0 |= 0x400; + ret |= 0x400; size = booke_page_size_to_tlb(tlb->size); if (size < 0 || size > 0x7) size = 1; - T0 |= size << 7; + ret |= size << 7; env->spr[SPR_40x_PID] = tlb->PID; + return ret; } -void do_4xx_tlbre_hi (void) +target_ulong helper_4xx_tlbre_hi (target_ulong entry) { ppcemb_tlb_t *tlb; + target_ulong ret; - T0 &= 0x3F; - tlb = &env->tlb[T0].tlbe; - T0 = tlb->RPN; + entry &= 0x3F; + tlb = &env->tlb[entry].tlbe; + ret = tlb->RPN; if (tlb->prot & PAGE_EXEC) - T0 |= 0x200; + ret |= 0x200; if (tlb->prot & PAGE_WRITE) - T0 |= 0x100; + ret |= 0x100; + return ret; } -void do_4xx_tlbwe_hi (void) +void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val) { ppcemb_tlb_t *tlb; target_ulong page, end; #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { - fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1); + fprintf(logfile, "%s entry " TDX " val " TDX "\n", __func__, entry, val); } #endif - T0 &= 0x3F; - tlb = &env->tlb[T0].tlbe; + entry &= 0x3F; + tlb = &env->tlb[entry].tlbe; /* Invalidate previous TLB (if it's valid) */ if (tlb->prot & PAGE_VALID) { end = tlb->EPN + tlb->size; #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX - " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end); + " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end); } #endif for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) tlb_flush_page(env, page); } - tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7); + tlb->size = booke_tlb_to_page_size((val >> 7) & 0x7); /* We cannot handle TLB size < TARGET_PAGE_SIZE. * If this ever occurs, one should use the ppcemb target instead * of the ppc or ppc64 one */ - if ((T1 & 0x40) && tlb->size < TARGET_PAGE_SIZE) { + if ((val & 0x40) && tlb->size < TARGET_PAGE_SIZE) { cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u " "are not supported (%d)\n", - tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7)); + tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7)); } - tlb->EPN = T1 & ~(tlb->size - 1); - if (T1 & 0x40) + tlb->EPN = val & ~(tlb->size - 1); + if (val & 0x40) tlb->prot |= PAGE_VALID; else tlb->prot &= ~PAGE_VALID; - if (T1 & 0x20) { + if (val & 0x20) { /* XXX: TO BE FIXED */ cpu_abort(env, "Little-endian TLB entries are not supported by now\n"); } tlb->PID = env->spr[SPR_40x_PID]; /* PID */ - tlb->attr = T1 & 0xFF; + tlb->attr = val & 0xFF; #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX @@ -2791,28 +2841,28 @@ void do_4xx_tlbwe_hi (void) } } -void do_4xx_tlbwe_lo (void) +void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val) { ppcemb_tlb_t *tlb; #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { - fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1); + fprintf(logfile, "%s entry " TDX " val " TDX "\n", __func__, entry, val); } #endif - T0 &= 0x3F; - tlb = &env->tlb[T0].tlbe; - tlb->RPN = T1 & 0xFFFFFC00; + entry &= 0x3F; + tlb = &env->tlb[entry].tlbe; + tlb->RPN = val & 0xFFFFFC00; tlb->prot = PAGE_READ; - if (T1 & 0x200) + if (val & 0x200) tlb->prot |= PAGE_EXEC; - if (T1 & 0x100) + if (val & 0x100) tlb->prot |= PAGE_WRITE; #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX " size " ADDRX " prot %c%c%c%c PID %d\n", __func__, - (int)T0, tlb->RPN, tlb->EPN, tlb->size, + (int)entry, tlb->RPN, tlb->EPN, tlb->size, tlb->prot & PAGE_READ ? 'r' : '-', tlb->prot & PAGE_WRITE ? 'w' : '-', tlb->prot & PAGE_EXEC ? 'x' : '-', @@ -2821,8 +2871,13 @@ void do_4xx_tlbwe_lo (void) #endif } +target_ulong helper_4xx_tlbsx (target_ulong address) +{ + return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]); +} + /* PowerPC 440 TLB management */ -void do_440_tlbwe (int word) +void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value) { ppcemb_tlb_t *tlb; target_ulong EPN, RPN, size; @@ -2830,28 +2885,28 @@ void do_440_tlbwe (int word) #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { - fprintf(logfile, "%s word %d T0 " TDX " T1 " TDX "\n", - __func__, word, T0, T1); + fprintf(logfile, "%s word %d entry " TDX " value " TDX "\n", + __func__, word, entry, value); } #endif do_flush_tlbs = 0; - T0 &= 0x3F; - tlb = &env->tlb[T0].tlbe; + entry &= 0x3F; + tlb = &env->tlb[entry].tlbe; switch (word) { default: /* Just here to please gcc */ case 0: - EPN = T1 & 0xFFFFFC00; + EPN = value & 0xFFFFFC00; if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) do_flush_tlbs = 1; tlb->EPN = EPN; - size = booke_tlb_to_page_size((T1 >> 4) & 0xF); + size = booke_tlb_to_page_size((value >> 4) & 0xF); if ((tlb->prot & PAGE_VALID) && tlb->size < size) do_flush_tlbs = 1; tlb->size = size; tlb->attr &= ~0x1; - tlb->attr |= (T1 >> 8) & 1; - if (T1 & 0x200) { + tlb->attr |= (value >> 8) & 1; + if (value & 0x200) { tlb->prot |= PAGE_VALID; } else { if (tlb->prot & PAGE_VALID) { @@ -2864,71 +2919,79 @@ void do_440_tlbwe (int word) tlb_flush(env, 1); break; case 1: - RPN = T1 & 0xFFFFFC0F; + RPN = value & 0xFFFFFC0F; if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) tlb_flush(env, 1); tlb->RPN = RPN; break; case 2: - tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00); + tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00); tlb->prot = tlb->prot & PAGE_VALID; - if (T1 & 0x1) + if (value & 0x1) tlb->prot |= PAGE_READ << 4; - if (T1 & 0x2) + if (value & 0x2) tlb->prot |= PAGE_WRITE << 4; - if (T1 & 0x4) + if (value & 0x4) tlb->prot |= PAGE_EXEC << 4; - if (T1 & 0x8) + if (value & 0x8) tlb->prot |= PAGE_READ; - if (T1 & 0x10) + if (value & 0x10) tlb->prot |= PAGE_WRITE; - if (T1 & 0x20) + if (value & 0x20) tlb->prot |= PAGE_EXEC; break; } } -void do_440_tlbre (int word) +target_ulong helper_440_tlbre (uint32_t word, target_ulong entry) { ppcemb_tlb_t *tlb; + target_ulong ret; int size; - T0 &= 0x3F; - tlb = &env->tlb[T0].tlbe; + entry &= 0x3F; + tlb = &env->tlb[entry].tlbe; switch (word) { default: /* Just here to please gcc */ case 0: - T0 = tlb->EPN; + ret = tlb->EPN; size = booke_page_size_to_tlb(tlb->size); if (size < 0 || size > 0xF) size = 1; - T0 |= size << 4; + ret |= size << 4; if (tlb->attr & 0x1) - T0 |= 0x100; + ret |= 0x100; if (tlb->prot & PAGE_VALID) - T0 |= 0x200; + ret |= 0x200; env->spr[SPR_440_MMUCR] &= ~0x000000FF; env->spr[SPR_440_MMUCR] |= tlb->PID; break; case 1: - T0 = tlb->RPN; + ret = tlb->RPN; break; case 2: - T0 = tlb->attr & ~0x1; + ret = tlb->attr & ~0x1; if (tlb->prot & (PAGE_READ << 4)) - T0 |= 0x1; + ret |= 0x1; if (tlb->prot & (PAGE_WRITE << 4)) - T0 |= 0x2; + ret |= 0x2; if (tlb->prot & (PAGE_EXEC << 4)) - T0 |= 0x4; + ret |= 0x4; if (tlb->prot & PAGE_READ) - T0 |= 0x8; + ret |= 0x8; if (tlb->prot & PAGE_WRITE) - T0 |= 0x10; + ret |= 0x10; if (tlb->prot & PAGE_EXEC) - T0 |= 0x20; + ret |= 0x20; break; } + return ret; } + +target_ulong helper_440_tlbsx (target_ulong address) +{ + return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF); +} + #endif /* !CONFIG_USER_ONLY */ |